diff --git a/ChangeLog.txt b/ChangeLog.txt index 6bf156df9..a1c6ac456 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -50,6 +50,7 @@ - Puzzle app. Fix updating layout when file already opened. - Tape app. Custom measurement name. - Tape app. Show variables in order they were added. +- Shortcuts manager. # Valentina 0.7.52 September 12, 2022 - Fix crash when default locale is ru. diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp index bceef8e0a..074ef1f87 100644 --- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp @@ -29,7 +29,9 @@ #include "puzzlepreferencesconfigurationpage.h" #include "../../vpapplication.h" #include "../vganalytics/vganalytics.h" +#include "../vmisc/dialogs/vshortcutdialog.h" #include "../vmisc/theme/vtheme.h" +#include "../vmisc/vabstractshortcutmanager.h" #include "ui_puzzlepreferencesconfigurationpage.h" #if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) @@ -79,6 +81,12 @@ PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget * //----------------------- Update ui->checkBoxAutomaticallyCheckUpdates->setChecked(settings->IsAutomaticallyCheckUpdates()); + // Tab Shortcuts + InitShortcuts(); + connect(ui->pushButtonRestoreDefaults, &QPushButton::clicked, this, [this]() { InitShortcuts(true); }); + connect(ui->shortcutsTable, &QTableWidget::cellDoubleClicked, this, + &PuzzlePreferencesConfigurationPage::ShortcutCellDoubleClicked); + // Tab Scrolling ui->spinBoxDuration->setMinimum(VCommonSettings::scrollingDurationMin); ui->spinBoxDuration->setMaximum(VCommonSettings::scrollingDurationMax); @@ -193,6 +201,19 @@ auto PuzzlePreferencesConfigurationPage::Apply() -> QStringList } settings->SetSingleLineFonts(ui->checkBoxSingleLineFonts->isChecked()); + // Tab Shortcuts + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + const auto &shortcutsList = manager->GetShortcutsList(); + for (int i = 0; i < m_transientShortcuts.length(); i++) + { + settings->SetActionShortcuts(VAbstractShortcutManager::ShortcutActionToString(shortcutsList.value(i).type), + m_transientShortcuts.value(i)); + } + + manager->UpdateShortcuts(); + } + // Tab Scrolling settings->SetScrollingDuration(ui->spinBoxDuration->value()); settings->SetScrollingUpdateInterval(ui->spinBoxUpdateInterval->value()); @@ -213,12 +234,27 @@ void PuzzlePreferencesConfigurationPage::changeEvent(QEvent *event) if (event->type() == QEvent::LanguageChange) { // retranslate designer form (single inheritance approach) + RetranslateShortcutsTable(); ui->retranslateUi(this); } // remember to call base class implementation QWidget::changeEvent(event); } +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesConfigurationPage::ShortcutCellDoubleClicked(int row, int column) +{ + Q_UNUSED(column) + auto *shortcutDialog = new VShortcutDialog(row, this); + connect(shortcutDialog, &VShortcutDialog::ShortcutsListChanged, this, + [this](int index, const QStringList &stringListShortcuts) + { + m_transientShortcuts.replace(index, stringListShortcuts); + UpdateShortcutsTable(); + }); + shortcutDialog->open(); +} + //--------------------------------------------------------------------------------------------------------------------- void PuzzlePreferencesConfigurationPage::SetThemeModeComboBox() { @@ -227,3 +263,75 @@ void PuzzlePreferencesConfigurationPage::SetThemeModeComboBox() ui->comboBoxThemeMode->addItem(tr("Dark", "theme"), static_cast(VThemeMode::Dark)); ui->comboBoxThemeMode->addItem(tr("Light", "theme"), static_cast(VThemeMode::Light)); } + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesConfigurationPage::InitShortcuts(bool defaults) +{ + VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return; + } + + manager->UpdateShortcuts(); + m_transientShortcuts.clear(); + ui->shortcutsTable->clearContents(); + const auto &shortcutsList = manager->GetShortcutsList(); + ui->shortcutsTable->setRowCount(static_cast(shortcutsList.length())); + + for (int i = 0; i < shortcutsList.length(); i++) + { + const VAbstractShortcutManager::VSShortcut &shortcut = shortcutsList.value(i); + + // Add shortcut to transient shortcut list + if (defaults) + { + m_transientShortcuts.append(shortcut.defaultShortcuts); + } + else + { + m_transientShortcuts.append(shortcut.shortcuts); + } + + // Add shortcut to table widget + auto *nameItem = new QTableWidgetItem(); + nameItem->setText(VAbstractShortcutManager::ReadableName(shortcut.type)); + ui->shortcutsTable->setItem(i, 0, nameItem); + + auto *shortcutsItem = new QTableWidgetItem(); + shortcutsItem->setText(VAbstractShortcutManager::StringListToReadableString(m_transientShortcuts.value(i))); + ui->shortcutsTable->setItem(i, 1, shortcutsItem); + } + UpdateShortcutsTable(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesConfigurationPage::UpdateShortcutsTable() +{ + for (int i = 0; i < m_transientShortcuts.length(); i++) + { + const QStringList &shortcuts = m_transientShortcuts.value(i); + ui->shortcutsTable->item(i, 1)->setText(VAbstractShortcutManager::StringListToReadableString(shortcuts)); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzlePreferencesConfigurationPage::RetranslateShortcutsTable() +{ + VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return; + } + + const auto &shortcutsList = manager->GetShortcutsList(); + for (int i = 0; i < shortcutsList.length(); i++) + { + const VAbstractShortcutManager::VSShortcut &shortcut = shortcutsList.value(i); + + if (QTableWidgetItem *it = ui->shortcutsTable->item(i, 0)) + { + it->setText(VAbstractShortcutManager::ReadableName(shortcut.type)); + } + } +} diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h index 15fabd428..8398bbdf3 100644 --- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h @@ -52,13 +52,20 @@ public: protected: void changeEvent(QEvent *event) override; +private slots: + void ShortcutCellDoubleClicked(int row, int column); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(PuzzlePreferencesConfigurationPage) // NOLINT Ui::PuzzlePreferencesConfigurationPage *ui; bool m_langChanged{false}; + QList m_transientShortcuts{}; void SetThemeModeComboBox(); + void InitShortcuts(bool defaults = false); + void UpdateShortcutsTable(); + void RetranslateShortcutsTable(); }; #endif // PUZZLEPREFERENCESCONFIGURATIONPAGE_H diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui index d5fe2d34f..f929b8279 100644 --- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui +++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui @@ -235,6 +235,87 @@ This option will take an affect after restart. + + + Shortcuts + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + 0 + + + 2 + + + true + + + 150 + + + false + + + true + + + false + + + + Action + + + + + Shortcuts + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Restore defaults + + + + + + + Scrolling diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri index 36f38d1eb..626342d38 100644 --- a/src/app/puzzle/puzzle.pri +++ b/src/app/puzzle/puzzle.pri @@ -39,7 +39,8 @@ SOURCES += \ $$PWD/xml/vplayoutfilereader.cpp \ $$PWD/xml/vplayoutfilewriter.cpp \ $$PWD/xml/vplayoutliterals.cpp \ - $$PWD/dialogs/dialogsavemanuallayout.cpp + $$PWD/dialogs/dialogsavemanuallayout.cpp \ + $$PWD/vpuzzleshortcutmanager.cpp *msvc*:SOURCES += $$PWD/stable.cpp @@ -82,7 +83,8 @@ HEADERS += \ $$PWD/xml/vplayoutfilereader.h \ $$PWD/xml/vplayoutfilewriter.h \ $$PWD/xml/vplayoutliterals.h \ - $$PWD/dialogs/dialogsavemanuallayout.h + $$PWD/dialogs/dialogsavemanuallayout.h \ + $$PWD/vpuzzleshortcutmanager.h FORMS += \ $$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.ui \ diff --git a/src/app/puzzle/puzzle.qbs b/src/app/puzzle/puzzle.qbs index be4f6f083..a3ab909b4 100644 --- a/src/app/puzzle/puzzle.qbs +++ b/src/app/puzzle/puzzle.qbs @@ -56,6 +56,8 @@ VToolApp { "vpsettings.h", "vptilefactory.h", "vpmainwindow.ui", + "vpuzzleshortcutmanager.cpp", + "vpuzzleshortcutmanager.h", ] Group { diff --git a/src/app/puzzle/vpapplication.cpp b/src/app/puzzle/vpapplication.cpp index e32f73f0f..56a0cb37e 100644 --- a/src/app/puzzle/vpapplication.cpp +++ b/src/app/puzzle/vpapplication.cpp @@ -40,6 +40,7 @@ #include "../vmisc/vsysexits.h" #include "version.h" #include "vpmainwindow.h" +#include "vpuzzleshortcutmanager.h" #include #include @@ -459,6 +460,8 @@ void VPApplication::InitOptions() statistic->SetApiSecret(GA_API_SECRET); statistic->SetRepoRevision(QLatin1String(BUILD_REVISION)); statistic->Enable(settings->IsCollectStatistic()); + + m_shortcutManager = new VPuzzleShortcutManager(this); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index 0edc0f53d..29e78b13e 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -432,6 +432,12 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) { QTimer::singleShot(V_SECONDS(1), this, &VPMainWindow::AskDefaultSettings); } + + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + connect(manager, &VAbstractShortcutManager::shortcutsUpdated, this, &VPMainWindow::UpdateShortcuts); + UpdateShortcuts(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -655,9 +661,10 @@ void VPMainWindow::SetupMenu() // most of the actions are connected through name convention (auto-connection) // File // -------------------- connects the actions for the file menu - ui->actionNew->setShortcuts(QKeySequence::New); - ui->actionSave->setShortcuts(QKeySequence::Save); - ui->actionSaveAs->setShortcuts(QKeySequence::SaveAs); + m_actionShortcuts.insert(VShortcutAction::New, ui->actionNew); + m_actionShortcuts.insert(VShortcutAction::Open, ui->actionOpen); + m_actionShortcuts.insert(VShortcutAction::Save, ui->actionSave); + m_actionShortcuts.insert(VShortcutAction::SaveAs, ui->actionSaveAs); m_recentFileActs.fill(nullptr); for (auto &recentFileAct : m_recentFileActs) @@ -689,7 +696,7 @@ void VPMainWindow::SetupMenu() UpdateRecentFileActions(); connect(ui->actionExit, &QAction::triggered, this, &VPMainWindow::close); - ui->actionExit->setShortcuts(QKeySequence::Quit); + m_actionShortcuts.insert(VShortcutAction::Quit, ui->actionExit); // Layout connect(ui->actionExportLayout, &QAction::triggered, this, &VPMainWindow::on_ExportLayout); @@ -705,13 +712,13 @@ void VPMainWindow::SetupMenu() // Add Undo/Redo actions. undoAction = m_layout->UndoStack()->createUndoAction(this, tr("&Undo")); - undoAction->setShortcuts(QKeySequence::Undo); + m_actionShortcuts.insert(VShortcutAction::Undo, undoAction); undoAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo"))); ui->menuSheet->addAction(undoAction); ui->toolBarUndoCommands->addAction(undoAction); redoAction = m_layout->UndoStack()->createRedoAction(this, tr("&Redo")); - redoAction->setShortcuts(QKeySequence::Redo); + m_actionShortcuts.insert(VShortcutAction::Redo, redoAction); redoAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-redo"))); ui->menuSheet->addAction(redoAction); ui->toolBarUndoCommands->addAction(redoAction); @@ -1586,61 +1593,18 @@ void VPMainWindow::InitZoomToolBar() delete m_mouseCoordinate; - QT_WARNING_PUSH -#if !defined(Q_OS_MACOS) && defined(Q_CC_CLANG) - QT_WARNING_DISABLE_CLANG("-Wenum-enum-conversion") -#endif - // connect the zoom buttons and shortcuts to the slots - QList zoomInShortcuts; - zoomInShortcuts.append(QKeySequence(QKeySequence::ZoomIn)); - zoomInShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(QKeyCombination(Qt::ControlModifier), Qt::Key_Plus | Qt::KeypadModifier)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_Plus + Qt::KeypadModifier)); -#endif - ui->actionZoomIn->setShortcuts(zoomInShortcuts); + m_actionShortcuts.insert(VShortcutAction::ZoomIn, ui->actionZoomIn); connect(ui->actionZoomIn, &QAction::triggered, m_graphicsView, &VPMainGraphicsView::ZoomIn); - QList zoomOutShortcuts; - zoomOutShortcuts.append(QKeySequence(QKeySequence::ZoomOut)); - zoomOutShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(QKeyCombination(Qt::ControlModifier), Qt::Key_Minus | Qt::KeypadModifier)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_Minus + Qt::KeypadModifier)); -#endif - ui->actionZoomOut->setShortcuts(zoomOutShortcuts); + m_actionShortcuts.insert(VShortcutAction::ZoomOut, ui->actionZoomOut); connect(ui->actionZoomOut, &QAction::triggered, m_graphicsView, &VPMainGraphicsView::ZoomOut); - QList zoomOriginalShortcuts; - zoomOriginalShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ControlModifier | Qt::Key_0)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_0)); -#endif - zoomOriginalShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(QKeyCombination(Qt::ControlModifier), Qt::Key_0 | Qt::KeypadModifier)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_0 + Qt::KeypadModifier)); -#endif - ui->actionZoomOriginal->setShortcuts(zoomOriginalShortcuts); + m_actionShortcuts.insert(VShortcutAction::ZoomOriginal, ui->actionZoomOriginal); connect(ui->actionZoomOriginal, &QAction::triggered, m_graphicsView, &VPMainGraphicsView::ZoomOriginal); - QList zoomFitBestShortcuts; - zoomFitBestShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ControlModifier | Qt::Key_Equal)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_Equal)); -#endif - ui->actionZoomFitBest->setShortcuts(zoomFitBestShortcuts); + m_actionShortcuts.insert(VShortcutAction::ZoomFitBest, ui->actionZoomFitBest); connect(ui->actionZoomFitBest, &QAction::triggered, m_graphicsView, &VPMainGraphicsView::ZoomFitBest); - - QT_WARNING_POP } //--------------------------------------------------------------------------------------------------------------------- @@ -4762,6 +4726,15 @@ void VPMainWindow::LayoutWarningPiecesOutOfBound_toggled(bool checked) } } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::UpdateShortcuts() +{ + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + manager->UpdateActionShortcuts(m_actionShortcuts); + } +} + //--------------------------------------------------------------------------------------------------------------------- #if defined(Q_OS_MAC) void VPMainWindow::AboutToShowDockMenu() diff --git a/src/app/puzzle/vpmainwindow.h b/src/app/puzzle/vpmainwindow.h index ff6b7943b..eb97c418d 100644 --- a/src/app/puzzle/vpmainwindow.h +++ b/src/app/puzzle/vpmainwindow.h @@ -36,6 +36,7 @@ #include "../vlayout/dialogs/vabstractlayoutdialog.h" #include "../vlayout/vlayoutpiece.h" #include "../vmisc/def.h" +#include "../vmisc/vabstractshortcutmanager.h" #include "../vmisc/vlockguard.h" #include "../vwidgets/vabstractmainwindow.h" #include "carousel/vpcarrousel.h" @@ -294,6 +295,8 @@ private slots: void LayoutWarningPiecesSuperposition_toggled(bool checked); void LayoutWarningPiecesOutOfBound_toggled(bool checked); + void UpdateShortcuts(); + private: Q_DISABLE_COPY_MOVE(VPMainWindow) // NOLINT Ui::VPMainWindow *ui; @@ -339,6 +342,8 @@ private: QFileSystemWatcher *m_watermarkWatcher{nullptr}; + QMultiHash m_actionShortcuts{}; + struct VPLayoutPrinterPage { VPSheetPtr sheet{}; diff --git a/src/app/puzzle/vpuzzleshortcutmanager.cpp b/src/app/puzzle/vpuzzleshortcutmanager.cpp new file mode 100644 index 000000000..162764a78 --- /dev/null +++ b/src/app/puzzle/vpuzzleshortcutmanager.cpp @@ -0,0 +1,59 @@ +/************************************************************************ + ** + ** @file vpuzzleshortcutmanager.cpp + ** @author Roman Telezhynskyi + ** @date 23 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "vpuzzleshortcutmanager.h" + +VPuzzleShortcutManager::VPuzzleShortcutManager(QObject *parent) + : VAbstractShortcutManager{parent} +{ + QT_WARNING_PUSH +#if !defined(Q_OS_MACOS) && defined(Q_CC_CLANG) + QT_WARNING_DISABLE_CLANG("-Wenum-enum-conversion") +#endif + + AddShortcut({VShortcutAction::New, KeyBindingsToStringList(QKeySequence::New), {}}); + AddShortcut({VShortcutAction::Open, KeyBindingsToStringList(QKeySequence::Open), {}}); + AddShortcut({VShortcutAction::Save, KeyBindingsToStringList(QKeySequence::Save), {}}); + AddShortcut({VShortcutAction::SaveAs, KeyBindingsToStringList(QKeySequence::SaveAs), {}}); + AddShortcut({VShortcutAction::Undo, KeyBindingsToStringList(QKeySequence::Undo), {}}); + AddShortcut({VShortcutAction::Redo, KeyBindingsToStringList(QKeySequence::Redo), {}}); + AddShortcut({VShortcutAction::ZoomIn, KeyBindingsToStringList(QKeySequence::ZoomIn), {}}); + AddShortcut({VShortcutAction::ZoomOut, KeyBindingsToStringList(QKeySequence::ZoomOut), {}}); + AddShortcut({VShortcutAction::ZoomOriginal, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_0).toString(), +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QKeySequence(Qt::ControlModifier + Qt::Key_0 + Qt::KeypadModifier).toString() +#endif + }, + {}}); + AddShortcut({VShortcutAction::ZoomFitBest, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_Equal).toString()}, + {}}); + AddShortcut({VShortcutAction::Quit, KeyBindingsToStringList(QKeySequence::Quit), {}}); + + QT_WARNING_POP +} diff --git a/src/app/puzzle/vpuzzleshortcutmanager.h b/src/app/puzzle/vpuzzleshortcutmanager.h new file mode 100644 index 000000000..faa2d1a88 --- /dev/null +++ b/src/app/puzzle/vpuzzleshortcutmanager.h @@ -0,0 +1,49 @@ +/************************************************************************ + ** + ** @file vpuzzleshortcutmanager.h + ** @author Roman Telezhynskyi + ** @date 23 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef VPUZZLESHORTCUTMANAGER_H +#define VPUZZLESHORTCUTMANAGER_H + +#include "../vmisc/vabstractshortcutmanager.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#include "../vmisc/defglobal.h" +#endif + +class VPuzzleShortcutManager : public VAbstractShortcutManager +{ + Q_OBJECT // NOLINT + +public: + explicit VPuzzleShortcutManager(QObject *parent = nullptr); + ~VPuzzleShortcutManager() override = default; + +private: + Q_DISABLE_COPY_MOVE(VPuzzleShortcutManager) // NOLINT +}; + +#endif // VPUZZLESHORTCUTMANAGER_H diff --git a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp index 44ffdc7ca..e01df6a1f 100644 --- a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp +++ b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp @@ -31,7 +31,9 @@ #include "../../vtapesettings.h" #include "../qmuparser/qmudef.h" #include "../vganalytics/vganalytics.h" +#include "../vmisc/dialogs/vshortcutdialog.h" #include "../vmisc/theme/vtheme.h" +#include "../vmisc/vabstractshortcutmanager.h" #include "../vpatterndb/pmsystems.h" #include "ui_tapepreferencesconfigurationpage.h" @@ -105,6 +107,12 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare //----------------------- Update ui->checkBoxAutomaticallyCheckUpdates->setChecked(settings->IsAutomaticallyCheckUpdates()); + // Tab Shortcuts + InitShortcuts(); + connect(ui->pushButtonRestoreDefaults, &QPushButton::clicked, this, [this]() { InitShortcuts(true); }); + connect(ui->shortcutsTable, &QTableWidget::cellDoubleClicked, this, + &TapePreferencesConfigurationPage::ShortcutCellDoubleClicked); + // Tab Privacy ui->checkBoxSendUsageStatistics->setChecked(settings->IsCollectStatistic()); } @@ -181,6 +189,19 @@ auto TapePreferencesConfigurationPage::Apply() -> QStringList settings->SetAutomaticallyCheckUpdates(ui->checkBoxAutomaticallyCheckUpdates->isChecked()); } + // Tab Shortcuts + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + const auto &shortcutsList = manager->GetShortcutsList(); + for (int i = 0; i < m_transientShortcuts.length(); i++) + { + settings->SetActionShortcuts(VAbstractShortcutManager::ShortcutActionToString(shortcutsList.value(i).type), + m_transientShortcuts.value(i)); + } + + manager->UpdateShortcuts(); + } + // Tab Privacy settings->SetCollectStatistic(ui->checkBoxSendUsageStatistics->isChecked()); VGAnalytics::Instance()->Enable(ui->checkBoxSendUsageStatistics->isChecked()); @@ -201,6 +222,20 @@ void TapePreferencesConfigurationPage::changeEvent(QEvent *event) QWidget::changeEvent(event); } +//--------------------------------------------------------------------------------------------------------------------- +void TapePreferencesConfigurationPage::ShortcutCellDoubleClicked(int row, int column) +{ + Q_UNUSED(column) + auto *shortcutDialog = new VShortcutDialog(row, this); + connect(shortcutDialog, &VShortcutDialog::ShortcutsListChanged, this, + [this](int index, const QStringList &stringListShortcuts) + { + m_transientShortcuts.replace(index, stringListShortcuts); + UpdateShortcutsTable(); + }); + shortcutDialog->open(); +} + //--------------------------------------------------------------------------------------------------------------------- void TapePreferencesConfigurationPage::RetranslateUi() { @@ -215,6 +250,8 @@ void TapePreferencesConfigurationPage::RetranslateUi() ui->systemCombo->blockSignals(false); ui->systemCombo->setCurrentIndex(ui->systemCombo->findData(code)); } + + RetranslateShortcutsTable(); } //--------------------------------------------------------------------------------------------------------------------- @@ -225,3 +262,75 @@ void TapePreferencesConfigurationPage::SetThemeModeComboBox() ui->comboBoxThemeMode->addItem(tr("Dark", "theme"), static_cast(VThemeMode::Dark)); ui->comboBoxThemeMode->addItem(tr("Light", "theme"), static_cast(VThemeMode::Light)); } + +//--------------------------------------------------------------------------------------------------------------------- +void TapePreferencesConfigurationPage::InitShortcuts(bool defaults) +{ + VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return; + } + + manager->UpdateShortcuts(); + m_transientShortcuts.clear(); + ui->shortcutsTable->clearContents(); + const auto &shortcutsList = manager->GetShortcutsList(); + ui->shortcutsTable->setRowCount(static_cast(shortcutsList.length())); + + for (int i = 0; i < shortcutsList.length(); i++) + { + const VAbstractShortcutManager::VSShortcut &shortcut = shortcutsList.value(i); + + // Add shortcut to transient shortcut list + if (defaults) + { + m_transientShortcuts.append(shortcut.defaultShortcuts); + } + else + { + m_transientShortcuts.append(shortcut.shortcuts); + } + + // Add shortcut to table widget + auto *nameItem = new QTableWidgetItem(); + nameItem->setText(VAbstractShortcutManager::ReadableName(shortcut.type)); + ui->shortcutsTable->setItem(i, 0, nameItem); + + auto *shortcutsItem = new QTableWidgetItem(); + shortcutsItem->setText(VAbstractShortcutManager::StringListToReadableString(m_transientShortcuts.value(i))); + ui->shortcutsTable->setItem(i, 1, shortcutsItem); + } + UpdateShortcutsTable(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void TapePreferencesConfigurationPage::UpdateShortcutsTable() +{ + for (int i = 0; i < m_transientShortcuts.length(); i++) + { + const QStringList &shortcuts = m_transientShortcuts.value(i); + ui->shortcutsTable->item(i, 1)->setText(VAbstractShortcutManager::StringListToReadableString(shortcuts)); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void TapePreferencesConfigurationPage::RetranslateShortcutsTable() +{ + VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return; + } + + const auto &shortcutsList = manager->GetShortcutsList(); + for (int i = 0; i < shortcutsList.length(); i++) + { + const VAbstractShortcutManager::VSShortcut &shortcut = shortcutsList.value(i); + + if (QTableWidgetItem *it = ui->shortcutsTable->item(i, 0)) + { + it->setText(VAbstractShortcutManager::ReadableName(shortcut.type)); + } + } +} diff --git a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h index 606c8f6f3..3c21ecbe4 100644 --- a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h +++ b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h @@ -53,15 +53,22 @@ public: protected: void changeEvent(QEvent *event) override; +private slots: + void ShortcutCellDoubleClicked(int row, int column); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(TapePreferencesConfigurationPage) // NOLINT Ui::TapePreferencesConfigurationPage *ui; bool m_langChanged; bool m_systemChanged; + QList m_transientShortcuts{}; void RetranslateUi(); void SetThemeModeComboBox(); + void InitShortcuts(bool defaults = false); + void UpdateShortcutsTable(); + void RetranslateShortcutsTable(); }; #endif // TAPEPREFERENCESCONFIGURATIONPAGE_H diff --git a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui index 4e147bbf9..26cbb22a2 100644 --- a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui +++ b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui @@ -249,6 +249,87 @@ + + + Shortcuts + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + 0 + + + 2 + + + true + + + 150 + + + false + + + true + + + false + + + + Action + + + + + Shortcuts + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Restore defaults + + + + + + + Privacy diff --git a/src/app/tape/mapplication.cpp b/src/app/tape/mapplication.cpp index 59a4d5669..ea2bd0cd0 100644 --- a/src/app/tape/mapplication.cpp +++ b/src/app/tape/mapplication.cpp @@ -42,6 +42,7 @@ #include "../vmisc/vsysexits.h" #include "tmainwindow.h" #include "version.h" +#include "vtapeshortcutmanager.h" #include #include @@ -504,6 +505,8 @@ void MApplication::InitOptions() statistic->SetApiSecret(GA_API_SECRET); statistic->SetRepoRevision(QLatin1String(BUILD_REVISION)); statistic->Enable(settings->IsCollectStatistic()); + + m_shortcutManager = new VTapeShortcutManager(this); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/tape/tape.pri b/src/app/tape/tape.pri index 3b4cc6b54..99d6e1a2e 100644 --- a/src/app/tape/tape.pri +++ b/src/app/tape/tape.pri @@ -16,7 +16,8 @@ SOURCES += \ $$PWD/dialogs/dialogtapepreferences.cpp \ $$PWD/dialogs/configpages/tapepreferencesconfigurationpage.cpp \ $$PWD/vtapesettings.cpp \ - $$PWD/dialogs/dialogsetupmultisize.cpp + $$PWD/dialogs/dialogsetupmultisize.cpp \ + $$PWD/vtapeshortcutmanager.cpp *msvc*:SOURCES += $$PWD/stable.cpp @@ -36,7 +37,8 @@ HEADERS += \ $$PWD/dialogs/dialogtapepreferences.h \ $$PWD/dialogs/configpages/tapepreferencesconfigurationpage.h \ $$PWD/vtapesettings.h \ - $$PWD/dialogs/dialogsetupmultisize.h + $$PWD/dialogs/dialogsetupmultisize.h \ + $$PWD/vtapeshortcutmanager.h FORMS += \ $$PWD/dialogs/dialogdimensioncustomnames.ui \ diff --git a/src/app/tape/tape.qbs b/src/app/tape/tape.qbs index f3a13a5a3..70a37f2a6 100644 --- a/src/app/tape/tape.qbs +++ b/src/app/tape/tape.qbs @@ -62,6 +62,8 @@ VToolApp { "vlitepattern.h", "vtapesettings.h", "tmainwindow.ui", + "vtapeshortcutmanager.cpp", + "vtapeshortcutmanager.h", ] Group { diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index 69171de0b..db9d30d1b 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -316,6 +316,20 @@ TMainWindow::TMainWindow(QWidget *parent) { QTimer::singleShot(V_SECONDS(1), this, &TMainWindow::AskDefaultSettings); } + + m_buttonShortcuts.insert(VShortcutAction::CaseSensitiveMatch, ui->toolButtonCaseSensitive); + m_buttonShortcuts.insert(VShortcutAction::WholeWordMatch, ui->toolButtonWholeWord); + m_buttonShortcuts.insert(VShortcutAction::RegexMatch, ui->toolButtonRegexp); + m_buttonShortcuts.insert(VShortcutAction::SearchHistory, ui->pushButtonSearch); + m_buttonShortcuts.insert(VShortcutAction::RegexMatchUnicodeProperties, ui->toolButtonUseUnicodeProperties); + m_buttonShortcuts.insert(VShortcutAction::FindNext, ui->toolButtonFindNext); + m_buttonShortcuts.insert(VShortcutAction::FindPrevious, ui->toolButtonFindNext); + + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + connect(manager, &VAbstractShortcutManager::shortcutsUpdated, this, &TMainWindow::UpdateShortcuts); + UpdateShortcuts(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -2864,12 +2878,23 @@ void TMainWindow::AskDefaultSettings() } } +//--------------------------------------------------------------------------------------------------------------------- +void TMainWindow::UpdateShortcuts() +{ + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + manager->UpdateButtonShortcut(m_buttonShortcuts); + manager->UpdateActionShortcuts(m_actionShortcuts); + UpdateSearchControlsTooltips(); + } +} + //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::SetupMenu() { // File connect(ui->actionNew, &QAction::triggered, this, &TMainWindow::FileNew); - ui->actionNew->setShortcuts(QKeySequence::New); + m_actionShortcuts.insert(VShortcutAction::New, ui->actionNew); connect(ui->actionOpenIndividual, &QAction::triggered, this, &TMainWindow::OpenIndividual); connect(ui->actionOpenMultisize, &QAction::triggered, this, &TMainWindow::OpenMultisize); @@ -2877,10 +2902,10 @@ void TMainWindow::SetupMenu() connect(ui->actionCreateFromExisting, &QAction::triggered, this, &TMainWindow::CreateFromExisting); connect(ui->actionSave, &QAction::triggered, this, &TMainWindow::FileSave); - ui->actionSave->setShortcuts(QKeySequence::Save); + m_actionShortcuts.insert(VShortcutAction::Save, ui->actionSave); connect(ui->actionSaveAs, &QAction::triggered, this, &TMainWindow::FileSaveAs); - ui->actionSaveAs->setShortcuts(QKeySequence::SaveAs); + m_actionShortcuts.insert(VShortcutAction::SaveAs, ui->actionSaveAs); connect(ui->actionExportToCSV, &QAction::triggered, this, &TMainWindow::ExportDataToCSV); connect(ui->actionImportFromCSV, &QAction::triggered, this, &TMainWindow::ImportDataFromCSV); @@ -2930,7 +2955,7 @@ void TMainWindow::SetupMenu() ui->menuFile->insertAction(ui->actionPreferences, m_separatorAct); connect(ui->actionQuit, &QAction::triggered, this, &TMainWindow::close); - ui->actionQuit->setShortcuts(QKeySequence::Quit); + m_actionShortcuts.insert(VShortcutAction::Quit, ui->actionQuit); // Measurements connect(ui->actionAddCustom, &QAction::triggered, this, &TMainWindow::AddCustom); @@ -5043,12 +5068,18 @@ void TMainWindow::SaveSearchRequest() //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::UpdateSearchControlsTooltips() { - auto UpdateToolTip = [](QAbstractButton *button) + auto UpdateToolTip = [this](QAbstractButton *button) { if (button->toolTip().contains("%1"_L1)) { + m_serachButtonTooltips.insert(button, button->toolTip()); button->setToolTip(button->toolTip().arg(button->shortcut().toString(QKeySequence::NativeText))); } + else if (m_serachButtonTooltips.contains(button)) + { + QString tooltip = m_serachButtonTooltips.value(button); + button->setToolTip(tooltip.arg(button->shortcut().toString(QKeySequence::NativeText))); + } }; UpdateToolTip(ui->toolButtonCaseSensitive); diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h index 9b46e986b..41d2bd4e8 100644 --- a/src/app/tape/tmainwindow.h +++ b/src/app/tape/tmainwindow.h @@ -35,6 +35,7 @@ #include "../vformat/vmeasurements.h" #include "../vmisc/def.h" +#include "../vmisc/vabstractshortcutmanager.h" #include "../vmisc/vlockguard.h" #include "../vmisc/vtablesearch.h" #include "../vwidgets/vabstractmainwindow.h" @@ -47,6 +48,7 @@ class TMainWindow; class QLabel; class QxtCsvModel; class VMeasurement; +class QAbstractButton; class TMainWindow : public VAbstractMainWindow { @@ -155,6 +157,8 @@ private slots: void AskDefaultSettings(); + void UpdateShortcuts(); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(TMainWindow) // NOLINT @@ -201,6 +205,10 @@ private: QString description{}; // NOLINT(misc-non-private-member-variables-in-classes) }; + QMultiHash m_actionShortcuts{}; + QMultiHash m_buttonShortcuts{}; + QHash m_serachButtonTooltips{}; + void SetupMenu(); void InitWindow(); void InitMenu(); diff --git a/src/app/tape/vtapeshortcutmanager.cpp b/src/app/tape/vtapeshortcutmanager.cpp new file mode 100644 index 000000000..24c1b125d --- /dev/null +++ b/src/app/tape/vtapeshortcutmanager.cpp @@ -0,0 +1,59 @@ +/************************************************************************ + ** + ** @file vtapeshortcutmanager.cpp + ** @author Roman Telezhynskyi + ** @date 23 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "vtapeshortcutmanager.h" + +VTapeShortcutManager::VTapeShortcutManager(QObject *parent) + : VAbstractShortcutManager{parent} +{ + QT_WARNING_PUSH +#if !defined(Q_OS_MACOS) && defined(Q_CC_CLANG) + QT_WARNING_DISABLE_CLANG("-Wenum-enum-conversion") +#endif + + AddShortcut({VShortcutAction::New, KeyBindingsToStringList(QKeySequence::New), {}}); + AddShortcut({VShortcutAction::Save, KeyBindingsToStringList(QKeySequence::Save), {}}); + AddShortcut({VShortcutAction::SaveAs, KeyBindingsToStringList(QKeySequence::SaveAs), {}}); + AddShortcut({VShortcutAction::Quit, KeyBindingsToStringList(QKeySequence::Quit), {}}); + AddShortcut({VShortcutAction::CaseSensitiveMatch, + {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_C).toString()}, + {}}); + AddShortcut( + {VShortcutAction::WholeWordMatch, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_W).toString()}, {}}); + AddShortcut( + {VShortcutAction::RegexMatch, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_X).toString()}, {}}); + AddShortcut( + {VShortcutAction::SearchHistory, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_Down).toString()}, {}}); + AddShortcut({VShortcutAction::RegexMatchUnicodeProperties, + {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_U).toString()}, + {}}); + AddShortcut({VShortcutAction::FindNext, {QKeySequence(Qt::Key_F3).toString()}, {}}); + AddShortcut( + {VShortcutAction::FindPrevious, {QKeySequence(Qt::ShiftModifier QKEY_SEQUENCE_OP Qt::Key_F3).toString()}, {}}); + + QT_WARNING_POP +} diff --git a/src/app/tape/vtapeshortcutmanager.h b/src/app/tape/vtapeshortcutmanager.h new file mode 100644 index 000000000..f0e14c651 --- /dev/null +++ b/src/app/tape/vtapeshortcutmanager.h @@ -0,0 +1,49 @@ +/************************************************************************ + ** + ** @file vtapeshortcutmanager.h + ** @author Roman Telezhynskyi + ** @date 23 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef VTAPESHORTCUTMANAGER_H +#define VTAPESHORTCUTMANAGER_H + +#include "../vmisc/vabstractshortcutmanager.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#include "../vmisc/defglobal.h" +#endif + +class VTapeShortcutManager : public VAbstractShortcutManager +{ + Q_OBJECT // NOLINT + +public: + explicit VTapeShortcutManager(QObject *parent = nullptr); + ~VTapeShortcutManager() override = default; + +private: + Q_DISABLE_COPY_MOVE(VTapeShortcutManager) // NOLINT +}; + +#endif // VTAPESHORTCUTMANAGER_H diff --git a/src/app/valentina/core/vapplication.cpp b/src/app/valentina/core/vapplication.cpp index 812b16d65..ad7bc8574 100644 --- a/src/app/valentina/core/vapplication.cpp +++ b/src/app/valentina/core/vapplication.cpp @@ -42,6 +42,7 @@ #include "../vmisc/theme/vtheme.h" #include "../vmisc/vsysexits.h" #include "../vmisc/vvalentinasettings.h" +#include "vvalentinashortcutmanager.h" #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) #include "../vmisc/backport/text.h" @@ -53,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -704,6 +706,8 @@ void VApplication::InitOptions() VTheme::InitApplicationStyle(); VTheme::SetIconTheme(); VTheme::InitThemeMode(); + + m_shortcutManager = new VValentinaShortcutManager(this); } auto *statistic = VGAnalytics::Instance(); diff --git a/src/app/valentina/core/vvalentinashortcutmanager.cpp b/src/app/valentina/core/vvalentinashortcutmanager.cpp new file mode 100644 index 000000000..9e159adbe --- /dev/null +++ b/src/app/valentina/core/vvalentinashortcutmanager.cpp @@ -0,0 +1,124 @@ +/************************************************************************ + ** + ** @file vvalentinashortcutmanager.cpp + ** @author Roman Telezhynskyi + ** @date 20 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "vvalentinashortcutmanager.h" +#include "qnamespace.h" +#include "vabstractshortcutmanager.h" + +#include + +//--------------------------------------------------------------------------------------------------------------------- +VValentinaShortcutManager::VValentinaShortcutManager(QObject *parent) + : VAbstractShortcutManager{parent} +{ + QT_WARNING_PUSH +#if !defined(Q_OS_MACOS) && defined(Q_CC_CLANG) + QT_WARNING_DISABLE_CLANG("-Wenum-enum-conversion") +#endif + + AddShortcut({VShortcutAction::ZoomIn, KeyBindingsToStringList(QKeySequence::ZoomIn), {}}); + AddShortcut({VShortcutAction::ZoomOut, KeyBindingsToStringList(QKeySequence::ZoomOut), {}}); + AddShortcut({VShortcutAction::ZoomOriginal, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_0).toString(), +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QKeySequence(Qt::ControlModifier + Qt::Key_0 + Qt::KeypadModifier).toString() +#endif + }, + {}}); + AddShortcut({VShortcutAction::ZoomFitBest, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_Equal).toString()}, + {}}); + AddShortcut({VShortcutAction::ZoomFitBestCurrent, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_M).toString()}, + {}}); + AddShortcut({VShortcutAction::IncreaseLabelFont, + {QKeySequence(Qt::ShiftModifier QKEY_SEQUENCE_OP Qt::Key_Plus).toString()}, + {}}); + AddShortcut({VShortcutAction::DecreaseLabelFont, + {QKeySequence(Qt::ShiftModifier QKEY_SEQUENCE_OP Qt::Key_Minus).toString()}, + {}}); + AddShortcut({VShortcutAction::OriginalLabelFont, + {QKeySequence(Qt::ShiftModifier QKEY_SEQUENCE_OP Qt::Key_0).toString()}, + {}}); + AddShortcut( + {VShortcutAction::HideLabels, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_L).toString()}, {}}); + AddShortcut({VShortcutAction::Undo, KeyBindingsToStringList(QKeySequence::Undo), {}}); + AddShortcut({VShortcutAction::Redo, KeyBindingsToStringList(QKeySequence::Redo), {}}); + AddShortcut({VShortcutAction::New, KeyBindingsToStringList(QKeySequence::New), {}}); + AddShortcut({VShortcutAction::Open, KeyBindingsToStringList(QKeySequence::Open), {}}); + AddShortcut({VShortcutAction::Save, KeyBindingsToStringList(QKeySequence::Save), {}}); + AddShortcut({VShortcutAction::SaveAs, KeyBindingsToStringList(QKeySequence::SaveAs), {}}); + AddShortcut( + {VShortcutAction::DrawMode, {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_W).toString()}, {}}); + AddShortcut( + {VShortcutAction::DetailsMode, {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_E).toString()}, {}}); + AddShortcut( + {VShortcutAction::LayoutMode, {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_L).toString()}, {}}); + AddShortcut( + {VShortcutAction::NewPatternPiece, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::ShiftModifier QKEY_SEQUENCE_OP Qt::Key_N).toString()}, + {}}); + AddShortcut({VShortcutAction::NextPatternPiece, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_PageDown).toString()}, + {}}); + AddShortcut({VShortcutAction::PreviusPatternPiece, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_PageUp).toString()}, + {}}); + AddShortcut({VShortcutAction::InteractiveTools, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_D).toString()}, + {}}); + AddShortcut({VShortcutAction::TableOfVariables, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_T).toString()}, + {}}); + AddShortcut({VShortcutAction::PatternHistory, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_H).toString()}, + {}}); + AddShortcut({VShortcutAction::Quit, KeyBindingsToStringList(QKeySequence::Quit), {}}); + AddShortcut({VShortcutAction::LastTool, {QKeySequence(Qt::Key_L).toString()}, {}}); + AddShortcut({VShortcutAction::CurveDetails, {QKeySequence(Qt::Key_F2).toString()}, {}}); + AddShortcut({VShortcutAction::FinalMeasurements, + {QKeySequence(Qt::ControlModifier QKEY_SEQUENCE_OP Qt::Key_I).toString()}, + {}}); + + AddShortcut({VShortcutAction::CaseSensitiveMatch, + {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_C).toString()}, + {}}); + AddShortcut( + {VShortcutAction::WholeWordMatch, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_W).toString()}, {}}); + AddShortcut( + {VShortcutAction::RegexMatch, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_X).toString()}, {}}); + AddShortcut( + {VShortcutAction::SearchHistory, {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_Down).toString()}, {}}); + AddShortcut({VShortcutAction::RegexMatchUnicodeProperties, + {QKeySequence(Qt::AltModifier QKEY_SEQUENCE_OP Qt::Key_U).toString()}, + {}}); + AddShortcut({VShortcutAction::FindNext, {QKeySequence(Qt::Key_F3).toString()}, {}}); + AddShortcut( + {VShortcutAction::FindPrevious, {QKeySequence(Qt::ShiftModifier QKEY_SEQUENCE_OP Qt::Key_F3).toString()}, {}}); + + QT_WARNING_POP +} diff --git a/src/app/valentina/core/vvalentinashortcutmanager.h b/src/app/valentina/core/vvalentinashortcutmanager.h new file mode 100644 index 000000000..d099b96c4 --- /dev/null +++ b/src/app/valentina/core/vvalentinashortcutmanager.h @@ -0,0 +1,49 @@ +/************************************************************************ + ** + ** @file vvalentinashortcutmanager.h + ** @author Roman Telezhynskyi + ** @date 20 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef VVALENTINASHORTCUTMANAGER_H +#define VVALENTINASHORTCUTMANAGER_H + +#include "../vmisc/vabstractshortcutmanager.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#include "../vmisc/defglobal.h" +#endif + +class VValentinaShortcutManager : public VAbstractShortcutManager +{ + Q_OBJECT // NOLINT + +public: + explicit VValentinaShortcutManager(QObject *parent = nullptr); + ~VValentinaShortcutManager() override = default; + +private: + Q_DISABLE_COPY_MOVE(VValentinaShortcutManager) // NOLINT +}; + +#endif // VVALENTINASHORTCUTMANAGER_H diff --git a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp index 4842cdbe5..30ff099f6 100644 --- a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp +++ b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.cpp @@ -30,10 +30,13 @@ #include "../../core/vapplication.h" #include "../qmuparser/qmudef.h" #include "../vganalytics/vganalytics.h" +#include "../vmisc/dialogs/vshortcutdialog.h" #include "../vmisc/literals.h" #include "../vmisc/theme/vtheme.h" +#include "../vmisc/vabstractshortcutmanager.h" #include "../vmisc/vvalentinasettings.h" #include "../vpatterndb/pmsystems.h" +#include "qpushbutton.h" #include "ui_preferencesconfigurationpage.h" #include "vcommonsettings.h" @@ -161,6 +164,12 @@ PreferencesConfigurationPage::PreferencesConfigurationPage(QWidget *parent) //----------------------- Update ui->checkBoxAutomaticallyCheckUpdates->setChecked(settings->IsAutomaticallyCheckUpdates()); + // Tab Shortcuts + InitShortcuts(); + connect(ui->pushButtonRestoreDefaults, &QPushButton::clicked, this, [this]() { InitShortcuts(true); }); + connect(ui->shortcutsTable, &QTableWidget::cellDoubleClicked, this, + &PreferencesConfigurationPage::ShortcutCellDoubleClicked); + // Tab Scrolling ui->spinBoxDuration->setMinimum(VCommonSettings::scrollingDurationMin); ui->spinBoxDuration->setMaximum(VCommonSettings::scrollingDurationMax); @@ -294,6 +303,19 @@ auto PreferencesConfigurationPage::Apply() -> QStringList settings->SetAutomaticallyCheckUpdates(ui->checkBoxAutomaticallyCheckUpdates->isChecked()); } + // Tab Shortcuts + if (VAbstractShortcutManager *manager = VAbstractValApplication::VApp()->GetShortcutManager()) + { + const auto &shortcutsList = manager->GetShortcutsList(); + for (int i = 0; i < m_transientShortcuts.length(); i++) + { + settings->SetActionShortcuts(VAbstractShortcutManager::ShortcutActionToString(shortcutsList.value(i).type), + m_transientShortcuts.value(i)); + } + + manager->UpdateShortcuts(); + } + // Tab Scrolling settings->SetScrollingDuration(ui->spinBoxDuration->value()); settings->SetScrollingUpdateInterval(ui->spinBoxUpdateInterval->value()); @@ -321,6 +343,20 @@ void PreferencesConfigurationPage::changeEvent(QEvent *event) QWidget::changeEvent(event); } +//--------------------------------------------------------------------------------------------------------------------- +void PreferencesConfigurationPage::ShortcutCellDoubleClicked(int row, int column) +{ + Q_UNUSED(column) + auto *shortcutDialog = new VShortcutDialog(row, this); + connect(shortcutDialog, &VShortcutDialog::ShortcutsListChanged, this, + [this](int index, const QStringList &stringListShortcuts) + { + m_transientShortcuts.replace(index, stringListShortcuts); + UpdateShortcutsTable(); + }); + shortcutDialog->open(); +} + //--------------------------------------------------------------------------------------------------------------------- void PreferencesConfigurationPage::SetLabelComboBox(const QStringList &list) { @@ -387,4 +423,78 @@ void PreferencesConfigurationPage::RetranslateUi() ui->comboBoxPieceLbelLanguage->blockSignals(false); ui->comboBoxPieceLbelLanguage->setCurrentIndex(ui->comboBoxPieceLbelLanguage->findData(code)); } + + RetranslateShortcutsTable(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PreferencesConfigurationPage::InitShortcuts(bool defaults) +{ + VAbstractShortcutManager *manager = VAbstractValApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return; + } + + manager->UpdateShortcuts(); + m_transientShortcuts.clear(); + ui->shortcutsTable->clearContents(); + const auto &shortcutsList = manager->GetShortcutsList(); + ui->shortcutsTable->setRowCount(static_cast(shortcutsList.length())); + + for (int i = 0; i < shortcutsList.length(); i++) + { + const VAbstractShortcutManager::VSShortcut &shortcut = shortcutsList.value(i); + + // Add shortcut to transient shortcut list + if (defaults) + { + m_transientShortcuts.append(shortcut.defaultShortcuts); + } + else + { + m_transientShortcuts.append(shortcut.shortcuts); + } + + // Add shortcut to table widget + auto *nameItem = new QTableWidgetItem(); + nameItem->setText(VAbstractShortcutManager::ReadableName(shortcut.type)); + ui->shortcutsTable->setItem(i, 0, nameItem); + + auto *shortcutsItem = new QTableWidgetItem(); + shortcutsItem->setText(VAbstractShortcutManager::StringListToReadableString(m_transientShortcuts.value(i))); + ui->shortcutsTable->setItem(i, 1, shortcutsItem); + } + UpdateShortcutsTable(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void PreferencesConfigurationPage::UpdateShortcutsTable() +{ + for (int i = 0; i < m_transientShortcuts.length(); i++) + { + const QStringList &shortcuts = m_transientShortcuts.value(i); + ui->shortcutsTable->item(i, 1)->setText(VAbstractShortcutManager::StringListToReadableString(shortcuts)); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void PreferencesConfigurationPage::RetranslateShortcutsTable() +{ + VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return; + } + + const auto &shortcutsList = manager->GetShortcutsList(); + for (int i = 0; i < shortcutsList.length(); i++) + { + const VAbstractShortcutManager::VSShortcut &shortcut = shortcutsList.value(i); + + if (QTableWidgetItem *it = ui->shortcutsTable->item(i, 0)) + { + it->setText(VAbstractShortcutManager::ReadableName(shortcut.type)); + } + } } diff --git a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.h b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.h index 563c284dc..45c0b4329 100644 --- a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.h +++ b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.h @@ -53,6 +53,9 @@ public: protected: void changeEvent(QEvent *event) override; +private slots: + void ShortcutCellDoubleClicked(int row, int column); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(PreferencesConfigurationPage) // NOLINT @@ -62,12 +65,16 @@ private: bool m_systemChanged{false}; bool m_unitChanged{false}; bool m_labelLangChanged{false}; + QList m_transientShortcuts{}; void SetLabelComboBox(const QStringList &list); void SetThemeModeComboBox(); void SetPointerModeComboBox(); void InitUnits(); void RetranslateUi(); + void InitShortcuts(bool defaults = false); + void UpdateShortcutsTable(); + void RetranslateShortcutsTable(); }; #endif // PREFERENCESCONFIGURATIONPAGE_H diff --git a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui index c516f2c90..fef5596c8 100644 --- a/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui +++ b/src/app/valentina/dialogs/configpages/preferencesconfigurationpage.ui @@ -17,7 +17,7 @@ - 0 + 1 @@ -33,7 +33,7 @@ 0 - -163 + 0 624 995 @@ -443,6 +443,87 @@ + + + Shortcuts + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + 0 + + + 2 + + + true + + + 150 + + + false + + + true + + + false + + + + Action + + + + + Shortcuts + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Restore defaults + + + + + + + Scrolling diff --git a/src/app/valentina/dialogs/dialogfinalmeasurements.cpp b/src/app/valentina/dialogs/dialogfinalmeasurements.cpp index 82050e185..efbfd3523 100644 --- a/src/app/valentina/dialogs/dialogfinalmeasurements.cpp +++ b/src/app/valentina/dialogs/dialogfinalmeasurements.cpp @@ -104,6 +104,21 @@ DialogFinalMeasurements::DialogFinalMeasurements(VPattern *doc, QWidget *parent) { ui->tableWidget->selectRow(0); } + + m_shortcuts.insert(VShortcutAction::CaseSensitiveMatch, ui->toolButtonCaseSensitive); + m_shortcuts.insert(VShortcutAction::WholeWordMatch, ui->toolButtonWholeWord); + m_shortcuts.insert(VShortcutAction::RegexMatch, ui->toolButtonRegexp); + m_shortcuts.insert(VShortcutAction::SearchHistory, ui->pushButtonSearch); + m_shortcuts.insert(VShortcutAction::RegexMatchUnicodeProperties, ui->toolButtonUseUnicodeProperties); + m_shortcuts.insert(VShortcutAction::FindNext, ui->toolButtonFindNext); + m_shortcuts.insert(VShortcutAction::FindPrevious, ui->toolButtonFindNext); + + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + connect(VAbstractValApplication::VApp()->GetShortcutManager(), &VAbstractShortcutManager::shortcutsUpdated, + this, &DialogFinalMeasurements::UpdateShortcuts); + UpdateShortcuts(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -491,6 +506,16 @@ void DialogFinalMeasurements::FullUpdateFromFile() m_search->RefreshList(ui->lineEditFind->text()); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogFinalMeasurements::UpdateShortcuts() +{ + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + manager->UpdateButtonShortcut(m_shortcuts); + UpdateSearchControlsTooltips(); + } +} + //--------------------------------------------------------------------------------------------------------------------- void DialogFinalMeasurements::FillFinalMeasurements(bool freshCall) { @@ -906,12 +931,18 @@ void DialogFinalMeasurements::SaveSearchRequest() //--------------------------------------------------------------------------------------------------------------------- void DialogFinalMeasurements::UpdateSearchControlsTooltips() { - auto UpdateToolTip = [](QAbstractButton *button) + auto UpdateToolTip = [this](QAbstractButton *button) { if (button->toolTip().contains("%1"_L1)) { + m_serachButtonTooltips.insert(button, button->toolTip()); button->setToolTip(button->toolTip().arg(button->shortcut().toString(QKeySequence::NativeText))); } + else if (m_serachButtonTooltips.contains(button)) + { + QString tooltip = m_serachButtonTooltips.value(button); + button->setToolTip(tooltip.arg(button->shortcut().toString(QKeySequence::NativeText))); + } }; UpdateToolTip(ui->toolButtonCaseSensitive); diff --git a/src/app/valentina/dialogs/dialogfinalmeasurements.h b/src/app/valentina/dialogs/dialogfinalmeasurements.h index 0a2103a95..d5d5b7e6e 100644 --- a/src/app/valentina/dialogs/dialogfinalmeasurements.h +++ b/src/app/valentina/dialogs/dialogfinalmeasurements.h @@ -31,6 +31,7 @@ #include +#include "../vmisc/vabstractshortcutmanager.h" #include "../vmisc/vtablesearch.h" #include "../vpatterndb/vcontainer.h" #include "../xml/vpattern.h" @@ -40,6 +41,8 @@ namespace Ui class DialogFinalMeasurements; } +class QAbstractButton; + class DialogFinalMeasurements : public QDialog { Q_OBJECT // NOLINT @@ -68,6 +71,7 @@ private slots: void DeployFormula(); void Fx(); void FullUpdateFromFile(); + void UpdateShortcuts(); private: Q_DISABLE_COPY_MOVE(DialogFinalMeasurements) // NOLINT @@ -82,6 +86,9 @@ private: QMenu *m_searchHistory; + QMultiHash m_shortcuts{}; + QHash m_serachButtonTooltips{}; + void FillFinalMeasurements(bool freshCall = false); void ShowUnits(); diff --git a/src/app/valentina/dialogs/dialoghistory.cpp b/src/app/valentina/dialogs/dialoghistory.cpp index f38bff851..f591b76c8 100644 --- a/src/app/valentina/dialogs/dialoghistory.cpp +++ b/src/app/valentina/dialogs/dialoghistory.cpp @@ -88,6 +88,21 @@ DialogHistory::DialogHistory(VContainer *data, VPattern *doc, QWidget *parent) ShowPoint(); InitSearch(); + + m_shortcuts.insert(VShortcutAction::CaseSensitiveMatch, ui->toolButtonCaseSensitive); + m_shortcuts.insert(VShortcutAction::WholeWordMatch, ui->toolButtonWholeWord); + m_shortcuts.insert(VShortcutAction::RegexMatch, ui->toolButtonRegexp); + m_shortcuts.insert(VShortcutAction::SearchHistory, ui->pushButtonSearch); + m_shortcuts.insert(VShortcutAction::RegexMatchUnicodeProperties, ui->toolButtonUseUnicodeProperties); + m_shortcuts.insert(VShortcutAction::FindNext, ui->toolButtonFindNext); + m_shortcuts.insert(VShortcutAction::FindPrevious, ui->toolButtonFindNext); + + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + connect(VAbstractValApplication::VApp()->GetShortcutManager(), &VAbstractShortcutManager::shortcutsUpdated, + this, &DialogHistory::UpdateShortcuts); + UpdateShortcuts(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -571,6 +586,16 @@ void DialogHistory::showEvent(QShowEvent *event) QDialog::showEvent(event); // return default behavior NOLINT(bugprone-parent-virtual-call) } +//--------------------------------------------------------------------------------------------------------------------- +void DialogHistory::UpdateShortcuts() +{ + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + manager->UpdateButtonShortcut(m_shortcuts); + UpdateSearchControlsTooltips(); + } +} + //--------------------------------------------------------------------------------------------------------------------- void DialogHistory::RetranslateUi() { @@ -784,12 +809,18 @@ void DialogHistory::SaveSearchRequest() //--------------------------------------------------------------------------------------------------------------------- void DialogHistory::UpdateSearchControlsTooltips() { - auto UpdateToolTip = [](QAbstractButton *button) + auto UpdateToolTip = [this](QAbstractButton *button) { if (button->toolTip().contains("%1"_L1)) { + m_serachButtonTooltips.insert(button, button->toolTip()); button->setToolTip(button->toolTip().arg(button->shortcut().toString(QKeySequence::NativeText))); } + else if (m_serachButtonTooltips.contains(button)) + { + QString tooltip = m_serachButtonTooltips.value(button); + button->setToolTip(tooltip.arg(button->shortcut().toString(QKeySequence::NativeText))); + } }; UpdateToolTip(ui->toolButtonCaseSensitive); diff --git a/src/app/valentina/dialogs/dialoghistory.h b/src/app/valentina/dialogs/dialoghistory.h index 987672514..219c47e4d 100644 --- a/src/app/valentina/dialogs/dialoghistory.h +++ b/src/app/valentina/dialogs/dialoghistory.h @@ -29,6 +29,7 @@ #ifndef DIALOGHISTORY_H #define DIALOGHISTORY_H +#include "../vmisc/vabstractshortcutmanager.h" #include "../vtools/dialogs/tools/dialogtool.h" #include @@ -80,6 +81,9 @@ protected: auto IsValid() const -> bool final { return true; } void showEvent(QShowEvent *event) override; +private slots: + void UpdateShortcuts(); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(DialogHistory) // NOLINT @@ -96,6 +100,9 @@ private: QMenu *m_searchHistory; + QMultiHash m_shortcuts{}; + QHash m_serachButtonTooltips{}; + void FillTable(); auto Record(const VToolRecord &tool) const -> HistoryRecord; auto RecordDescription(const VToolRecord &tool, HistoryRecord record, const QDomElement &domElem) const diff --git a/src/app/valentina/dialogs/dialogincrements.cpp b/src/app/valentina/dialogs/dialogincrements.cpp index b3701c4de..a6ee891ba 100644 --- a/src/app/valentina/dialogs/dialogincrements.cpp +++ b/src/app/valentina/dialogs/dialogincrements.cpp @@ -185,6 +185,29 @@ DialogIncrements::DialogIncrements(VContainer *data, VPattern *doc, QWidget *par { ui->tableWidgetPC->selectRow(0); } + + m_shortcuts.insert(VShortcutAction::CaseSensitiveMatch, ui->toolButtonCaseSensitive); + m_shortcuts.insert(VShortcutAction::WholeWordMatch, ui->toolButtonWholeWord); + m_shortcuts.insert(VShortcutAction::RegexMatch, ui->toolButtonRegexp); + m_shortcuts.insert(VShortcutAction::SearchHistory, ui->pushButtonSearch); + m_shortcuts.insert(VShortcutAction::RegexMatchUnicodeProperties, ui->toolButtonUseUnicodeProperties); + m_shortcuts.insert(VShortcutAction::FindNext, ui->toolButtonFindNext); + m_shortcuts.insert(VShortcutAction::FindPrevious, ui->toolButtonFindNext); + + m_shortcuts.insert(VShortcutAction::CaseSensitiveMatch, ui->toolButtonCaseSensitivePC); + m_shortcuts.insert(VShortcutAction::WholeWordMatch, ui->toolButtonWholeWordPC); + m_shortcuts.insert(VShortcutAction::RegexMatch, ui->toolButtonRegexpPC); + m_shortcuts.insert(VShortcutAction::SearchHistory, ui->pushButtonSearchPC); + m_shortcuts.insert(VShortcutAction::RegexMatchUnicodeProperties, ui->toolButtonUseUnicodePropertiesPC); + m_shortcuts.insert(VShortcutAction::FindNext, ui->toolButtonFindNextPC); + m_shortcuts.insert(VShortcutAction::FindPrevious, ui->toolButtonFindNextPC); + + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + connect(VAbstractValApplication::VApp()->GetShortcutManager(), &VAbstractShortcutManager::shortcutsUpdated, + this, &DialogIncrements::UpdateShortcuts); + UpdateShortcuts(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -1195,12 +1218,18 @@ void DialogIncrements::SavePreviewCalculationsSearchRequest() //--------------------------------------------------------------------------------------------------------------------- void DialogIncrements::UpdateSearchControlsTooltips() { - auto UpdateToolTip = [](QAbstractButton *button) + auto UpdateToolTip = [this](QAbstractButton *button) { if (button->toolTip().contains("%1"_L1)) { + m_serachButtonTooltips.insert(button, button->toolTip()); button->setToolTip(button->toolTip().arg(button->shortcut().toString(QKeySequence::NativeText))); } + else if (m_serachButtonTooltips.contains(button)) + { + QString tooltip = m_serachButtonTooltips.value(button); + button->setToolTip(tooltip.arg(button->shortcut().toString(QKeySequence::NativeText))); + } }; UpdateToolTip(ui->toolButtonCaseSensitive); @@ -1337,6 +1366,16 @@ void DialogIncrements::RefreshPattern() } } +//--------------------------------------------------------------------------------------------------------------------- +void DialogIncrements::UpdateShortcuts() +{ + if (VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager()) + { + manager->UpdateButtonShortcut(m_shortcuts); + UpdateSearchControlsTooltips(); + } +} + //--------------------------------------------------------------------------------------------------------------------- void DialogIncrements::FillIncrementsTable(QTableWidget *table, const QMap> &increments, diff --git a/src/app/valentina/dialogs/dialogincrements.h b/src/app/valentina/dialogs/dialogincrements.h index 24aac224b..51c4a87d3 100644 --- a/src/app/valentina/dialogs/dialogincrements.h +++ b/src/app/valentina/dialogs/dialogincrements.h @@ -29,6 +29,7 @@ #ifndef DIALOGINCREMENTS_H #define DIALOGINCREMENTS_H +#include "../vmisc/vabstractshortcutmanager.h" #include "../vmisc/vtablesearch.h" #include "../vtools/dialogs/tools/dialogtool.h" #include "../xml/vpattern.h" @@ -82,6 +83,7 @@ private slots: void DeployFormula(); void Fx(); void RefreshPattern(); + void UpdateShortcuts(); private: // cppcheck-suppress unknownMacro @@ -112,6 +114,9 @@ private: QMenu *m_searchHistory; QMenu *m_searchHistoryPC; + QMultiHash m_shortcuts{}; + QHash m_serachButtonTooltips{}; + template void FillTable(const QMap &varTable, QTableWidget *table); static void FillIncrementsTable(QTableWidget *table, const QMap> &increments, diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index fccc55dc1..76e53e6e6 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -193,6 +193,7 @@ #include "dialogs/vwidgetgroups.h" #include "ui_mainwindow.h" #include "vabstractapplication.h" +#include "vabstractshortcutmanager.h" #include "vsinglelineoutlinechar.h" #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -396,6 +397,7 @@ MainWindow::MainWindow(QWidget *parent) ToolBarStages(); ToolBarDrawTools(); InitToolButtons(); + InitActionShortcuts(); connect(ui->actionAddBackgroundImage, &QAction::triggered, this, &MainWindow::ActionAddBackgroundImage); connect(ui->actionExportFontCorrections, &QAction::triggered, this, &MainWindow::ActionExportFontCorrections); @@ -533,6 +535,12 @@ MainWindow::MainWindow(QWidget *parent) } ui->actionExportFontCorrections->setEnabled(settings->GetSingleStrokeOutlineFont()); + + if (VAbstractShortcutManager *manager = VAbstractValApplication::VApp()->GetShortcutManager()) + { + connect(manager, &VAbstractShortcutManager::shortcutsUpdated, this, &MainWindow::UpdateShortcuts); + UpdateShortcuts(); + } } //--------------------------------------------------------------------------------------------------------------------- @@ -2943,83 +2951,25 @@ void MainWindow::ToolBarDraws() //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolBarTools() { - /*First we will try use Standard Shortcuts from Qt, but because keypad "-" and "+" not the same keys like in main - keypad, shortcut Ctrl+"-" or "+" from keypad will not working with standard shortcut (QKeySequence::ZoomIn or - QKeySequence::ZoomOut). For examle "+" is Qt::Key_Plus + Qt::KeypadModifier for keypad. - Also for me don't work Qt:CTRL and work Qt::ControlModifier.*/ - - QT_WARNING_PUSH -#if !defined(Q_OS_MACOS) && defined(Q_CC_CLANG) - QT_WARNING_DISABLE_CLANG("-Wenum-enum-conversion") -#endif - - QList zoomInShortcuts; - zoomInShortcuts.append(QKeySequence(QKeySequence::ZoomIn)); - zoomInShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(QKeyCombination(Qt::ControlModifier), Qt::Key_Plus | Qt::KeypadModifier)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_Plus + Qt::KeypadModifier)); -#endif - ui->actionZoomIn->setShortcuts(zoomInShortcuts); + m_shortcutActions.insert(VShortcutAction::ZoomIn, ui->actionZoomIn); connect(ui->actionZoomIn, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomIn); - QList zoomOutShortcuts; - zoomOutShortcuts.append(QKeySequence(QKeySequence::ZoomOut)); - zoomOutShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(QKeyCombination(Qt::ControlModifier), Qt::Key_Minus | Qt::KeypadModifier)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_Minus + Qt::KeypadModifier)); -#endif - ui->actionZoomOut->setShortcuts(zoomOutShortcuts); + m_shortcutActions.insert(VShortcutAction::ZoomOut, ui->actionZoomOut); connect(ui->actionZoomOut, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomOut); - QList zoomOriginalShortcuts; - zoomOriginalShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ControlModifier | Qt::Key_0)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_0)); -#endif - zoomOriginalShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(QKeyCombination(Qt::ControlModifier), Qt::Key_0 | Qt::KeypadModifier)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_0 + Qt::KeypadModifier)); -#endif - ui->actionZoomOriginal->setShortcuts(zoomOriginalShortcuts); + m_shortcutActions.insert(VShortcutAction::ZoomOriginal, ui->actionZoomOriginal); connect(ui->actionZoomOriginal, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomOriginal); - QList zoomFitBestShortcuts; - zoomFitBestShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ControlModifier | Qt::Key_Equal)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_Equal)); -#endif - ui->actionZoomFitBest->setShortcuts(zoomFitBestShortcuts); + m_shortcutActions.insert(VShortcutAction::ZoomFitBest, ui->actionZoomFitBest); connect(ui->actionZoomFitBest, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomFitBest); - QList zoomFitBestCurrentShortcuts; - zoomFitBestCurrentShortcuts.append( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ControlModifier | Qt::Key_M)); -#else - QKeySequence(Qt::ControlModifier + Qt::Key_M)); -#endif - ui->actionZoomFitBestCurrent->setShortcuts(zoomFitBestCurrentShortcuts); + m_shortcutActions.insert(VShortcutAction::ZoomFitBestCurrent, ui->actionZoomFitBestCurrent); connect(ui->actionZoomFitBestCurrent, &QAction::triggered, this, &MainWindow::ZoomFitBestCurrent); connect(ui->actionPreviousPatternPiece, &QAction::triggered, this, &MainWindow::PreviousPatternPiece); connect(ui->actionNextPatternPiece, &QAction::triggered, this, &MainWindow::NextPatternPiece); - ui->actionIncreaseLabelFont->setShortcut( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ShiftModifier | Qt::Key_Plus)); -#else - QKeySequence(Qt::ShiftModifier + Qt::Key_Plus)); -#endif + m_shortcutActions.insert(VShortcutAction::IncreaseLabelFont, ui->actionIncreaseLabelFont); connect(ui->actionIncreaseLabelFont, &QAction::triggered, this, [this]() { @@ -3036,12 +2986,7 @@ void MainWindow::ToolBarTools() } }); - ui->actionDecreaseLabelFont->setShortcut( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ShiftModifier | Qt::Key_Minus)); -#else - QKeySequence(Qt::ShiftModifier + Qt::Key_Minus)); -#endif + m_shortcutActions.insert(VShortcutAction::DecreaseLabelFont, ui->actionDecreaseLabelFont); connect(ui->actionDecreaseLabelFont, &QAction::triggered, this, [this]() { @@ -3058,12 +3003,7 @@ void MainWindow::ToolBarTools() } }); - ui->actionOriginalLabelFont->setShortcut( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::ShiftModifier | Qt::Key_0)); -#else - QKeySequence(Qt::ShiftModifier + Qt::Key_0)); -#endif + m_shortcutActions.insert(VShortcutAction::OriginalLabelFont, ui->actionOriginalLabelFont); connect(ui->actionOriginalLabelFont, &QAction::triggered, this, [this]() { @@ -3080,12 +3020,7 @@ void MainWindow::ToolBarTools() } }); - ui->actionHideLabels->setShortcut( -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QKeySequence(Qt::AltModifier | Qt::Key_L)); -#else - QKeySequence(Qt::AltModifier + Qt::Key_L)); -#endif + m_shortcutActions.insert(VShortcutAction::HideLabels, ui->actionHideLabels); ui->actionHideLabels->setChecked(VAbstractValApplication::VApp()->ValentinaSettings()->GetHideLabels()); connect(ui->actionHideLabels, &QAction::triggered, this, [this](bool checked) @@ -3101,8 +3036,6 @@ void MainWindow::ToolBarTools() m_sceneDetails->update(); } }); - - QT_WARNING_POP } //--------------------------------------------------------------------------------------------------------------------- @@ -3438,6 +3371,28 @@ void MainWindow::InitToolButtons() connect(ui->actionPlaceLabelTool, &QAction::triggered, this, &MainWindow::ToolPlaceLabel); } +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::InitActionShortcuts() +{ + m_shortcutActions.insert(VShortcutAction::New, ui->actionNew); + m_shortcutActions.insert(VShortcutAction::Open, ui->actionOpen); + m_shortcutActions.insert(VShortcutAction::Save, ui->actionSave); + m_shortcutActions.insert(VShortcutAction::SaveAs, ui->actionSaveAs); + m_shortcutActions.insert(VShortcutAction::DrawMode, ui->actionDraw); + m_shortcutActions.insert(VShortcutAction::DetailsMode, ui->actionDetails); + m_shortcutActions.insert(VShortcutAction::LayoutMode, ui->actionLayout); + m_shortcutActions.insert(VShortcutAction::NewPatternPiece, ui->actionNewDraw); + m_shortcutActions.insert(VShortcutAction::NextPatternPiece, ui->actionNextPatternPiece); + m_shortcutActions.insert(VShortcutAction::PreviusPatternPiece, ui->actionPreviousPatternPiece); + m_shortcutActions.insert(VShortcutAction::InteractiveTools, ui->actionInteractiveTools); + m_shortcutActions.insert(VShortcutAction::TableOfVariables, ui->actionTable); + m_shortcutActions.insert(VShortcutAction::PatternHistory, ui->actionHistory); + m_shortcutActions.insert(VShortcutAction::Quit, ui->actionExit); + m_shortcutActions.insert(VShortcutAction::LastTool, ui->actionLast_tool); + m_shortcutActions.insert(VShortcutAction::CurveDetails, ui->actionShowCurveDetails); + m_shortcutActions.insert(VShortcutAction::FinalMeasurements, ui->actionFinalMeasurements); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief mouseMove save mouse position and show user. @@ -5202,6 +5157,15 @@ void MainWindow::ActionOpenTape_triggered() VApplication::StartDetachedProcess(VApplication::TapeFilePath(), arguments); } +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::UpdateShortcuts() +{ + if (VAbstractShortcutManager *manager = VAbstractValApplication::VApp()->GetShortcutManager()) + { + manager->UpdateActionShortcuts(m_shortcutActions); + } +} + //--------------------------------------------------------------------------------------------------------------------- void MainWindow::InitDimensionControls() { @@ -5643,6 +5607,11 @@ void MainWindow::ReadSettings() QFont f = ui->plainTextEditPatternMessages->font(); f.setPointSize(qMax(settings->GetPatternMessageFontSize(f.pointSize()), 1)); ui->plainTextEditPatternMessages->setFont(f); + + if (VAbstractShortcutManager *manager = VAbstractValApplication::VApp()->GetShortcutManager()) + { + manager->UpdateShortcuts(); + } } else { @@ -5736,14 +5705,14 @@ void MainWindow::CreateMenus() // Add Undo/Redo actions. undoAction = VAbstractApplication::VApp()->getUndoStack()->createUndoAction(this, tr("&Undo")); connect(undoAction, &QAction::triggered, m_toolOptions, &VToolOptionsPropertyBrowser::RefreshOptions); - undoAction->setShortcuts(QKeySequence::Undo); + m_shortcutActions.insert(VShortcutAction::Undo, undoAction); undoAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo"))); ui->menuPatternPiece->insertAction(ui->actionLast_tool, undoAction); ui->toolBarTools->addAction(undoAction); redoAction = VAbstractApplication::VApp()->getUndoStack()->createRedoAction(this, tr("&Redo")); connect(redoAction, &QAction::triggered, m_toolOptions, &VToolOptionsPropertyBrowser::RefreshOptions); - redoAction->setShortcuts(QKeySequence::Redo); + m_shortcutActions.insert(VShortcutAction::Redo, redoAction); redoAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-redo"))); ui->menuPatternPiece->insertAction(ui->actionLast_tool, redoAction); ui->toolBarTools->addAction(redoAction); diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h index 88da421ba..b8ffbba45 100644 --- a/src/app/valentina/mainwindow.h +++ b/src/app/valentina/mainwindow.h @@ -30,6 +30,7 @@ #define MAINWINDOW_H #include "../vformat/vdimensions.h" +#include "../vmisc/vabstractshortcutmanager.h" #include "../vmisc/vlockguard.h" #include "core/vcmdexport.h" #include "mainwindowsnogui.h" @@ -254,6 +255,8 @@ private slots: void ActionShowMainPath_triggered(bool checked); void ActionOpenTape_triggered(); + void UpdateShortcuts(); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(MainWindow) // NOLINT @@ -338,6 +341,8 @@ private: bool m_patternMessagesActive{false}; bool m_backgroundImagesActive{false}; + QMultiHash m_shortcutActions{}; + void InitDimensionControls(); void InitDimensionGradation(int index, const MeasurementDimension_p &dimension, const QPointer &control); static void InitDimensionXGradation(const QVector &bases, const DimesionLabels &labels, @@ -351,6 +356,7 @@ private: void ToolBarTools(); void ToolBarDrawTools(); void InitToolButtons(); + void InitActionShortcuts(); void CancelTool(); void SetupDrawToolsIcons(); diff --git a/src/app/valentina/valentina.pri b/src/app/valentina/valentina.pri index ee92ea3db..e5b425f6d 100644 --- a/src/app/valentina/valentina.pri +++ b/src/app/valentina/valentina.pri @@ -10,7 +10,8 @@ include(core/core.pri) SOURCES += \ $$PWD/main.cpp \ $$PWD/mainwindow.cpp \ - $$PWD/mainwindowsnogui.cpp + $$PWD/mainwindowsnogui.cpp \ + $$PWD/vvalentinashortcutmanager.cpp *msvc*:SOURCES += $$PWD/stable.cpp @@ -19,7 +20,8 @@ HEADERS += \ $$PWD/mainwindow.h \ $$PWD/stable.h \ $$PWD/version.h \ - $$PWD/mainwindowsnogui.h + $$PWD/mainwindowsnogui.h \ + $$PWD/vvalentinashortcutmanager.h # Main forms FORMS += \ diff --git a/src/app/valentina/valentina.qbs b/src/app/valentina/valentina.qbs index d46037d3e..481df0252 100644 --- a/src/app/valentina/valentina.qbs +++ b/src/app/valentina/valentina.qbs @@ -161,12 +161,13 @@ VToolApp { "vformulapropertyeditor.h", "vtooloptionspropertybrowser.h", "vcmdexport.h", - "vapplication.cpp", "vformulaproperty.cpp", "vformulapropertyeditor.cpp", "vtooloptionspropertybrowser.cpp", - "vcmdexport.cpp" + "vcmdexport.cpp", + "vvalentinashortcutmanager.cpp", + "vvalentinashortcutmanager.h", ] } diff --git a/src/libs/vmisc/dialogs/vshortcutdialog.cpp b/src/libs/vmisc/dialogs/vshortcutdialog.cpp new file mode 100644 index 000000000..fc8066b54 --- /dev/null +++ b/src/libs/vmisc/dialogs/vshortcutdialog.cpp @@ -0,0 +1,139 @@ +/************************************************************************ + ** + ** @file vshortcutdialog.cpp + ** @author Roman Telezhynskyi + ** @date 21 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "vshortcutdialog.h" +#include "../vabstractapplication.h" +#include "ui_vshortcutdialog.h" + +#include + +#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) +#include "../compatibility.h" +#endif + +using namespace Qt::Literals::StringLiterals; + +namespace +{ +//--------------------------------------------------------------------------------------------------------------------- +auto ShortcutAlreadyBound(const QKeySequence &chosenSequence, const VShortcutAction &exemptShortcut) -> QString +{ + if (chosenSequence.isEmpty()) + { + return {}; + } + + VAbstractShortcutManager *manager = VAbstractApplication::VApp()->GetShortcutManager(); + if (manager == nullptr) + { + return {}; + } + + const auto &shortcutsList = manager->GetShortcutsList(); + for (const auto &shortcut : shortcutsList) + { + auto sequenceList = VAbstractShortcutManager::StringListToKeySequenceList(shortcut.shortcuts); + + if (sequenceList.contains(chosenSequence) && shortcut.type != exemptShortcut) + { + return VAbstractShortcutManager::ReadableName(shortcut.type); + } + } + return {}; +} +} // namespace + +//--------------------------------------------------------------------------------------------------------------------- +VShortcutDialog::VShortcutDialog(int index, QWidget *parent) + : QDialog(parent), + ui(new Ui::VShortcutDialog), + m_index(index) +{ + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose); + setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint | Qt::CustomizeWindowHint)); + + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &VShortcutDialog::ButtonBoxClicked); + + m_shortcutObject = VAbstractApplication::VApp()->GetShortcutManager()->GetShortcutsList().value(index); + ui->keySequenceEdit->setKeySequence(m_shortcutObject.shortcuts.join(", "_L1)); +} + +//--------------------------------------------------------------------------------------------------------------------- +VShortcutDialog::~VShortcutDialog() +{ + delete ui; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VShortcutDialog::AcceptValidated() +{ + QDialog::done(1); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VShortcutDialog::ButtonBoxClicked(QAbstractButton *button) +{ + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) + { + QStringList shortcutsStringList = ui->keySequenceEdit->keySequence().toString().split(", "_L1); + const auto sequenceList = VAbstractShortcutManager::StringListToKeySequenceList(shortcutsStringList); + + for (const auto &sequence : sequenceList) + { + auto conflictingShortcut = ShortcutAlreadyBound(sequence, m_shortcutObject.type); + if (!conflictingShortcut.isEmpty()) + { + QString nativeShortcutString = sequence.toString(QKeySequence::NativeText); + QMessageBox::warning( + this, tr("Shortcut Already Used"), + tr(R"("%1" is already bound to "%2")").arg(nativeShortcutString, conflictingShortcut)); + return; + } + } + + AcceptValidated(); + + emit ShortcutsListChanged(m_index, shortcutsStringList); + } + else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) + { + ui->keySequenceEdit->setKeySequence(m_shortcutObject.defaultShortcuts.join(", "_L1)); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VShortcutDialog::done(int r) +{ + if (r == QDialog::Accepted) + { + return; + } + + QDialog::done(r); +} diff --git a/src/libs/vmisc/dialogs/vshortcutdialog.h b/src/libs/vmisc/dialogs/vshortcutdialog.h new file mode 100644 index 000000000..616f76793 --- /dev/null +++ b/src/libs/vmisc/dialogs/vshortcutdialog.h @@ -0,0 +1,67 @@ +/************************************************************************ + ** + ** @file vshortcutdialog.h + ** @author Roman Telezhynskyi + ** @date 21 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef VSHORTCUTDIALOG_H +#define VSHORTCUTDIALOG_H + +#include + +#include "../vabstractshortcutmanager.h" + +namespace Ui +{ +class VShortcutDialog; +} + +class QAbstractButton; + +class VShortcutDialog : public QDialog +{ + Q_OBJECT // NOLINT + +public: + explicit VShortcutDialog(int index, QWidget *parent = nullptr); + ~VShortcutDialog() override; + +signals: + void ShortcutsListChanged(int index, QStringList shortcutsStringList); + +private slots: + void ButtonBoxClicked(QAbstractButton *button); + +private: + Q_DISABLE_COPY_MOVE(VShortcutDialog) // NOLINT + + Ui::VShortcutDialog *ui; + VAbstractShortcutManager::VSShortcut m_shortcutObject{}; + int m_index; + + void AcceptValidated(); + void done(int r) override; +}; + +#endif // VSHORTCUTDIALOG_H diff --git a/src/libs/vmisc/dialogs/vshortcutdialog.ui b/src/libs/vmisc/dialogs/vshortcutdialog.ui new file mode 100644 index 000000000..c1d24e513 --- /dev/null +++ b/src/libs/vmisc/dialogs/vshortcutdialog.ui @@ -0,0 +1,71 @@ + + + VShortcutDialog + + + + 0 + 0 + 366 + 74 + + + + Dialog + + + + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + + + + + + + buttonBox + accepted() + VShortcutDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + VShortcutDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/libs/vmisc/vabstractapplication.cpp b/src/libs/vmisc/vabstractapplication.cpp index cf15d6cac..de5d8c65e 100644 --- a/src/libs/vmisc/vabstractapplication.cpp +++ b/src/libs/vmisc/vabstractapplication.cpp @@ -443,6 +443,12 @@ auto VAbstractApplication::AppUptime() const -> qint64 return m_uptimeTimer.elapsed(); } +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractApplication::GetShortcutManager() const -> VAbstractShortcutManager * +{ + return m_shortcutManager; +} + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) //--------------------------------------------------------------------------------------------------------------------- auto VAbstractApplication::TextCodecCache(QStringConverter::Encoding encoding) const -> VTextCodec * diff --git a/src/libs/vmisc/vabstractapplication.h b/src/libs/vmisc/vabstractapplication.h index 627c1863a..e46fb2a3f 100644 --- a/src/libs/vmisc/vabstractapplication.h +++ b/src/libs/vmisc/vabstractapplication.h @@ -50,6 +50,7 @@ class VAbstractApplication; // use in define class VCommonSettings; class VSvgFontDatabase; class QFileSystemWatcher; +class VAbstractShortcutManager; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) class VTextCodec; @@ -106,6 +107,8 @@ public: auto AppUptime() const -> qint64; + auto GetShortcutManager() const -> VAbstractShortcutManager *; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, hicpp-avoid-c-arrays, modernize-avoid-c-arrays) static auto IsOptionSet(int argc, char *argv[], const char *option) -> bool; // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, hicpp-avoid-c-arrays, modernize-avoid-c-arrays) @@ -129,6 +132,8 @@ protected: QElapsedTimer m_uptimeTimer{}; + VAbstractShortcutManager *m_shortcutManager{nullptr}; + virtual void InitTrVars() = 0; static void CheckSystemLocale(); diff --git a/src/libs/vmisc/vabstractshortcutmanager.cpp b/src/libs/vmisc/vabstractshortcutmanager.cpp new file mode 100644 index 000000000..4178415f2 --- /dev/null +++ b/src/libs/vmisc/vabstractshortcutmanager.cpp @@ -0,0 +1,345 @@ +/************************************************************************ + ** + ** @file vabstractshortcutmanager.cpp + ** @author Roman Telezhynskyi + ** @date 20 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "vabstractshortcutmanager.h" + +#include +#include +#include + +#include "qassert.h" +#include "qtpreprocessorsupport.h" +#include "vabstractapplication.h" +#include "vcommonsettings.h" + +#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) +#include "compatibility.h" +#endif + +using namespace Qt::Literals::StringLiterals; + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractShortcutManager::VAbstractShortcutManager(QObject *parent) + : QObject{parent} +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractShortcutManager::UpdateShortcuts() +{ + VCommonSettings *settings = VAbstractApplication::VApp()->Settings(); + // Set all shortcuts to the user-set shortcut or the default + for (auto &shortcut : m_shortcutsList) + { + shortcut.shortcuts = + settings->GetActionShortcuts(ShortcutActionToString(shortcut.type), shortcut.defaultShortcuts); + } + + emit shortcutsUpdated(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractShortcutManager::UpdateActionShortcuts(const QMultiHash &actions) +{ + for (const auto &shortcut : m_shortcutsList) + { + const auto actionList = actions.values(shortcut.type); + + for (const auto &action : actionList) + { + if (action) + { + action->setShortcuts(StringListToKeySequenceList(shortcut.shortcuts)); + } + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractShortcutManager::UpdateButtonShortcut(const QMultiHash &buttons) +{ + for (const auto &shortcut : m_shortcutsList) + { + const auto buttonList = buttons.values(shortcut.type); + + for (const auto &button : buttonList) + { + if (button) + { + QList keySequence = StringListToKeySequenceList(shortcut.shortcuts); + if (!keySequence.isEmpty()) + { + button->setShortcut(keySequence.constFirst()); + } + } + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::GetShortcutsList() const -> QList +{ + return m_shortcutsList; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::ShortcutActionToString(VShortcutAction type) -> QString +{ + Q_STATIC_ASSERT_X(static_cast(VShortcutAction::LAST_ONE_DO_NOT_USE) == 35, "Convert all actions."); + + switch (type) + { + case VShortcutAction::ZoomIn: + return "zoomin"_L1; + case VShortcutAction::ZoomOut: + return "zoomout"_L1; + case VShortcutAction::ZoomOriginal: + return "zoomoriginal"_L1; + case VShortcutAction::ZoomFitBest: + return "zoomfitbest"_L1; + case VShortcutAction::ZoomFitBestCurrent: + return "zoomfitbestcurrent"_L1; + case VShortcutAction::IncreaseLabelFont: + return "increaselabelfont"_L1; + case VShortcutAction::DecreaseLabelFont: + return "decreaselabelfont"_L1; + case VShortcutAction::OriginalLabelFont: + return "originallabelfont"_L1; + case VShortcutAction::HideLabels: + return "hidelabels"_L1; + case VShortcutAction::Undo: + return "undo"_L1; + case VShortcutAction::Redo: + return "redo"_L1; + case VShortcutAction::New: + return "new"_L1; + case VShortcutAction::Open: + return "open"_L1; + case VShortcutAction::Save: + return "save"_L1; + case VShortcutAction::SaveAs: + return "saveas"_L1; + case VShortcutAction::DrawMode: + return "drawmode"_L1; + case VShortcutAction::DetailsMode: + return "detailsmode"_L1; + case VShortcutAction::LayoutMode: + return "layoutmode"_L1; + case VShortcutAction::NewPatternPiece: + return "newpatternpiece"_L1; + case VShortcutAction::NextPatternPiece: + return "nextpatternpiece"_L1; + case VShortcutAction::PreviusPatternPiece: + return "previuspatternpiece"_L1; + case VShortcutAction::InteractiveTools: + return "interactivetools"_L1; + case VShortcutAction::TableOfVariables: + return "tableofvariables"_L1; + case VShortcutAction::PatternHistory: + return "patternhistory"_L1; + case VShortcutAction::Quit: + return "quit"_L1; + case VShortcutAction::LastTool: + return "lasttool"_L1; + case VShortcutAction::CurveDetails: + return "curvedetails"_L1; + case VShortcutAction::FinalMeasurements: + return "finalmeasurements"_L1; + case VShortcutAction::CaseSensitiveMatch: + return "casesensitivematch"_L1; + case VShortcutAction::WholeWordMatch: + return "wholewordmatch"_L1; + case VShortcutAction::RegexMatch: + return "regexmatch"_L1; + case VShortcutAction::SearchHistory: + return "searchhistory"_L1; + case VShortcutAction::RegexMatchUnicodeProperties: + return "regexmatchunicodeproperties"_L1; + case VShortcutAction::FindNext: + return "findnext"_L1; + case VShortcutAction::FindPrevious: + return "findprevious"_L1; + case VShortcutAction::LAST_ONE_DO_NOT_USE: + Q_UNREACHABLE(); + break; + }; + return {}; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::ReadableName(VShortcutAction type) -> QString +{ + Q_STATIC_ASSERT_X(static_cast(VShortcutAction::LAST_ONE_DO_NOT_USE) == 35, "Translate all actions."); + + switch (type) + { + case VShortcutAction::ZoomIn: + return tr("Zoom in", "shortcut for action"); + case VShortcutAction::ZoomOut: + return tr("Zoom out", "shortcut for action"); + case VShortcutAction::ZoomOriginal: + return tr("Zoom original", "shortcut for action"); + case VShortcutAction::ZoomFitBest: + return tr("Zoom fit best", "shortcut for action"); + case VShortcutAction::ZoomFitBestCurrent: + return tr("Zoom fit best current", "shortcut for action"); + case VShortcutAction::IncreaseLabelFont: + return tr("Increase point label font size", "shortcut for action"); + case VShortcutAction::DecreaseLabelFont: + return tr("Decrease point label font size", "shortcut for action"); + case VShortcutAction::OriginalLabelFont: + return tr("Original point label font size", "shortcut for action"); + case VShortcutAction::HideLabels: + return tr("Hide point labels", "shortcut for action"); + case VShortcutAction::Undo: + return tr("Undo", "shortcut for action"); + case VShortcutAction::Redo: + return tr("Redo", "shortcut for action"); + case VShortcutAction::New: + return tr("New", "shortcut for action"); + case VShortcutAction::Open: + return tr("Open", "shortcut for action"); + case VShortcutAction::Save: + return tr("Save", "shortcut for action"); + case VShortcutAction::SaveAs: + return tr("Save as", "shortcut for action"); + case VShortcutAction::DrawMode: + return tr("Draw mode", "shortcut for action"); + case VShortcutAction::DetailsMode: + return tr("Details mode", "shortcut for action"); + case VShortcutAction::LayoutMode: + return tr("Layout mode", "shortcut for action"); + case VShortcutAction::NewPatternPiece: + return tr("New pattern piece", "shortcut for action"); + case VShortcutAction::NextPatternPiece: + return tr("Next pattern piece", "shortcut for action"); + case VShortcutAction::PreviusPatternPiece: + return tr("Previous pattern piece", "shortcut for action"); + case VShortcutAction::InteractiveTools: + return tr("Interactive tools mode", "shortcut for action"); + case VShortcutAction::TableOfVariables: + return tr("Open Table of variables dialog", "shortcut for action"); + case VShortcutAction::PatternHistory: + return tr("Open pattern history dialog", "shortcut for action"); + case VShortcutAction::Quit: + return tr("Quit app", "shortcut for action"); + case VShortcutAction::LastTool: + return tr("activate last used tool", "shortcut for action"); + case VShortcutAction::CurveDetails: + return tr("Show curve details", "shortcut for action"); + case VShortcutAction::FinalMeasurements: + return tr("Open final measurements dialog", "shortcut for action"); + case VShortcutAction::CaseSensitiveMatch: + return tr("Case sensitive match", "shortcut for action"); + case VShortcutAction::WholeWordMatch: + return tr("Whole word match", "shortcut for action"); + case VShortcutAction::RegexMatch: + return tr("Regex match", "shortcut for action"); + case VShortcutAction::SearchHistory: + return tr("Search history", "shortcut for action"); + case VShortcutAction::RegexMatchUnicodeProperties: + return tr("Regex match by unicode properties", "shortcut for action"); + case VShortcutAction::FindNext: + return tr("Find next match", "shortcut for action"); + case VShortcutAction::FindPrevious: + return tr("Find previus match", "shortcut for action"); + case VShortcutAction::LAST_ONE_DO_NOT_USE: + Q_UNREACHABLE(); //-V501 + break; + }; + return {}; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::StringListToReadableString(const QStringList &stringList) -> QString +{ + QString s = QKeySequence::fromString(stringList.join(", "_L1)).toString(QKeySequence::NativeText); + return s; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractShortcutManager::AddShortcut(const VSShortcut &shortcut) +{ + m_shortcutsList.append(shortcut); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::CustomKeyBindings(QKeySequence::StandardKey sequence) -> QList +{ + QT_WARNING_PUSH +#if !defined(Q_OS_MACOS) && defined(Q_CC_CLANG) + QT_WARNING_DISABLE_CLANG("-Wenum-enum-conversion") +#endif + +/* + * Because keypad "-" and "+" not the same keys like in main keypad, shortcut Ctrl+"-" or "+" from keypad will not + * working with standard shortcut (QKeySequence::ZoomIn or QKeySequence::ZoomOut). For examle "+" is Qt::Key_Plus + + * Qt::KeypadModifier for keypad. Also for me don't work Qt:CTRL and work Qt::ControlModifier. + */ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + switch (sequence) + { + case QKeySequence::ZoomIn: + return {QKeySequence(Qt::ControlModifier + Qt::Key_Plus + Qt::KeypadModifier)}; + case QKeySequence::ZoomOut: + return {QKeySequence(Qt::ControlModifier + Qt::Key_Minus + Qt::KeypadModifier)}; + default: + break; + } +#else + Q_UNUSED(sequence) +#endif + + return {}; + + QT_WARNING_POP +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::KeyBindingsToStringList(QKeySequence::StandardKey sequence) -> QStringList +{ + const auto seqList = QKeySequence::keyBindings(sequence) + CustomKeyBindings(sequence); + QStringList strings; + strings.reserve(seqList.size()); + for (const auto &seq : seqList) + { + strings << seq.toString(); + } + return strings; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VAbstractShortcutManager::StringListToKeySequenceList(const QStringList &stringList) -> QList +{ + QList keySequences; + keySequences.reserve(stringList.size()); + for (const auto &string : stringList) + { + keySequences << QKeySequence::fromString(string); + } + return keySequences; +} diff --git a/src/libs/vmisc/vabstractshortcutmanager.h b/src/libs/vmisc/vabstractshortcutmanager.h new file mode 100644 index 000000000..587a210ef --- /dev/null +++ b/src/libs/vmisc/vabstractshortcutmanager.h @@ -0,0 +1,140 @@ +/************************************************************************ + ** + ** @file vabstractshortcutmanager.h + ** @author Roman Telezhynskyi + ** @date 20 10, 2023 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef VABSTRACTSHORTCUTMANAGER_H +#define VABSTRACTSHORTCUTMANAGER_H + +#include +#include + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#include +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#include "defglobal.h" +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#define QKEY_SEQUENCE_OP | +#else +#define QKEY_SEQUENCE_OP + +#endif + +enum class VShortcutAction +{ + ZoomIn, + ZoomOut, + ZoomOriginal, + ZoomFitBest, + ZoomFitBestCurrent, + IncreaseLabelFont, + DecreaseLabelFont, + OriginalLabelFont, + HideLabels, + Undo, + Redo, + New, + Open, + Save, + SaveAs, + DrawMode, + DetailsMode, + LayoutMode, + NewPatternPiece, + NextPatternPiece, + PreviusPatternPiece, + InteractiveTools, + TableOfVariables, + PatternHistory, + Quit, + LastTool, + CurveDetails, + FinalMeasurements, + CaseSensitiveMatch, + WholeWordMatch, + RegexMatch, + SearchHistory, + RegexMatchUnicodeProperties, + FindNext, + FindPrevious, + LAST_ONE_DO_NOT_USE +}; + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +Q_DECL_CONST_FUNCTION inline auto qHash(VShortcutAction key, uint seed = 0) noexcept -> uint +{ + auto underlyingValue = static_cast::type>(key); + return ::qHash(underlyingValue, seed); +} +#endif + +class QAction; +class QAbstractButton; + +class VAbstractShortcutManager : public QObject +{ + Q_OBJECT // NOLINT + +public: + struct VSShortcut + { + VShortcutAction type{}; + QStringList defaultShortcuts{}; + QStringList shortcuts{}; + }; + + explicit VAbstractShortcutManager(QObject *parent = nullptr); + ~VAbstractShortcutManager() override = default; + + void UpdateShortcuts(); + void UpdateActionShortcuts(const QMultiHash &actions); + void UpdateButtonShortcut(const QMultiHash &buttons); + + auto GetShortcutsList() const -> QList; + + static auto ShortcutActionToString(VShortcutAction type) -> QString; + static auto ReadableName(VShortcutAction type) -> QString; + static auto StringListToReadableString(const QStringList &stringList) -> QString; + static auto StringListToKeySequenceList(const QStringList &stringList) -> QList; + +signals: + void shortcutsUpdated(); + +protected: + void AddShortcut(const VSShortcut &shortcut); + + static auto CustomKeyBindings(QKeySequence::StandardKey sequence) -> QList; + static auto KeyBindingsToStringList(QKeySequence::StandardKey sequence) -> QStringList; + +private: + Q_DISABLE_COPY_MOVE(VAbstractShortcutManager) // NOLINT + + QList m_shortcutsList{}; +}; + +#endif // VABSTRACTSHORTCUTMANAGER_H diff --git a/src/libs/vmisc/vabstractvalapplication.h b/src/libs/vmisc/vabstractvalapplication.h index 04190e2fb..407ad0bb7 100644 --- a/src/libs/vmisc/vabstractvalapplication.h +++ b/src/libs/vmisc/vabstractvalapplication.h @@ -122,7 +122,7 @@ public: auto GetDimensionWaistLabel() const -> QString; void SetDimensionWaistLabel(const QString &label); - virtual void OpenSettings() override; + void OpenSettings() override; auto ValentinaSettings() -> VValentinaSettings *; static auto VApp() -> VAbstractValApplication *; diff --git a/src/libs/vmisc/vcommonsettings.cpp b/src/libs/vmisc/vcommonsettings.cpp index 6bae17484..c5a717ec6 100644 --- a/src/libs/vmisc/vcommonsettings.cpp +++ b/src/libs/vmisc/vcommonsettings.cpp @@ -1650,3 +1650,20 @@ void VCommonSettings::SetTranslateFormula(bool value) settings.setValue(*settingsPatternTranslateFormula, value); settings.sync(); } + +//--------------------------------------------------------------------------------------------------------------------- +auto VCommonSettings::GetActionShortcuts(const QString &name, const QStringList &defaultShortcuts) -> QStringList +{ + QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename); + settings.beginGroup("shortcuts"_L1); + return settings.value(name, defaultShortcuts).toStringList(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCommonSettings::SetActionShortcuts(const QString &name, const QStringList &shortcuts) +{ + QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename); + settings.beginGroup("shortcuts"_L1); + settings.setValue(name, shortcuts); + settings.sync(); +} diff --git a/src/libs/vmisc/vcommonsettings.h b/src/libs/vmisc/vcommonsettings.h index 12dde345a..96fafe88f 100644 --- a/src/libs/vmisc/vcommonsettings.h +++ b/src/libs/vmisc/vcommonsettings.h @@ -335,6 +335,9 @@ public: auto IsTranslateFormula() const -> bool; void SetTranslateFormula(bool value); + auto GetActionShortcuts(const QString &name, const QStringList &defaultShortcuts) -> QStringList; + void SetActionShortcuts(const QString &name, const QStringList &shortcuts); + signals: void SVGFontsPathChanged(const QString &oldPath, const QString &newPath); diff --git a/src/libs/vmisc/vmisc.pri b/src/libs/vmisc/vmisc.pri index 14c03f1c5..0ba183d27 100644 --- a/src/libs/vmisc/vmisc.pri +++ b/src/libs/vmisc/vmisc.pri @@ -30,7 +30,8 @@ SOURCES += \ $$PWD/dialogs/dialogexporttocsv.cpp \ $$PWD/literals.cpp \ $$PWD/vmodifierkey.cpp \ - $$PWD/dialogs/dialogselectlanguage.cpp + $$PWD/dialogs/dialogselectlanguage.cpp \ + $$PWD/vabstractshortcutmanager.cpp *msvc*:SOURCES += $$PWD/stable.cpp @@ -123,7 +124,8 @@ HEADERS += \ $$PWD/backport/text.h \ $$PWD/dialogs/dialogselectlanguage.h \ $$PWD/fpm/fixed.hpp \ - $$PWD/fpm/math.hpp + $$PWD/fpm/math.hpp \ + $$PWD/vabstractshortcutmanager.cpp contains(DEFINES, APPIMAGE) { SOURCES += \ diff --git a/src/libs/vmisc/vmisc.qbs b/src/libs/vmisc/vmisc.qbs index 8be127c9a..27cfa4edb 100644 --- a/src/libs/vmisc/vmisc.qbs +++ b/src/libs/vmisc/vmisc.qbs @@ -42,6 +42,8 @@ VLib { "vdatastreamenum.h", "vmodifierkey.h", "typedef.h", + "vabstractshortcutmanager.h", + "vabstractshortcutmanager.cpp", ] if (Utilities.versionCompare(Qt.core.version, "6") >= 0) { @@ -75,6 +77,9 @@ VLib { "dialogselectlanguage.h", "dialogexporttocsv.ui", "dialogselectlanguage.ui", + "vshortcutdialog.cpp", + "vshortcutdialog.h", + "vshortcutdialog.ui", ] } diff --git a/src/libs/vmisc/vmodifierkey.h b/src/libs/vmisc/vmodifierkey.h index 587c95029..1eb0baa72 100644 --- a/src/libs/vmisc/vmodifierkey.h +++ b/src/libs/vmisc/vmodifierkey.h @@ -69,7 +69,7 @@ public: /** Returns a string representation for user interface purposes. * * This operator is intented to be used for implicit type casts. */ - operator QString() const; + operator QString() const; // NOLINT(google-explicit-constructor) /** Returns a shared Alt modifier key. */ static auto Alt() -> const VModifierKey &;