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 @@
+
+
+ Shortcut
+
+
+ -
+
+
+ Filter
+
+
+
+ -
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 789
+ 447
+
+
+
+
-
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+ QAbstractItemView::SingleSelection
+
+
+ QAbstractItemView::SelectRows
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+ 25
+
+
+ 25
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Active keyboard shortcuts without pressing Ctrl key
+
+
+
+
+
+ -
+
+
+ false
+
+
+ Shortcuts
+
+
+ Qt::AlignCenter
+
+
+
-
+
+
+ color: red;
+
+
+ Qt::PlainText
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Abort
+
+
+
+ -
+
+
+ Record
+
+
+ true
+
+
+
+ -
+
+
+ Stylus Button
+
+
+
+ -
+
+
+ Mouse Button
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Reset
+
+
+
+ -
+
+
+ Key Sequence
+
+
+
+
+
+
+
+
true
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?
Use all available displays
Alle verfügbaren Bildschirme nutzen
+
+ Key sequence already in use
+ Tastenkombination wird bereits benutzt
+
+
+ Mouse button already in use
+ Maustaste wird bereits benutzt
+
+
+ Stylus button already in use
+ Stifttaste wird bereits benutzt
+
+
+ Accept
+ preferencesDialog
+ Übernehmen
+
+
+ Record
+ preferencesDialog
+ Aufnehmen
+
UBSettings
@@ -3079,7 +3101,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?
Reset zoom factor
- Zoom zurücksetzen
+ Zoom-Faktor zurücksetzen
@@ -3129,7 +3151,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?
Command
- Kommando
+ Befehl
@@ -3144,12 +3166,12 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?
Mouse Button
- Mausknopf
+ Maustaste
Tablet Button
- Tablet Stiftknopf
+ Stifttaste
@@ -4076,6 +4098,46 @@ p, li { white-space: pre-wrap; }
List of screens used for Control, Display and Previous pages
Liste der Bildschirme, die für die Hauptansicht, Erweiterte Ansicht und Vorherige Seiten verwendet werden
+
+ Shortcut
+ Kurzbefehl
+
+
+ Filter
+ Filter
+
+
+ Active keyboard shortcuts without pressing Ctrl key
+ Aktiviere Kurzbefehle auch ohne Strg Taste
+
+
+ Shortcuts
+ Kurzbefehle
+
+
+ Abort
+ Abbrechen
+
+
+ Record
+ Aufnehmen
+
+
+ Stylus Button
+ Stifttaste
+
+
+ Mouse Button
+ Maustaste
+
+
+ Reset
+ Zurücksetzen
+
+
+ Key Sequence
+ Tasten
+
trapFlashDialog
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(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(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(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& lightBackgroundColors,
const QList& darkBackgroundColors, const QList& lightBackgroundSelectedColors,
const QList& 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
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()