From 48e97dc15de6fd0ea2bce61f58dbf9500ac7444a Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Wed, 6 Oct 2021 23:19:18 +0800 Subject: [PATCH] - implement: config shortcuts --- RedPandaIDE/RedPandaIDE.pro | 2 + RedPandaIDE/autolinkmanager.cpp | 5 +- RedPandaIDE/autolinkmanager.h | 2 - RedPandaIDE/codesnippetsmanager.cpp | 2 + RedPandaIDE/mainwindow.cpp | 8 ++ RedPandaIDE/mainwindow.h | 3 +- .../environmentshortcutwidget.cpp | 44 ++++--- .../environmentshortcutwidget.h | 18 ++- RedPandaIDE/settingsdialog/settingsdialog.cpp | 7 +- RedPandaIDE/shortcutmanager.cpp | 109 ++++++++++++++++++ RedPandaIDE/shortcutmanager.h | 38 ++++++ RedPandaIDE/systemconsts.h | 3 + 12 files changed, 212 insertions(+), 29 deletions(-) create mode 100644 RedPandaIDE/shortcutmanager.cpp create mode 100644 RedPandaIDE/shortcutmanager.h diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 2c0f3cdd..92714521 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -61,6 +61,7 @@ SOURCES += \ settingsdialog/projectoutputwidget.cpp \ settingsdialog/projectprecompilewidget.cpp \ settingsdialog/projectversioninfowidget.cpp \ + shortcutmanager.cpp \ symbolusagemanager.cpp \ todoparser.cpp \ widgets/aboutdialog.cpp \ @@ -166,6 +167,7 @@ HEADERS += \ settingsdialog/projectoutputwidget.h \ settingsdialog/projectprecompilewidget.h \ settingsdialog/projectversioninfowidget.h \ + shortcutmanager.h \ symbolusagemanager.h \ todoparser.h \ widgets/aboutdialog.h \ diff --git a/RedPandaIDE/autolinkmanager.cpp b/RedPandaIDE/autolinkmanager.cpp index 7c97eba7..da5b0485 100644 --- a/RedPandaIDE/autolinkmanager.cpp +++ b/RedPandaIDE/autolinkmanager.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "systemconsts.h" AutolinkManager* pAutolinkManager; @@ -21,7 +22,7 @@ PAutolink AutolinkManager::getLink(const QString &header) const void AutolinkManager::load() { QDir dir(pSettings->dirs().config()); - QString filename=dir.filePath(AUTOLINK_CONFIG); + QString filename=dir.filePath(DEV_AUTOLINK_FILE); QFile file(filename); if (!file.exists()) { QFile preFile(":/config/autolink.json"); @@ -52,7 +53,7 @@ void AutolinkManager::load() void AutolinkManager::save() { QDir dir(pSettings->dirs().config()); - QString filename=dir.filePath(AUTOLINK_CONFIG); + QString filename=dir.filePath(DEV_AUTOLINK_FILE); QFile file(filename); if (file.open(QFile::WriteOnly|QFile::Truncate)) { QJsonDocument doc(toJson()); diff --git a/RedPandaIDE/autolinkmanager.h b/RedPandaIDE/autolinkmanager.h index 935d9baf..730daa08 100644 --- a/RedPandaIDE/autolinkmanager.h +++ b/RedPandaIDE/autolinkmanager.h @@ -7,8 +7,6 @@ #include #include -#define AUTOLINK_CONFIG "autolink.json" - struct Autolink { QString header; QString linkOption; diff --git a/RedPandaIDE/codesnippetsmanager.cpp b/RedPandaIDE/codesnippetsmanager.cpp index 3e2d8673..989cc790 100644 --- a/RedPandaIDE/codesnippetsmanager.cpp +++ b/RedPandaIDE/codesnippetsmanager.cpp @@ -47,6 +47,7 @@ void CodeSnippetsManager::load() tr("Read code snippets failed"), tr("Can't open code snippet file '%1' for read.") .arg(filename)); + return; } QByteArray json = file.readAll(); @@ -58,6 +59,7 @@ void CodeSnippetsManager::load() tr("Read code snippet file '%1' failed:%2") .arg(filename) .arg(error.errorString())); + return; } mSnippets.clear(); QJsonArray array = doc.array(); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index e5209b18..a09254d6 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -178,6 +178,7 @@ MainWindow::MainWindow(QWidget *parent) updateEditorColorSchemes(); + updateShortcuts(); } MainWindow::~MainWindow() @@ -666,6 +667,13 @@ void MainWindow::resetAutoSaveTimer() } } +void MainWindow::updateShortcuts() +{ + ShortcutManager manager; + manager.load(); + manager.applyTo(findChildren()); +} + QPlainTextEdit *MainWindow::txtLocals() { return ui->txtLocals; diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index edcddcb3..c75ff16b 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -14,6 +14,7 @@ #include "symbolusagemanager.h" #include "codesnippetsmanager.h" #include "todoparser.h" +#include "shortcutmanager.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -87,7 +88,7 @@ public: void rebuildOpenedFileHisotryMenu(); void updateClassBrowserForEditor(Editor* editor); void resetAutoSaveTimer(); - + void updateShortcuts(); void saveLastOpens(); void loadLastOpens(); diff --git a/RedPandaIDE/settingsdialog/environmentshortcutwidget.cpp b/RedPandaIDE/settingsdialog/environmentshortcutwidget.cpp index 12b2bb1f..a85f6ce0 100644 --- a/RedPandaIDE/settingsdialog/environmentshortcutwidget.cpp +++ b/RedPandaIDE/settingsdialog/environmentshortcutwidget.cpp @@ -9,6 +9,8 @@ EnvironmentShortcutWidget::EnvironmentShortcutWidget(const QString& name, const { ui->setupUi(this); ui->tblShortcut->setModel(&mModel); + connect(&mModel, &EnvironmentShortcutModel::shortcutChanged, + this, &SettingsWidget::setSettingsChanged); } EnvironmentShortcutWidget::~EnvironmentShortcutWidget() @@ -23,10 +25,11 @@ void EnvironmentShortcutWidget::doLoad() void EnvironmentShortcutWidget::doSave() { - foreach (const PEnvironmentShortCut& shortcut, mModel.shortcuts()) { - shortcut->action->setShortcut(QKeySequence::fromString(shortcut->shortcut)); - shortcut->shortcut = shortcut->action->shortcut().toString(); - } + ShortcutManager manager; + manager.setShortcuts(mModel.shortcuts()); + manager.save(); + pMainWindow->updateShortcuts(); + mModel.reload(); } EnvironmentShortcutModel::EnvironmentShortcutModel(QObject *parent):QAbstractTableModel(parent) @@ -41,6 +44,8 @@ void EnvironmentShortcutModel::reload() QList actions = pMainWindow->findChildren(QString(),Qt::FindDirectChildrenOnly); QList menus = pMainWindow->mainWidget()->menubar->findChildren(); foreach( const QMenu* menu, menus) { + if (menu->title().isEmpty()) + continue; loadShortCutsOfMenu(menu, actions); } endResetModel(); @@ -62,7 +67,7 @@ QVariant EnvironmentShortcutModel::data(const QModelIndex &index, int role) cons return QVariant(); } if (role==Qt::DisplayRole || role == Qt::EditRole) { - PEnvironmentShortCut item = mShortcuts[index.row()]; + PEnvironmentShortcut item = mShortcuts[index.row()]; switch( index.column()) { case 0: return item->fullPath; @@ -81,8 +86,12 @@ bool EnvironmentShortcutModel::setData(const QModelIndex &index, const QVariant if (role == Qt::EditRole) { if (index.column()!=1) return false; - PEnvironmentShortCut item = mShortcuts[index.row()]; - item->shortcut = value.toString(); + PEnvironmentShortcut item = mShortcuts[index.row()]; + QString s = value.toString().trimmed(); + if (s!=item->shortcut) { + item->shortcut = value.toString(); + emit shortcutChanged(); + } return true; } return false; @@ -112,20 +121,29 @@ Qt::ItemFlags EnvironmentShortcutModel::flags(const QModelIndex &index) const return flags; } -const QList &EnvironmentShortcutModel::shortcuts() const +const QList &EnvironmentShortcutModel::shortcuts() const { return mShortcuts; } +void EnvironmentShortcutModel::shortcutsUpdated() +{ + beginResetModel(); + endResetModel(); +} + void EnvironmentShortcutModel::loadShortCutsOfMenu(const QMenu *menu, QList &globalActions) { QList actions = menu->actions(); foreach (QAction* action,actions) { - PEnvironmentShortCut item = std::make_shared(); - item->name = action->objectName(); - item->fullPath = QString("%1 > %2").arg(menu->title(),action->text()); - item->action = action; - item->shortcut = action->shortcut().toString().trimmed(); + if (!action->text().isEmpty()) { + PEnvironmentShortcut item = std::make_shared(); + item->name = action->objectName(); + item->fullPath = QString("%1 > %2").arg(menu->title(),action->text()); + item->action = action; + item->shortcut = action->shortcut().toString().trimmed(); + mShortcuts.append(item); + } globalActions.removeAll(action); } } diff --git a/RedPandaIDE/settingsdialog/environmentshortcutwidget.h b/RedPandaIDE/settingsdialog/environmentshortcutwidget.h index 3dcfac3e..6c01e4ca 100644 --- a/RedPandaIDE/settingsdialog/environmentshortcutwidget.h +++ b/RedPandaIDE/settingsdialog/environmentshortcutwidget.h @@ -4,21 +4,15 @@ #include #include #include "settingswidget.h" +#include "../shortcutmanager.h" namespace Ui { class EnvironmentShortcutWidget; } -struct EnvironmentShortCut { - QString name; - QString fullPath; - QString shortcut; - QAction* action; -}; - -using PEnvironmentShortCut = std::shared_ptr; class QMenu; class EnvironmentShortcutModel: public QAbstractTableModel { + Q_OBJECT // QAbstractItemModel interface public: explicit EnvironmentShortcutModel(QObject* parent=nullptr); @@ -30,11 +24,15 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role) override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; - const QList &shortcuts() const; + const QList &shortcuts() const; +signals: + void shortcutChanged(); +public slots: + void shortcutsUpdated(); private: void loadShortCutsOfMenu(const QMenu * menu, QList& globalActions); private: - QList mShortcuts; + QList mShortcuts; }; class EnvironmentShortcutWidget : public SettingsWidget diff --git a/RedPandaIDE/settingsdialog/settingsdialog.cpp b/RedPandaIDE/settingsdialog/settingsdialog.cpp index b0b895cb..dec33520 100644 --- a/RedPandaIDE/settingsdialog/settingsdialog.cpp +++ b/RedPandaIDE/settingsdialog/settingsdialog.cpp @@ -15,6 +15,7 @@ #include "editorsnippetwidget.h" #include "editormiscwidget.h" #include "environmentappearencewidget.h" +#include "environmentshortcutwidget.h" #include "environmentfileassociationwidget.h" #include "executorgeneralwidget.h" #include "debuggeneralwidget.h" @@ -96,7 +97,11 @@ PSettingsDialog SettingsDialog::optionDialog() widget->init(); dialog->addWidget(widget); - widget = new EnvironmentFileAssociationWidget(tr("FileAssociation"),tr("Environment")); + widget = new EnvironmentFileAssociationWidget(tr("File Association"),tr("Environment")); + widget->init(); + dialog->addWidget(widget); + + widget = new EnvironmentShortcutWidget(tr("Shortcuts"),tr("Environment")); widget->init(); dialog->addWidget(widget); diff --git a/RedPandaIDE/shortcutmanager.cpp b/RedPandaIDE/shortcutmanager.cpp new file mode 100644 index 00000000..63b48f83 --- /dev/null +++ b/RedPandaIDE/shortcutmanager.cpp @@ -0,0 +1,109 @@ +#include "shortcutmanager.h" +#include "systemconsts.h" +#include "settings.h" +#include +#include +#include +#include +#include +#include +#include + +ShortcutManager::ShortcutManager(QObject *parent) : QObject(parent) +{ + +} + +void ShortcutManager::load() +{ + //if config file not exists, copy it from data + QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_SHORTCUT_FILE; + if (!fileExists(filename)) + return; + //read config file + QFile file(filename); + if (!file.open(QFile::ReadOnly)) { + QMessageBox::critical(nullptr, + tr("Read shortcut config failed"), + tr("Can't open shortcut config file '%1' for read.") + .arg(filename)); + return; + } + + QByteArray json = file.readAll(); + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(json,&error); + if (error.error != QJsonParseError::NoError) { + QMessageBox::critical(nullptr, + tr("Read shortcut config failed"), + tr("Read shortcut config file '%1' failed:%2") + .arg(filename) + .arg(error.errorString())); + return; + } + mShortcuts.clear(); + QJsonArray array = doc.array(); + foreach (const QJsonValue& value,array) { + QJsonObject object = value.toObject(); + PEnvironmentShortcut shortcut = std::make_shared(); + shortcut->name = object["name"].toString(); + if (shortcut->name.isEmpty()) + continue; + shortcut->shortcut = object["shortcut"].toString(); + mShortcuts.insert(shortcut->name,shortcut); + } +} + +void ShortcutManager::save() +{ + QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_SHORTCUT_FILE; + QFile file(filename); + if (!file.open(QFile::WriteOnly | QFile::Truncate)) { + QMessageBox::critical(nullptr, + tr("Save shortcut config failed"), + tr("Can't open shortcut config file '%1' for write.") + .arg(filename)); + return; + } + QJsonArray array; + foreach (const PEnvironmentShortcut& shortcut,mShortcuts) { + QJsonObject object; + object["name"]=shortcut->name; + object["shortcut"]=shortcut->shortcut; + array.append(object); + } + QJsonDocument doc; + doc.setArray(array); + if (file.write(doc.toJson())<0) { + QMessageBox::critical(nullptr, + tr("Save shortcut config failed"), + tr("Write to shortcut config file '%1' failed.") + .arg(filename)); + return; + } +} + +void ShortcutManager::setShortcuts(QList shortcuts) +{ + mShortcuts.clear(); + foreach(PEnvironmentShortcut shortcut, shortcuts) { + if (shortcut->name.isEmpty()) + continue; + mShortcuts.insert(shortcut->name,shortcut); + } +} + +void ShortcutManager::applyTo(QList actions) +{ + foreach (QAction* action ,actions) { + applyTo(action); + } +} + +void ShortcutManager::applyTo(QAction *action) +{ + PEnvironmentShortcut item = mShortcuts.value(action->objectName(), PEnvironmentShortcut()); + if (item) { + action->setShortcut(QKeySequence::fromString(item->shortcut)); + } +} diff --git a/RedPandaIDE/shortcutmanager.h b/RedPandaIDE/shortcutmanager.h new file mode 100644 index 00000000..339aa989 --- /dev/null +++ b/RedPandaIDE/shortcutmanager.h @@ -0,0 +1,38 @@ +#ifndef SHORTCUTMANAGER_H +#define SHORTCUTMANAGER_H + +#include +#include +#include + +class QAction; + +struct EnvironmentShortcut { + QString name; + QString fullPath; + QString shortcut; + QAction* action; +}; + +using PEnvironmentShortcut = std::shared_ptr; + +class ShortcutManager : public QObject +{ + Q_OBJECT +public: + explicit ShortcutManager(QObject *parent = nullptr); + void load(); + void save(); + void setShortcuts(QList shortcuts); + void applyTo(QList actions); + void applyTo(QAction* action); +signals: +private: + +private: + QMap mShortcuts; +}; + +using PShortcutManager = std::shared_ptr; + +#endif // SHORTCUTMANAGER_H diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index c22a8cf4..590f3284 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -34,6 +34,9 @@ #define DEV_LASTOPENS_FILE "lastopens.ini" #define DEV_SYMBOLUSAGE_FILE "symbolusage.json" #define DEV_CODESNIPPET_FILE "codesnippets.json" +#define DEV_AUTOLINK_FILE "autolink.json" +#define DEV_SHORTCUT_FILE "shortcuts.json" + #ifdef Q_OS_WIN # define PATH_SENSITIVITY Qt::CaseInsensitive # define PATH_SEPARATOR ";"