diff --git a/src/mumble/GlobalShortcut.cpp b/src/mumble/GlobalShortcut.cpp
index bf777c094..1aa05633a 100644
--- a/src/mumble/GlobalShortcut.cpp
+++ b/src/mumble/GlobalShortcut.cpp
@@ -12,6 +12,7 @@
#include "EnvUtils.h"
#include "MainWindow.h"
#include "ServerHandler.h"
+#include "widgets/EventFilters.h"
#include "Global.h"
#include "GlobalShortcutButtons.h"
@@ -43,43 +44,70 @@ static ConfigRegistrar registrarGlobalShortcut(1200, GlobalShortcutConfigDialogN
static const QString UPARROW = QString::fromUtf8("\xE2\x86\x91 ");
-ShortcutActionWidget::ShortcutActionWidget(QWidget *p) : MUComboBox(p) {
+ShortcutActionWidget::ShortcutActionWidget(QWidget *p) : QWidget(p) {
int idx = 0;
- insertItem(idx, tr("Unassigned"));
- setItemData(idx, -1);
+ m_comboBox = new MUComboBox();
+ m_comboBox->insertItem(idx, tr("Unassigned"));
+ m_comboBox->setItemData(idx, -1);
#ifndef Q_OS_MAC
- setSizeAdjustPolicy(AdjustToContents);
+ m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
#endif
idx++;
+ QFontMetrics fontMetrics = m_comboBox->fontMetrics();
+ int maxWidth = m_comboBox->minimumWidth();
+
foreach (GlobalShortcut *gs, GlobalShortcutEngine::engine->qmShortcuts) {
- insertItem(idx, gs->name);
- setItemData(idx, gs->idx);
- if (!gs->qsToolTip.isEmpty())
- setItemData(idx, gs->qsToolTip, Qt::ToolTipRole);
- if (!gs->qsWhatsThis.isEmpty())
- setItemData(idx, gs->qsWhatsThis, Qt::WhatsThisRole);
+ m_comboBox->insertItem(idx, gs->name);
+ m_comboBox->setItemData(idx, gs->idx);
+ if (!gs->qsToolTip.isEmpty()) {
+ m_comboBox->setItemData(idx, gs->qsToolTip, Qt::ToolTipRole);
+ }
+ if (!gs->qsWhatsThis.isEmpty()) {
+ m_comboBox->setItemData(idx, gs->qsWhatsThis, Qt::WhatsThisRole);
+ }
idx++;
+
+ maxWidth = std::max(maxWidth, fontMetrics.horizontalAdvance(gs->name));
}
// Sort the ShortcutActionWidget items
QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
- proxy->setSourceModel(model());
+ proxy->setSourceModel(m_comboBox->model());
- model()->setParent(proxy);
- setModel(proxy);
+ m_comboBox->model()->setParent(proxy);
+ m_comboBox->setModel(proxy);
- model()->sort(0);
+ m_comboBox->model()->sort(0);
+
+ m_comboBox->setFocusPolicy(Qt::NoFocus);
+
+ setMinimumWidth(maxWidth);
+ m_comboBox->view()->setMinimumWidth(maxWidth);
+ m_comboBox->adjustSize();
+
+ m_comboBox->setParent(this);
+
+ adjustSize();
+
+ KeyEventObserver *eventFilter = new KeyEventObserver(this, QEvent::KeyPress, true, { Qt::Key_Space });
+ connect(eventFilter, &KeyEventObserver::keyEventObserved, this, [=]() { m_comboBox->showPopup(); });
+ installEventFilter(eventFilter);
+
+ QTreeWidget *treeWidget = qobject_cast< QTreeWidget * >(p->parentWidget());
+ if (treeWidget) {
+ treeWidget->resizeColumnToContents(0);
+ }
}
void ShortcutActionWidget::setIndex(unsigned int idx) {
- setCurrentIndex(findData(idx));
+ m_comboBox->setCurrentIndex(m_comboBox->findData(idx));
}
unsigned int ShortcutActionWidget::index() const {
- return itemData(currentIndex()).toUInt();
+ return m_comboBox->itemData(m_comboBox->currentIndex()).toUInt();
}
ShortcutToggleWidget::ShortcutToggleWidget(QWidget *p) : MUComboBox(p) {
@@ -344,6 +372,7 @@ void ShortcutTargetDialog::on_qpbRemove_clicked() {
ShortcutTargetWidget::ShortcutTargetWidget(QWidget *p) : QFrame(p) {
qleTarget = new QLineEdit();
qleTarget->setReadOnly(true);
+ qleTarget->setFocusPolicy(Qt::NoFocus);
qtbEdit = new QToolButton();
qtbEdit->setText(tr("..."));
@@ -355,9 +384,38 @@ ShortcutTargetWidget::ShortcutTargetWidget(QWidget *p) : QFrame(p) {
l->addWidget(qleTarget, 1);
l->addWidget(qtbEdit);
+ KeyEventObserver *eventFilter = new KeyEventObserver(this, QEvent::KeyPress, true, { Qt::Key_Space });
+ connect(eventFilter, &KeyEventObserver::keyEventObserved, this, [=]() { qtbEdit->click(); });
+ installEventFilter(eventFilter);
+
QMetaObject::connectSlotsByName(this);
}
+TextEditWidget::TextEditWidget(QWidget *p) : QWidget(p) {
+ m_lineEdit = new QLineEdit();
+ m_lineEdit->setFocusPolicy(Qt::ClickFocus);
+
+ QHBoxLayout *l = new QHBoxLayout(this);
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+ l->addWidget(m_lineEdit);
+
+ KeyEventObserver *eventFilter = new KeyEventObserver(this, QEvent::KeyPress, true, { Qt::Key_Space });
+ connect(eventFilter, &KeyEventObserver::keyEventObserved, this,
+ [=]() { m_lineEdit->setFocus(Qt::MouseFocusReason); });
+ installEventFilter(eventFilter);
+
+ QMetaObject::connectSlotsByName(this);
+}
+
+QString TextEditWidget::currentString() const {
+ return m_lineEdit->text();
+}
+
+void TextEditWidget::setCurrentString(const QString &str) {
+ m_lineEdit->setText(str);
+}
+
/**
* This function returns a textual representation of the given shortcut target st.
*/
@@ -461,7 +519,7 @@ ShortcutDelegate::ShortcutDelegate(QObject *p) : QStyledItemDelegate(p) {
new QStandardItemEditorCreator< ShortcutTargetWidget >());
factory->registerEditor(static_cast< int >(QVariant::fromValue(ChannelTarget()).userType()),
new QStandardItemEditorCreator< ChannelSelectWidget >());
- factory->registerEditor(QVariant::String, new QStandardItemEditorCreator< QLineEdit >());
+ factory->registerEditor(QVariant::String, new QStandardItemEditorCreator< TextEditWidget >());
factory->registerEditor(QVariant::Invalid, new QStandardItemEditorCreator< QWidget >());
setItemEditorFactory(factory);
}
@@ -556,11 +614,16 @@ GlobalShortcutConfig::GlobalShortcutConfig(Settings &st) : ConfigWidget(st) {
qtwShortcuts->setColumnCount(canSuppress ? 4 : 3);
qtwShortcuts->setItemDelegate(new ShortcutDelegate(qtwShortcuts));
+ qtwShortcuts->headerItem()->setData(0, Qt::AccessibleTextRole, tr("Shortcut action"));
+ qtwShortcuts->headerItem()->setData(1, Qt::AccessibleTextRole, tr("Shortcut data"));
+ qtwShortcuts->headerItem()->setData(2, Qt::AccessibleTextRole, tr("Shortcut input combinations"));
+
qtwShortcuts->header()->setSectionResizeMode(0, QHeaderView::Fixed);
qtwShortcuts->header()->resizeSection(0, 150);
qtwShortcuts->header()->setSectionResizeMode(2, QHeaderView::Stretch);
- if (canSuppress)
+ if (canSuppress) {
qtwShortcuts->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
+ }
qcbEnableGlobalShortcuts->setVisible(canDisable);
@@ -670,6 +733,7 @@ void GlobalShortcutConfig::on_qpbAdd_clicked(bool) {
sc.bSuppress = false;
qlShortcuts << sc;
reload();
+ qtwShortcuts->setFocus(Qt::TabFocusReason);
}
void GlobalShortcutConfig::on_qpbRemove_clicked(bool) {
@@ -705,6 +769,17 @@ void GlobalShortcutConfig::on_qtwShortcuts_itemChanged(QTreeWidgetItem *item, in
if (gs && sc.qvData.userType() != gs->qvDefault.userType()) {
item->setData(1, Qt::DisplayRole, gs->qvDefault);
}
+
+ if (gs) {
+ item->setData(0, Qt::AccessibleTextRole, gs->name);
+ } else {
+ item->setData(0, Qt::AccessibleTextRole, tr("Unassigned"));
+ }
+ item->setData(1, Qt::AccessibleTextRole, sc.qvData);
+ item->setData(3, Qt::AccessibleDescriptionRole,
+ item->checkState(3) == Qt::Checked ? tr("checked") : tr("unchecked"));
+
+ qtwShortcuts->resizeColumnToContents(0);
}
QString GlobalShortcutConfig::title() const {
@@ -811,6 +886,7 @@ void GlobalShortcutConfig::reload() {
foreach (const Shortcut &sc, qlShortcuts) {
QTreeWidgetItem *item = itemForShortcut(sc);
qtwShortcuts->addTopLevelItem(item);
+ on_qtwShortcuts_itemChanged(item, 0);
}
#ifdef Q_OS_MAC
if (!Global::get().s.bSuppressMacEventTapWarning) {
diff --git a/src/mumble/GlobalShortcut.h b/src/mumble/GlobalShortcut.h
index 64b9dbfc3..d7a9f35e0 100644
--- a/src/mumble/GlobalShortcut.h
+++ b/src/mumble/GlobalShortcut.h
@@ -51,11 +51,14 @@ public:
*
* @see GlobalShortcutEngine
*/
-class ShortcutActionWidget : public MUComboBox {
+class ShortcutActionWidget : public QWidget {
private:
Q_OBJECT
Q_DISABLE_COPY(ShortcutActionWidget)
Q_PROPERTY(unsigned int index READ index WRITE setIndex USER true)
+
+ MUComboBox *m_comboBox;
+
public:
ShortcutActionWidget(QWidget *p = nullptr);
unsigned int index() const;
@@ -84,6 +87,20 @@ public:
void setCurrentChannel(const ChannelTarget &);
};
+class TextEditWidget : public QWidget {
+private:
+ Q_OBJECT
+ Q_DISABLE_COPY(TextEditWidget)
+ Q_PROPERTY(QString currentString READ currentString WRITE setCurrentString USER true)
+
+ QLineEdit *m_lineEdit;
+
+public:
+ TextEditWidget(QWidget *p = nullptr);
+ QString currentString() const;
+ void setCurrentString(const QString &);
+};
+
/**
* Dialog which is used to select the targets of a targeted shortcut like Whisper.
*/
diff --git a/src/mumble/GlobalShortcut.ui b/src/mumble/GlobalShortcut.ui
index f8d072cf4..8b4063289 100644
--- a/src/mumble/GlobalShortcut.ui
+++ b/src/mumble/GlobalShortcut.ui
@@ -124,13 +124,16 @@
-
-
+
List of configured shortcuts
Configured shortcuts
+
+ Use up and down keys to navigate through your added shortcuts. Use left and right keys to navigate between actions and options for a single shortcut. Entries can be added and deleted with the buttons below.
+
QAbstractItemView::AllEditTriggers
@@ -186,6 +189,12 @@
This will add a new global shortcut
+
+ Add unassigned shortcut
+
+
+ This adds a new empty entry to the "Configured Shortcut" tree above. The tree will be automatically focused. Assign a key or an action by selecting the entry in the tree above.
+
&Add
@@ -202,6 +211,12 @@
This will permanently remove a selected shortcut.
+
+ Remove selected shortcut
+
+
+ This removes the selected entry from the "Configured Shortcut" tree above
+
&Remove
@@ -271,6 +286,13 @@ Without this option enabled, using Mumble's global shortcuts in privileged appli
+
+
+ MultiColumnTreeWidget
+ QTreeWidget
+ widgets/MultiColumnTreeWidget.h
+
+
diff --git a/src/mumble/GlobalShortcutButtons.cpp b/src/mumble/GlobalShortcutButtons.cpp
index d96bc06fb..931033f24 100644
--- a/src/mumble/GlobalShortcutButtons.cpp
+++ b/src/mumble/GlobalShortcutButtons.cpp
@@ -10,6 +10,8 @@
#include "Global.h"
+#include
+
GlobalShortcutButtons::GlobalShortcutButtons(QWidget *parent) : QDialog(parent), m_ui(new Ui::GlobalShortcutButtons) {
m_ui->setupUi(this);
@@ -50,6 +52,16 @@ void GlobalShortcutButtons::setButtons(const QList< QVariant > &buttons) {
}
adjustSize();
+
+ // Without this the new dialog window will not be focused and the
+ // shortcut edit dialog is closed when TAB is pressed...
+ // Due to Qt action processing weirdness the timer is needed, otherwise
+ // the call has no effect.
+ if (buttons.isEmpty()) {
+ QTimer::singleShot(0, [&]() { m_ui->addButton->setFocus(Qt::TabFocusReason); });
+ } else {
+ QTimer::singleShot(0, [&]() { m_ui->buttonTree->setFocus(Qt::TabFocusReason); });
+ }
}
void GlobalShortcutButtons::addItem(const QVariant &button) {