diff options
| -rw-r--r-- | src/yuzu/configuration/configure_dialog.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_dialog.h | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_general.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_general.h | 4 | ||||
| -rw-r--r-- | src/yuzu/hotkeys.cpp | 67 | ||||
| -rw-r--r-- | src/yuzu/hotkeys.h | 107 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 84 | ||||
| -rw-r--r-- | src/yuzu/main.h | 3 | 
8 files changed, 159 insertions, 119 deletions
| diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 1ca7e876c..cc4b326ae 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -6,9 +6,12 @@  #include "ui_configure.h"  #include "yuzu/configuration/config.h"  #include "yuzu/configuration/configure_dialog.h" +#include "yuzu/hotkeys.h" -ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { +ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry) +    : QDialog(parent), ui(new Ui::ConfigureDialog) {      ui->setupUi(this); +    ui->generalTab->PopulateHotkeyList(registry);      this->setConfiguration();  } diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 21fa1f501..bbbdacc29 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -7,6 +7,8 @@  #include <memory>  #include <QDialog> +class HotkeyRegistry; +  namespace Ui {  class ConfigureDialog;  } @@ -15,7 +17,7 @@ class ConfigureDialog : public QDialog {      Q_OBJECT  public: -    explicit ConfigureDialog(QWidget* parent); +    explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry);      ~ConfigureDialog();      void applyConfiguration(); diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 04afc8724..d8caee1e8 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -35,6 +35,10 @@ void ConfigureGeneral::setConfiguration() {      ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);  } +void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { +    ui->widget->Populate(registry); +} +  void ConfigureGeneral::applyConfiguration() {      UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();      UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 447552d8c..4770034cc 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -7,6 +7,8 @@  #include <memory>  #include <QWidget> +class HotkeyRegistry; +  namespace Ui {  class ConfigureGeneral;  } @@ -18,11 +20,11 @@ public:      explicit ConfigureGeneral(QWidget* parent = nullptr);      ~ConfigureGeneral(); +    void PopulateHotkeyList(const HotkeyRegistry& registry);      void applyConfiguration();  private:      void setConfiguration(); -private:      std::unique_ptr<Ui::ConfigureGeneral> ui;  }; diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index 61acb38ee..dce399774 100644 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.cpp @@ -10,58 +10,53 @@  #include "yuzu/hotkeys.h"  #include "yuzu/ui_settings.h" -struct Hotkey { -    Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {} +HotkeyRegistry::HotkeyRegistry() = default; +HotkeyRegistry::~HotkeyRegistry() = default; -    QKeySequence keyseq; -    QShortcut* shortcut; -    Qt::ShortcutContext context; -}; - -typedef std::map<QString, Hotkey> HotkeyMap; -typedef std::map<QString, HotkeyMap> HotkeyGroupMap; - -HotkeyGroupMap hotkey_groups; - -void SaveHotkeys() { -    UISettings::values.shortcuts.clear(); -    for (auto group : hotkey_groups) { -        for (auto hotkey : group.second) { -            UISettings::values.shortcuts.emplace_back( -                UISettings::Shortcut(group.first + "/" + hotkey.first, -                                     UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), -                                                                    hotkey.second.context))); -        } -    } -} - -void LoadHotkeys() { +void HotkeyRegistry::LoadHotkeys() {      // Make sure NOT to use a reference here because it would become invalid once we call      // beginGroup()      for (auto shortcut : UISettings::values.shortcuts) { -        QStringList cat = shortcut.first.split("/"); +        const QStringList cat = shortcut.first.split('/');          Q_ASSERT(cat.size() >= 2);          // RegisterHotkey assigns default keybindings, so use old values as default parameters          Hotkey& hk = hotkey_groups[cat[0]][cat[1]];          if (!shortcut.second.first.isEmpty()) {              hk.keyseq = QKeySequence::fromString(shortcut.second.first); -            hk.context = (Qt::ShortcutContext)shortcut.second.second; +            hk.context = static_cast<Qt::ShortcutContext>(shortcut.second.second);          }          if (hk.shortcut)              hk.shortcut->setKey(hk.keyseq);      }  } -void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq, -                    Qt::ShortcutContext default_context) { -    if (hotkey_groups[group].find(action) == hotkey_groups[group].end()) { -        hotkey_groups[group][action].keyseq = default_keyseq; -        hotkey_groups[group][action].context = default_context; +void HotkeyRegistry::SaveHotkeys() { +    UISettings::values.shortcuts.clear(); +    for (const auto& group : hotkey_groups) { +        for (const auto& hotkey : group.second) { +            UISettings::values.shortcuts.emplace_back( +                UISettings::Shortcut(group.first + '/' + hotkey.first, +                                     UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), +                                                                    hotkey.second.context))); +        }      }  } -QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget) { +void HotkeyRegistry::RegisterHotkey(const QString& group, const QString& action, +                                    const QKeySequence& default_keyseq, +                                    Qt::ShortcutContext default_context) { +    auto& hotkey_group = hotkey_groups[group]; +    if (hotkey_group.find(action) != hotkey_group.end()) { +        return; +    } + +    auto& hotkey_action = hotkey_groups[group][action]; +    hotkey_action.keyseq = default_keyseq; +    hotkey_action.context = default_context; +} + +QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {      Hotkey& hk = hotkey_groups[group][action];      if (!hk.shortcut) @@ -72,10 +67,12 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge  GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) {      ui.setupUi(this); +} -    for (auto group : hotkey_groups) { +void GHotkeysDialog::Populate(const HotkeyRegistry& registry) { +    for (const auto& group : registry.hotkey_groups) {          QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first)); -        for (auto hotkey : group.second) { +        for (const auto& hotkey : group.second) {              QStringList columns;              columns << hotkey.first << hotkey.second.keyseq.toString();              QTreeWidgetItem* item = new QTreeWidgetItem(columns); diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h index a4ccc193b..f38e6c002 100644 --- a/src/yuzu/hotkeys.h +++ b/src/yuzu/hotkeys.h @@ -4,6 +4,7 @@  #pragma once +#include <map>  #include "ui_hotkeys.h"  class QDialog; @@ -11,47 +12,69 @@ class QKeySequence;  class QSettings;  class QShortcut; -/** - * Register a hotkey. - * - * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger") - * @param action Name of the action (e.g. "Start Emulation", "Load Image") - * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the settings - * file before - * @param default_context Default context to assign if the hotkey wasn't present in the settings - * file before - * @warning Both the group and action strings will be displayed in the hotkey settings dialog - */ -void RegisterHotkey(const QString& group, const QString& action, -                    const QKeySequence& default_keyseq = QKeySequence(), -                    Qt::ShortcutContext default_context = Qt::WindowShortcut); - -/** - * Returns a QShortcut object whose activated() signal can be connected to other QObjects' slots. - * - * @param group  General group this hotkey belongs to (e.g. "Main Window", "Debugger"). - * @param action Name of the action (e.g. "Start Emulation", "Load Image"). - * @param widget Parent widget of the returned QShortcut. - * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut - * will be the same. Thus, you shouldn't rely on the caller really being the QShortcut's parent. - */ -QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); - -/** - * Saves all registered hotkeys to the settings file. - * - * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a - * settings group will be created to store the key sequence and the hotkey context. - */ -void SaveHotkeys(); - -/** - * Loads hotkeys from the settings file. - * - * @note Yet unregistered hotkeys which are present in the settings will automatically be - * registered. - */ -void LoadHotkeys(); +class HotkeyRegistry final { +public: +    friend class GHotkeysDialog; + +    explicit HotkeyRegistry(); +    ~HotkeyRegistry(); + +    /** +     * Loads hotkeys from the settings file. +     * +     * @note Yet unregistered hotkeys which are present in the settings will automatically be +     *       registered. +     */ +    void LoadHotkeys(); + +    /** +     * Saves all registered hotkeys to the settings file. +     * +     * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a +     *       settings group will be created to store the key sequence and the hotkey context. +     */ +    void SaveHotkeys(); + +    /** +     * Returns a QShortcut object whose activated() signal can be connected to other QObjects' +     * slots. +     * +     * @param group  General group this hotkey belongs to (e.g. "Main Window", "Debugger"). +     * @param action Name of the action (e.g. "Start Emulation", "Load Image"). +     * @param widget Parent widget of the returned QShortcut. +     * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut +     *          will be the same. Thus, you shouldn't rely on the caller really being the +     *          QShortcut's parent. +     */ +    QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); + +    /** +     * Register a hotkey. +     * +     * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger") +     * @param action Name of the action (e.g. "Start Emulation", "Load Image") +     * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the +     *                       settings file before +     * @param default_context Default context to assign if the hotkey wasn't present in the settings +     *                        file before +     * @warning Both the group and action strings will be displayed in the hotkey settings dialog +     */ +    void RegisterHotkey(const QString& group, const QString& action, +                        const QKeySequence& default_keyseq = {}, +                        Qt::ShortcutContext default_context = Qt::WindowShortcut); + +private: +    struct Hotkey { +        QKeySequence keyseq; +        QShortcut* shortcut = nullptr; +        Qt::ShortcutContext context = Qt::WindowShortcut; +    }; + +    using HotkeyMap = std::map<QString, Hotkey>; +    using HotkeyGroupMap = std::map<QString, HotkeyMap>; + +    HotkeyGroupMap hotkey_groups; +};  class GHotkeysDialog : public QWidget {      Q_OBJECT @@ -59,6 +82,8 @@ class GHotkeysDialog : public QWidget {  public:      explicit GHotkeysDialog(QWidget* parent = nullptr); +    void Populate(const HotkeyRegistry& registry); +  private:      Ui::hotkeys ui;  }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index dd71bd763..17ed62c72 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -208,43 +208,46 @@ void GMainWindow::InitializeRecentFileMenuActions() {  }  void GMainWindow::InitializeHotkeys() { -    RegisterHotkey("Main Window", "Load File", QKeySequence::Open); -    RegisterHotkey("Main Window", "Start Emulation"); -    RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4)); -    RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen); -    RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape), -                   Qt::ApplicationShortcut); -    RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"), -                   Qt::ApplicationShortcut); -    LoadHotkeys(); - -    connect(GetHotkey("Main Window", "Load File", this), &QShortcut::activated, this, -            &GMainWindow::OnMenuLoadFile); -    connect(GetHotkey("Main Window", "Start Emulation", this), &QShortcut::activated, this, -            &GMainWindow::OnStartGame); -    connect(GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated, this, [&] { -        if (emulation_running) { -            if (emu_thread->IsRunning()) { -                OnPauseGame(); -            } else { -                OnStartGame(); -            } -        } -    }); -    connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated, -            ui.action_Fullscreen, &QAction::trigger); -    connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously, -            ui.action_Fullscreen, &QAction::trigger); -    connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] { -        if (emulation_running) { -            ui.action_Fullscreen->setChecked(false); -            ToggleFullscreen(); -        } -    }); -    connect(GetHotkey("Main Window", "Toggle Speed Limit", this), &QShortcut::activated, this, [&] { -        Settings::values.toggle_framelimit = !Settings::values.toggle_framelimit; -        UpdateStatusBar(); -    }); +    hotkey_registry.RegisterHotkey("Main Window", "Load File", QKeySequence::Open); +    hotkey_registry.RegisterHotkey("Main Window", "Start Emulation"); +    hotkey_registry.RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4)); +    hotkey_registry.RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen); +    hotkey_registry.RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape), +                                   Qt::ApplicationShortcut); +    hotkey_registry.RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"), +                                   Qt::ApplicationShortcut); +    hotkey_registry.LoadHotkeys(); + +    connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated, +            this, &GMainWindow::OnMenuLoadFile); +    connect(hotkey_registry.GetHotkey("Main Window", "Start Emulation", this), +            &QShortcut::activated, this, &GMainWindow::OnStartGame); +    connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated, +            this, [&] { +                if (emulation_running) { +                    if (emu_thread->IsRunning()) { +                        OnPauseGame(); +                    } else { +                        OnStartGame(); +                    } +                } +            }); +    connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), +            &QShortcut::activated, ui.action_Fullscreen, &QAction::trigger); +    connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), +            &QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger); +    connect(hotkey_registry.GetHotkey("Main Window", "Exit Fullscreen", this), +            &QShortcut::activated, this, [&] { +                if (emulation_running) { +                    ui.action_Fullscreen->setChecked(false); +                    ToggleFullscreen(); +                } +            }); +    connect(hotkey_registry.GetHotkey("Main Window", "Toggle Speed Limit", this), +            &QShortcut::activated, this, [&] { +                Settings::values.toggle_framelimit = !Settings::values.toggle_framelimit; +                UpdateStatusBar(); +            });  }  void GMainWindow::SetDefaultUIGeometry() { @@ -323,7 +326,8 @@ void GMainWindow::ConnectMenuEvents() {      connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);      // Fullscreen -    ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key()); +    ui.action_Fullscreen->setShortcut( +        hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key());      connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);      // Help @@ -757,7 +761,7 @@ void GMainWindow::ToggleWindowMode() {  }  void GMainWindow::OnConfigure() { -    ConfigureDialog configureDialog(this); +    ConfigureDialog configureDialog(this, hotkey_registry);      auto old_theme = UISettings::values.theme;      auto result = configureDialog.exec();      if (result == QDialog::Accepted) { @@ -896,7 +900,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {      UISettings::values.first_start = false;      game_list->SaveInterfaceLayout(); -    SaveHotkeys(); +    hotkey_registry.SaveHotkeys();      // Shutdown session if the emu thread is active...      if (emu_thread != nullptr) diff --git a/src/yuzu/main.h b/src/yuzu/main.h index a60d831b9..6e335b8f8 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -9,6 +9,7 @@  #include <QTimer>  #include "core/core.h"  #include "ui_main.h" +#include "yuzu/hotkeys.h"  class Config;  class EmuThread; @@ -172,6 +173,8 @@ private:      // stores default icon theme search paths for the platform      QStringList default_theme_paths; +    HotkeyRegistry hotkey_registry; +  protected:      void dropEvent(QDropEvent* event) override;      void dragEnterEvent(QDragEnterEvent* event) override; | 
