File 0955-shortcut-configuration.patch of Package OpenBoard

From 07141652f2bcd3eba16fb5291532b52e8b530fc0 Mon Sep 17 00:00:00 2001
From: letsfindaway <me@letsfindaway.de>
Date: Sun, 25 Aug 2024 15:34:04 +0200
Subject: [PATCH 1/2] feat: add preferences dialog for shortcut configuration

- recording of key sequences amd mouse/stylus buttons
- collect actions, filtering, collision detection
- persist shortcut settings
---
 resources/forms/preferences.ui       | 169 ++++++++++++++++++
 src/core/UBApplication.cpp           |  28 +++
 src/core/UBPreferencesController.cpp | 252 ++++++++++++++++++++++++++-
 src/core/UBPreferencesController.h   |  12 ++
 4 files changed, 459 insertions(+), 2 deletions(-)

diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui
index 45a2fc180..9b73f8d65 100644
--- a/resources/forms/preferences.ui
+++ b/resources/forms/preferences.ui
@@ -1095,6 +1095,175 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="shortcutTab">
+      <attribute name="title">
+       <string>Shortcut</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QLineEdit" name="filter">
+         <property name="placeholderText">
+          <string>Filter</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QScrollArea" name="shortcutScrollArea">
+         <property name="widgetResizable">
+          <bool>true</bool>
+         </property>
+         <widget class="QWidget" name="scrollAreaWidgetContents">
+          <property name="geometry">
+           <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>789</width>
+            <height>447</height>
+           </rect>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_41">
+           <item>
+            <widget class="QTableView" name="shortcutTableView">
+             <property name="editTriggers">
+              <set>QAbstractItemView::NoEditTriggers</set>
+             </property>
+             <property name="showDropIndicator" stdset="0">
+              <bool>false</bool>
+             </property>
+             <property name="selectionMode">
+              <enum>QAbstractItemView::SingleSelection</enum>
+             </property>
+             <property name="selectionBehavior">
+              <enum>QAbstractItemView::SelectRows</enum>
+             </property>
+             <property name="showGrid">
+              <bool>false</bool>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <attribute name="horizontalHeaderCascadingSectionResizes">
+              <bool>true</bool>
+             </attribute>
+             <attribute name="verticalHeaderVisible">
+              <bool>false</bool>
+             </attribute>
+             <attribute name="verticalHeaderMinimumSectionSize">
+              <number>25</number>
+             </attribute>
+             <attribute name="verticalHeaderDefaultSectionSize">
+              <number>25</number>
+             </attribute>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_11">
+         <item>
+          <widget class="QCheckBox" name="noCtrl">
+           <property name="text">
+            <string>Active keyboard shortcuts without pressing Ctrl key</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="shortcutsGroupBox">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="title">
+          <string>Shortcuts</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_20">
+          <item row="3" column="0" colspan="2">
+           <widget class="QLabel" name="report">
+            <property name="styleSheet">
+             <string notr="true">color: red;</string>
+            </property>
+            <property name="textFormat">
+             <enum>Qt::PlainText</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QLineEdit" name="stylusButton">
+            <property name="readOnly">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QPushButton" name="abortButton">
+            <property name="text">
+             <string>Abort</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QPushButton" name="recordButton">
+            <property name="text">
+             <string>Record</string>
+            </property>
+            <property name="checkable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="label_5">
+            <property name="text">
+             <string>Stylus Button</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="label_2">
+            <property name="text">
+             <string>Mouse Button</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLineEdit" name="mouseButton">
+            <property name="readOnly">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QLineEdit" name="keySequence">
+            <property name="readOnly">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="2">
+           <widget class="QPushButton" name="resetButton">
+            <property name="text">
+             <string>Reset</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_4">
+            <property name="text">
+             <string>Key Sequence</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
      <widget class="QWidget" name="thirdPartyLicence">
       <property name="enabled">
        <bool>true</bool>
diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp
index 9e74e09a3..44017610b 100644
--- a/src/core/UBApplication.cpp
+++ b/src/core/UBApplication.cpp
@@ -704,6 +704,34 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event)
                     || result;
     }
 
+    else if (event->type() == QEvent::MouseButtonPress)
+    {
+        // intercept special mouse buttons for shortcut handler
+        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
+        Qt::MouseButton button = mouseEvent->button();
+
+        if (button != Qt::LeftButton && button != Qt::RightButton)
+        {
+            return mPreferencesController->handleMouseEvent(mouseEvent)
+                    || UBShortcutManager::shortcutManager()->handleMouseEvent(mouseEvent)
+                    || result;
+        }
+    }
+
+    else if (event->type() == QEvent::TabletPress)
+    {
+        // intercept special tablet buttons for shortcut handler
+        QTabletEvent *tabletEvent = static_cast<QTabletEvent *>(event);
+        Qt::MouseButton button = tabletEvent->button();
+
+        if (button != Qt::LeftButton)
+        {
+            return mPreferencesController->handleTabletEvent(tabletEvent)
+                    || UBShortcutManager::shortcutManager()->handleTabletEvent(tabletEvent)
+                    || result;
+        }
+    }
+
     return result;
 }
 
diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp
index ed0e393d8..145323385 100644
--- a/src/core/UBPreferencesController.cpp
+++ b/src/core/UBPreferencesController.cpp
@@ -37,6 +37,7 @@
 #include "core/UBSetting.h"
 #include "core/UBApplicationController.h"
 #include "core/UBDisplayManager.h"
+#include "core/UBShortcutManager.h"
 
 #include "frameworks/UBStringUtils.h"
 
@@ -72,7 +73,6 @@ void UBPreferencesDialog::closeEvent(QCloseEvent* e)
 }
 
 
-
 UBPreferencesController::UBPreferencesController(QWidget *parent)
     : QObject(parent)
     , mPreferencesWindow(0)
@@ -88,6 +88,8 @@ UBPreferencesController::UBPreferencesController(QWidget *parent)
     adjustScreensPreferences();
 
     connect(UBApplication::displayManager, &UBDisplayManager::availableScreenCountChanged, this, &UBPreferencesController::adjustScreensPreferences);
+    mPreferencesUI->shortcutTab->installEventFilter(this);
+
     wire();
 }
 
@@ -103,6 +105,90 @@ UBPreferencesController::~UBPreferencesController()
     delete mMarkerProperties;
 }
 
+bool UBPreferencesController::handleKeyEvent(QKeyEvent *event)
+{
+    if (!mPreferencesUI->recordButton->isChecked()
+            || mPreferencesUI->mainTabWidget->currentWidget() != mPreferencesUI->shortcutTab)
+    {
+        return false;
+    }
+
+    int key = event->key();
+    Qt::KeyboardModifiers mods = event->modifiers();
+    QString text = event->text();
+
+    int keys = mods;
+
+    if (key < Qt::Key_Shift || key > Qt::Key_ScrollLock)
+    {
+        keys += key;
+    }
+
+    // compose key sequence from active modifiers and key
+    QKeySequence keySequence(keys);
+    QString keyString = keySequence.toString();
+    mPreferencesUI->keySequence->setText(keyString);
+
+    if (currentIndex.isValid())
+    {
+        bool ok = UBShortcutManager::shortcutManager()->checkData(currentIndex.siblingAtColumn(2), keyString);
+        applyShortcutFilter(ok ? mPreferencesUI->filter->text() : keyString, ok ? -1 : 2);
+        mPreferencesUI->recordButton->setEnabled(ok);
+        mPreferencesUI->report->setText(ok ? "" : tr("Key sequence already in use"));
+        mPreferencesUI->noCtrl->setEnabled(!UBShortcutManager::shortcutManager()->hasCtrlConflicts(keySequence));
+    }
+
+    return true;
+}
+
+bool UBPreferencesController::handleMouseEvent(QMouseEvent *event)
+{
+    if (!mPreferencesUI->recordButton->isChecked()
+            || mPreferencesUI->mainTabWidget->currentWidget() != mPreferencesUI->shortcutTab)
+    {
+        return false;
+    }
+
+    Qt::MouseButton button = event->button();
+
+    if (currentIndex.isValid())
+    {
+        QString buttonName = UBShortcutManager::buttonName(button);
+        mPreferencesUI->mouseButton->setText(buttonName);
+        bool ok = UBShortcutManager::shortcutManager()->checkData(currentIndex.siblingAtColumn(3), buttonName);
+        applyShortcutFilter(ok ? mPreferencesUI->filter->text() : buttonName, ok ? -1 : 3);
+        mPreferencesUI->recordButton->setEnabled(ok);
+        mPreferencesUI->report->setText(ok ? "" : tr("Mouse button already in use"));
+        return true;
+    }
+
+    return false;
+}
+
+bool UBPreferencesController::handleTabletEvent(QTabletEvent *event)
+{
+    if (!mPreferencesUI->recordButton->isChecked()
+            || mPreferencesUI->mainTabWidget->currentWidget() != mPreferencesUI->shortcutTab)
+    {
+        return false;
+    }
+
+    Qt::MouseButton button = event->button();
+
+    if (currentIndex.isValid())
+    {
+        QString buttonName = UBShortcutManager::buttonName(button);
+        mPreferencesUI->stylusButton->setText(buttonName);
+        bool ok = UBShortcutManager::shortcutManager()->checkData(currentIndex.siblingAtColumn(4), buttonName);
+        applyShortcutFilter(ok ? mPreferencesUI->filter->text() : buttonName, ok ? -1 : 4);
+        mPreferencesUI->recordButton->setEnabled(ok);
+        mPreferencesUI->report->setText(ok ? "" : tr("Stylus button already in use"));
+        return true;
+    }
+
+    return false;
+}
+
 void UBPreferencesController::adjustScreensPreferences()
 {
     bool enabled = UBApplication::displayManager->numScreens() > 1;
@@ -139,6 +225,50 @@ void UBPreferencesController::adjustScreensPreferences()
     }
 }
 
+void UBPreferencesController::applyShortcutFilter(const QString &filter, int filterCol)
+{
+    // go throug rows in reverse direction
+    QAbstractItemModel* model = mPreferencesUI->shortcutTableView->model();
+    QModelIndex index = model->index(0, 0);
+    bool groupVisible = false;
+    int minCol = filterCol < 0 ? 0 : filterCol;
+    int maxCol = filterCol < 0 ? model->columnCount() : filterCol + 1;
+
+    for (int row = model->rowCount() - 1; row >= 0; --row)
+    {
+        QModelIndex rowIndex = index.siblingAtRow(row);
+        bool match = false;
+        bool header = model->data(rowIndex, UBShortcutManager::GroupHeaderRole).toBool();
+
+        if (header)
+        {
+            match = groupVisible;
+            groupVisible = false;
+        }
+        else if (currentIndex.isValid() && currentIndex.row() == row)
+        {
+            match = true;
+            groupVisible = true;
+        }
+        else
+        {
+            for (int col = minCol; col < maxCol; ++col)
+            {
+                QModelIndex colIndex = rowIndex.siblingAtColumn(col);
+
+                if (model->data(colIndex).toString().contains(filter, Qt::CaseInsensitive))
+                {
+                    match = true;
+                    groupVisible = true;
+                    break;
+                }
+            }
+        }
+
+        mPreferencesUI->shortcutTableView->setRowHidden(row, !match);
+    }
+}
+
 void UBPreferencesController::show()
 {
     init();
@@ -293,6 +423,21 @@ void UBPreferencesController::wire()
 
     // about tab
     connect(mPreferencesUI->checkSoftwareUpdateAtLaunchCheckBox, SIGNAL(clicked(bool)), settings->appEnableAutomaticSoftwareUpdates, SLOT(setBool(bool)));
+
+    // shortcut tab
+    connect(mPreferencesUI->shortcutTableView, SIGNAL(activated(const QModelIndex&)), this, SLOT(actionSelected(const QModelIndex&)));
+    connect(mPreferencesUI->filter, SIGNAL(textChanged(const QString&)), this, SLOT(applyShortcutFilter(const QString&)));
+    connect(mPreferencesUI->recordButton, SIGNAL(clicked(bool)), this, SLOT(recordingClicked(bool)));
+    connect(mPreferencesUI->abortButton, SIGNAL(clicked()), this, SLOT(abortClicked()));
+    connect(mPreferencesUI->resetButton, SIGNAL(clicked()), this, SLOT(resetClicked()));
+    connect(mPreferencesUI->noCtrl, &QCheckBox::toggled, UBShortcutManager::shortcutManager(), &UBShortcutManager::ignoreCtrl);
+    connect(mPreferencesUI->mainTabWidget, &QTabWidget::currentChanged, [this](int tab){
+        auto shortcutTab = mPreferencesUI->mainTabWidget->indexOf(mPreferencesUI->shortcutTab);
+
+        if (tab != shortcutTab) {
+            abortClicked();
+        }
+    });
 }
 
 void UBPreferencesController::init()
@@ -351,6 +496,27 @@ void UBPreferencesController::init()
 
     mMarkerProperties->opacitySlider->setValue(settings->boardMarkerAlpha->get().toDouble() * 100);
 
+    // shortcut tab
+    mPreferencesUI->shortcutTableView->setModel(UBShortcutManager::shortcutManager());
+    mPreferencesUI->shortcutTableView->horizontalHeader()->setModel(UBShortcutManager::shortcutManager());
+    mPreferencesUI->shortcutTableView->horizontalHeader()->resizeSection(0, 150);
+    mPreferencesUI->shortcutTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
+    mPreferencesUI->noCtrl->setChecked(settings->value("Shortcut/IgnoreCtrl").toBool());
+    mPreferencesUI->noCtrl->setEnabled(!UBShortcutManager::shortcutManager()->hasCtrlConflicts());
+}
+
+bool UBPreferencesController::eventFilter(QObject *obj, QEvent *event)
+{
+    if (event->type() == QEvent::KeyPress)
+    {
+        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+        return handleKeyEvent(keyEvent);
+    }
+    else
+    {
+        // standard event processing
+        return QObject::eventFilter(obj, event);
+    }
 }
 
 void UBPreferencesController::close()
@@ -445,7 +611,8 @@ void UBPreferencesController::defaultSettings()
         mPreferencesUI->checkSoftwareUpdateAtLaunchCheckBox->setChecked(defaultValue);
 
     }
-    else if(mPreferencesUI->mainTabWidget->currentWidget() == mPreferencesUI->networkTab){
+    else if(mPreferencesUI->mainTabWidget->currentWidget() == mPreferencesUI->networkTab)
+    {
         bool defaultValue = settings->webUseExternalBrowser->reset().toBool();
         mPreferencesUI->useExternalBrowserCheckBox->setChecked(defaultValue);
         defaultValue = settings->webShowPageImmediatelyOnMirroredScreen->reset().toBool();
@@ -480,6 +647,23 @@ void UBPreferencesController::defaultSettings()
         lightBackgroundCrossOpacityValueChanged(lightBackgroundOpacity);
 
     }
+    else if(mPreferencesUI->mainTabWidget->currentWidget() == mPreferencesUI->shortcutTab)
+    {
+        if (mPreferencesUI->recordButton->isChecked())
+        {
+            abortClicked();
+        }
+
+        UBShortcutManager* sm = UBShortcutManager::shortcutManager();
+
+        for (int row = 0; row < sm->rowCount(); ++row)
+        {
+            QModelIndex rowIndex = sm->index(row, 0);
+            sm->resetData(rowIndex);
+        }
+
+        resetClicked();
+    }
 }
 
 void UBPreferencesController::darkBackgroundCrossOpacityValueChanged(int value)
@@ -690,6 +874,70 @@ void UBPreferencesController::systemOSKCheckBoxToggled(bool checked)
     mPreferencesUI->keyboardPaletteKeyButtonSize_Label->setVisible(!checked);
 }
 
+void UBPreferencesController::actionSelected(const QModelIndex &index)
+{
+    currentIndex = index;
+    UBShortcutManager* sm = UBShortcutManager::shortcutManager();
+    mPreferencesUI->keySequence->setText(sm->data(index.siblingAtColumn(2), UBShortcutManager::PrimaryShortcutRole).toString());
+    mPreferencesUI->mouseButton->setText(sm->data(index.siblingAtColumn(3)).toString());
+    mPreferencesUI->stylusButton->setText(sm->data(index.siblingAtColumn(4)).toString());
+
+    bool isAction = sm->data(index, UBShortcutManager::ActionRole).toBool();
+    mPreferencesUI->recordButton->setEnabled(true);
+    mPreferencesUI->shortcutsGroupBox->setEnabled(isAction);
+}
+
+void UBPreferencesController::recordingClicked(bool checked)
+{
+    if (!checked && currentIndex.isValid())
+    {
+        UBShortcutManager* sm = UBShortcutManager::shortcutManager();
+        sm->setData(currentIndex.siblingAtColumn(2), mPreferencesUI->keySequence->text());
+        sm->setData(currentIndex.siblingAtColumn(3), sm->buttonIndex(mPreferencesUI->mouseButton->text()));
+        sm->setData(currentIndex.siblingAtColumn(4), sm->buttonIndex(mPreferencesUI->stylusButton->text()));
+    }
+
+    mPreferencesUI->shortcutTableView->setSelectionMode(checked ? QTableView::NoSelection : QTableView::SingleSelection);
+    mPreferencesUI->recordButton->setText(checked ? tr("Accept", "preferencesDialog") : tr("Record", "preferencesDialog"));
+}
+
+void UBPreferencesController::abortClicked()
+{
+    applyShortcutFilter(mPreferencesUI->filter->text());
+
+    mPreferencesUI->recordButton->setEnabled(true);
+    mPreferencesUI->recordButton->setChecked(false);
+    mPreferencesUI->recordButton->setText(tr("Record", "preferencesDialog"));
+    mPreferencesUI->shortcutTableView->setSelectionMode(QTableView::SingleSelection);
+    mPreferencesUI->shortcutTableView->clearSelection();
+    mPreferencesUI->report->setText("");
+    mPreferencesUI->noCtrl->setEnabled(!UBShortcutManager::shortcutManager()->hasCtrlConflicts());
+    actionSelected(mPreferencesUI->shortcutTableView->model()->index(0, 0));
+}
+
+void UBPreferencesController::resetClicked()
+{
+    if (mPreferencesUI->recordButton->isChecked())
+    {
+        abortClicked();
+    }
+
+    if (currentIndex.isValid())
+    {
+        UBShortcutManager* sm = UBShortcutManager::shortcutManager();
+
+        sm->resetData(currentIndex);
+        applyShortcutFilter(mPreferencesUI->filter->text());
+
+        mPreferencesUI->keySequence->setText(sm->data(currentIndex.siblingAtColumn(2)).toString());
+        mPreferencesUI->mouseButton->setText(sm->data(currentIndex.siblingAtColumn(3)).toString());
+        mPreferencesUI->stylusButton->setText(sm->data(currentIndex.siblingAtColumn(4)).toString());
+    }
+
+    mPreferencesUI->report->setText("");
+    mPreferencesUI->noCtrl->setEnabled(!UBShortcutManager::shortcutManager()->hasCtrlConflicts());
+}
+
 UBBrushPropertiesFrame::UBBrushPropertiesFrame(QFrame* owner, const QList<QColor>& lightBackgroundColors,
                                                const QList<QColor>& darkBackgroundColors, const QList<QColor>& lightBackgroundSelectedColors,
                                                const QList<QColor>& darkBackgroundSelectedColors, UBPreferencesController* controller)
diff --git a/src/core/UBPreferencesController.h b/src/core/UBPreferencesController.h
index d89b4c181..25413762c 100644
--- a/src/core/UBPreferencesController.h
+++ b/src/core/UBPreferencesController.h
@@ -70,6 +70,9 @@ class UBPreferencesController : public QObject
         UBPreferencesController(QWidget *parent);
         virtual ~UBPreferencesController();
 
+        bool handleKeyEvent(QKeyEvent *event);
+        bool handleMouseEvent(QMouseEvent *event);
+        bool handleTabletEvent(QTabletEvent *event);
 
     public slots:
 
@@ -80,6 +83,8 @@ class UBPreferencesController : public QObject
         void wire();
         void init();
 
+        virtual bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE;
+
         UBPreferencesDialog* mPreferencesWindow;
         Ui::preferencesDialog* mPreferencesUI;
         UBBrushPropertiesFrame* mPenProperties;
@@ -104,14 +109,21 @@ class UBPreferencesController : public QObject
         void toolbarOrientationVertical(bool checked);
         void toolbarOrientationHorizontal(bool checked);
         void systemOSKCheckBoxToggled(bool checked);
+        void actionSelected(const QModelIndex& index);
+        void recordingClicked(bool checked);
+        void abortClicked();
+        void resetClicked();
 
     private slots:
         void adjustScreensPreferences();
+        void applyShortcutFilter(const QString& filter, int filterCol = -1);
+
 
     private:
         static qreal sSliderRatio;
         static qreal sMinPenWidth;
         static qreal sMaxPenWidth;
+        QModelIndex currentIndex;
 };
 
 class UBBrushPropertiesFrame : public Ui::brushProperties

From 414b6d55e67c0612a6318fd3acfa495432e44b73 Mon Sep 17 00:00:00 2001
From: letsfindaway <me@letsfindaway.de>
Date: Mon, 30 Sep 2024 16:21:21 +0200
Subject: [PATCH 2/2] i18n: update German translation

- change ownership of a translation string in UBShortcutManager
- add new translation strings
- update a few translations
---
 resources/i18n/OpenBoard_de.ts | 70 ++++++++++++++++++++++++++++++++--
 src/core/UBShortcutManager.cpp |  2 +-
 2 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts
index 275332271..b4e278c81 100644
--- a/resources/i18n/OpenBoard_de.ts
+++ b/resources/i18n/OpenBoard_de.ts
@@ -3008,6 +3008,28 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?</translation>
         <source>Use all available displays</source>
         <translation>Alle verfügbaren Bildschirme nutzen</translation>
     </message>
+    <message>
+        <source>Key sequence already in use</source>
+        <translation>Tastenkombination wird bereits benutzt</translation>
+    </message>
+    <message>
+        <source>Mouse button already in use</source>
+        <translation>Maustaste wird bereits benutzt</translation>
+    </message>
+    <message>
+        <source>Stylus button already in use</source>
+        <translation>Stifttaste wird bereits benutzt</translation>
+    </message>
+    <message>
+        <source>Accept</source>
+        <comment>preferencesDialog</comment>
+        <translation>Übernehmen</translation>
+    </message>
+    <message>
+        <source>Record</source>
+        <comment>preferencesDialog</comment>
+        <translation>Aufnehmen</translation>
+    </message>
 </context>
 <context>
     <name>UBSettings</name>
@@ -3079,7 +3101,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?</translation>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="260"/>
         <source>Reset zoom factor</source>
-        <translation>Zoom zurücksetzen</translation>
+        <translation>Zoom-Faktor zurücksetzen</translation>
     </message>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="266"/>
@@ -3129,7 +3151,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?</translation>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="466"/>
         <source>Command</source>
-        <translation>Kommando</translation>
+        <translation>Befehl</translation>
     </message>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="469"/>
@@ -3144,12 +3166,12 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?</translation>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="475"/>
         <source>Mouse Button</source>
-        <translation>Mausknopf</translation>
+        <translation>Maustaste</translation>
     </message>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="478"/>
         <source>Tablet Button</source>
-        <translation>Tablet Stiftknopf</translation>
+        <translation>Stifttaste</translation>
     </message>
     <message>
         <location filename="../../src/core/UBShortcutManager.cpp" line="629"/>
@@ -4076,6 +4098,46 @@ p, li { white-space: pre-wrap; }
         <source>List of screens used for Control, Display and Previous pages</source>
         <translation>Liste der Bildschirme, die für die Hauptansicht, Erweiterte Ansicht und Vorherige Seiten verwendet werden</translation>
     </message>
+    <message>
+        <source>Shortcut</source>
+        <translation>Kurzbefehl</translation>
+    </message>
+    <message>
+        <source>Filter</source>
+        <translation>Filter</translation>
+    </message>
+    <message>
+        <source>Active keyboard shortcuts without pressing Ctrl key</source>
+        <translation>Aktiviere Kurzbefehle auch ohne Strg Taste</translation>
+    </message>
+    <message>
+        <source>Shortcuts</source>
+        <translation>Kurzbefehle</translation>
+    </message>
+    <message>
+        <source>Abort</source>
+        <translation>Abbrechen</translation>
+    </message>
+    <message>
+        <source>Record</source>
+        <translation>Aufnehmen</translation>
+    </message>
+    <message>
+        <source>Stylus Button</source>
+        <translation>Stifttaste</translation>
+    </message>
+    <message>
+        <source>Mouse Button</source>
+        <translation>Maustaste</translation>
+    </message>
+    <message>
+        <source>Reset</source>
+        <translation>Zurücksetzen</translation>
+    </message>
+    <message>
+        <source>Key Sequence</source>
+        <translation>Tasten</translation>
+    </message>
 </context>
 <context>
     <name>trapFlashDialog</name>
diff --git a/src/core/UBShortcutManager.cpp b/src/core/UBShortcutManager.cpp
index dfe8c8239..56a66a870 100644
--- a/src/core/UBShortcutManager.cpp
+++ b/src/core/UBShortcutManager.cpp
@@ -43,7 +43,7 @@ UBShortcutManager* UBShortcutManager::sShortcutManager = nullptr;
 
 UBShortcutManager::UBShortcutManager() : mIgnoreCtrl(false)
 {
-    actionsOfGroup(QObject::tr("Common"));
+    actionsOfGroup(tr("Common"));
 }
 
 UBShortcutManager *UBShortcutManager::shortcutManager()
openSUSE Build Service is sponsored by