diff options
Diffstat (limited to 'src/yuzu/configuration')
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 59 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.h | 3 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure.ui | 19 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_dialog.cpp | 16 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_dialog.h | 3 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_general.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_general.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_general.ui | 24 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_hotkeys.cpp | 121 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_hotkeys.h | 48 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_hotkeys.ui | 42 | 
11 files changed, 285 insertions, 55 deletions
| diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index dead9f807..802db3945 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -2,6 +2,8 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <array> +#include <QKeySequence>  #include <QSettings>  #include "common/file_util.h"  #include "configure_input_simple.h" @@ -9,7 +11,6 @@  #include "core/hle/service/hid/controllers/npad.h"  #include "input_common/main.h"  #include "yuzu/configuration/config.h" -#include "yuzu/ui_settings.h"  Config::Config() {      // TODO: Don't hardcode the path; let the frontend decide where to put the config files. @@ -17,7 +18,6 @@ Config::Config() {      FileUtil::CreateFullPath(qt_config_loc);      qt_config =          std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); -      Reload();  } @@ -205,6 +205,27 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default      Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight,  }; +// This shouldn't have anything except static initializers (no functions). So +// QKeySequnce(...).toString() is NOT ALLOWED HERE. +// This must be in alphabetical order according to action name as it must have the same order as +// UISetting::values.shortcuts, which is alphabetically ordered. +const std::array<UISettings::Shortcut, 15> Config::default_hotkeys{ +    {{"Capture Screenshot", "Main Window", {"Ctrl+P", Qt::ApplicationShortcut}}, +     {"Continue/Pause Emulation", "Main Window", {"F4", Qt::WindowShortcut}}, +     {"Decrease Speed Limit", "Main Window", {"-", Qt::ApplicationShortcut}}, +     {"Exit yuzu", "Main Window", {"Ctrl+Q", Qt::WindowShortcut}}, +     {"Exit Fullscreen", "Main Window", {"Esc", Qt::WindowShortcut}}, +     {"Fullscreen", "Main Window", {"F11", Qt::WindowShortcut}}, +     {"Increase Speed Limit", "Main Window", {"+", Qt::ApplicationShortcut}}, +     {"Load Amiibo", "Main Window", {"F2", Qt::ApplicationShortcut}}, +     {"Load File", "Main Window", {"Ctrl+O", Qt::WindowShortcut}}, +     {"Restart Emulation", "Main Window", {"F6", Qt::WindowShortcut}}, +     {"Stop Emulation", "Main Window", {"F5", Qt::WindowShortcut}}, +     {"Toggle Filter Bar", "Main Window", {"Ctrl+F", Qt::WindowShortcut}}, +     {"Toggle Speed Limit", "Main Window", {"Ctrl+Z", Qt::ApplicationShortcut}}, +     {"Toggle Status Bar", "Main Window", {"Ctrl+S", Qt::WindowShortcut}}, +     {"Change Docked Mode", "Main Window", {"F10", Qt::ApplicationShortcut}}}}; +  void Config::ReadPlayerValues() {      for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {          auto& player = Settings::values.players[p]; @@ -508,20 +529,15 @@ void Config::ReadValues() {      qt_config->endGroup();      qt_config->beginGroup("Shortcuts"); -    QStringList groups = qt_config->childGroups(); -    for (auto group : groups) { +    for (auto [name, group, shortcut] : default_hotkeys) { +        auto [keyseq, context] = shortcut;          qt_config->beginGroup(group); - -        QStringList hotkeys = qt_config->childGroups(); -        for (auto hotkey : hotkeys) { -            qt_config->beginGroup(hotkey); -            UISettings::values.shortcuts.emplace_back(UISettings::Shortcut( -                group + "/" + hotkey, -                UISettings::ContextualShortcut(ReadSetting("KeySeq").toString(), -                                               ReadSetting("Context").toInt()))); -            qt_config->endGroup(); -        } - +        qt_config->beginGroup(name); +        UISettings::values.shortcuts.push_back( +            {name, +             group, +             {ReadSetting("KeySeq", keyseq).toString(), ReadSetting("Context", context).toInt()}}); +        qt_config->endGroup();          qt_config->endGroup();      }      qt_config->endGroup(); @@ -758,9 +774,16 @@ void Config::SaveValues() {      qt_config->endGroup();      qt_config->beginGroup("Shortcuts"); -    for (auto shortcut : UISettings::values.shortcuts) { -        WriteSetting(shortcut.first + "/KeySeq", shortcut.second.first); -        WriteSetting(shortcut.first + "/Context", shortcut.second.second); +    // Lengths of UISettings::values.shortcuts & default_hotkeys are same. +    // However, their ordering must also be the same. +    for (std::size_t i = 0; i < default_hotkeys.size(); i++) { +        auto [name, group, shortcut] = UISettings::values.shortcuts[i]; +        qt_config->beginGroup(group); +        qt_config->beginGroup(name); +        WriteSetting("KeySeq", shortcut.first, default_hotkeys[i].shortcut.first); +        WriteSetting("Context", shortcut.second, default_hotkeys[i].shortcut.second); +        qt_config->endGroup(); +        qt_config->endGroup();      }      qt_config->endGroup(); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index f4185db18..221d2364c 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -9,6 +9,7 @@  #include <string>  #include <QVariant>  #include "core/settings.h" +#include "yuzu/ui_settings.h"  class QSettings; @@ -47,6 +48,8 @@ private:      void WriteSetting(const QString& name, const QVariant& value);      void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); +    static const std::array<UISettings::Shortcut, 15> default_hotkeys; +      std::unique_ptr<QSettings> qt_config;      std::string qt_config_loc;  }; diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index 3f03f0b77..267717bc9 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui @@ -7,9 +7,15 @@      <x>0</x>      <y>0</y>      <width>382</width> -    <height>241</height> +    <height>650</height>     </rect>    </property> +  <property name="minimumSize"> +   <size> +    <width>0</width> +    <height>650</height> +   </size> +  </property>    <property name="windowTitle">     <string>yuzu Configuration</string>    </property> @@ -62,6 +68,11 @@           <string>Input</string>          </attribute>         </widget> +       <widget class="ConfigureHotkeys" name="hotkeysTab"> +        <attribute name="title"> +         <string>Hotkeys</string> +        </attribute> +       </widget>         <widget class="ConfigureGraphics" name="graphicsTab">          <attribute name="title">           <string>Graphics</string> @@ -150,6 +161,12 @@     <header>configuration/configure_input_simple.h</header>     <container>1</container>    </customwidget> +  <customwidget> +   <class>ConfigureHotkeys</class> +   <extends>QWidget</extends> +   <header>configuration/configure_hotkeys.h</header> +   <container>1</container> +  </customwidget>   </customwidgets>   <resources/>   <connections> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 777050405..51bd1f121 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -8,20 +8,22 @@  #include "ui_configure.h"  #include "yuzu/configuration/config.h"  #include "yuzu/configuration/configure_dialog.h" +#include "yuzu/configuration/configure_input_player.h"  #include "yuzu/hotkeys.h" -ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry) -    : QDialog(parent), ui(new Ui::ConfigureDialog) { +ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) +    : QDialog(parent), registry(registry), ui(new Ui::ConfigureDialog) {      ui->setupUi(this); -    ui->generalTab->PopulateHotkeyList(registry); +    ui->hotkeysTab->Populate(registry);      this->setConfiguration();      this->PopulateSelectionList();      connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,              &ConfigureDialog::UpdateVisibleTabs); -      adjustSize(); -      ui->selectorList->setCurrentRow(0); + +    // Synchronise lists upon initialisation +    ui->hotkeysTab->EmitHotkeysChanged();  }  ConfigureDialog::~ConfigureDialog() = default; @@ -34,6 +36,7 @@ void ConfigureDialog::applyConfiguration() {      ui->systemTab->applyConfiguration();      ui->profileManagerTab->applyConfiguration();      ui->inputTab->applyConfiguration(); +    ui->hotkeysTab->applyConfiguration(registry);      ui->graphicsTab->applyConfiguration();      ui->audioTab->applyConfiguration();      ui->debugTab->applyConfiguration(); @@ -47,7 +50,7 @@ void ConfigureDialog::PopulateSelectionList() {          {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}},           {tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}},           {tr("Graphics"), {tr("Graphics")}}, -         {tr("Controls"), {tr("Input")}}}}; +         {tr("Controls"), {tr("Input"), tr("Hotkeys")}}}};      for (const auto& entry : items) {          auto* const item = new QListWidgetItem(entry.first); @@ -66,6 +69,7 @@ void ConfigureDialog::UpdateVisibleTabs() {                                                   {tr("System"), ui->systemTab},                                                   {tr("Profiles"), ui->profileManagerTab},                                                   {tr("Input"), ui->inputTab}, +                                                 {tr("Hotkeys"), ui->hotkeysTab},                                                   {tr("Graphics"), ui->graphicsTab},                                                   {tr("Audio"), ui->audioTab},                                                   {tr("Debug"), ui->debugTab}, diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 243d9fa09..2363ba584 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -17,7 +17,7 @@ class ConfigureDialog : public QDialog {      Q_OBJECT  public: -    explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry); +    explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry);      ~ConfigureDialog() override;      void applyConfiguration(); @@ -28,4 +28,5 @@ private:      void PopulateSelectionList();      std::unique_ptr<Ui::ConfigureDialog> ui; +    HotkeyRegistry& registry;  }; diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 389fcf667..eeb038afb 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -35,10 +35,6 @@ void ConfigureGeneral::setConfiguration() {      ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);  } -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 59738af40..df41d995b 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -20,7 +20,6 @@ public:      explicit ConfigureGeneral(QWidget* parent = nullptr);      ~ConfigureGeneral() override; -    void PopulateHotkeyList(const HotkeyRegistry& registry);      void applyConfiguration();  private: diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index 01d1c0b8e..1a5721fe7 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -98,22 +98,6 @@        </widget>       </item>       <item> -      <widget class="QGroupBox" name="HotKeysGroupBox"> -       <property name="title"> -        <string>Hotkeys</string> -       </property> -       <layout class="QHBoxLayout" name="HotKeysHorizontalLayout"> -        <item> -         <layout class="QVBoxLayout" name="HotKeysVerticalLayout"> -          <item> -           <widget class="GHotkeysDialog" name="widget" native="true"/> -          </item> -         </layout> -        </item> -       </layout> -      </widget> -     </item> -     <item>        <spacer name="verticalSpacer">         <property name="orientation">          <enum>Qt::Vertical</enum> @@ -130,14 +114,6 @@     </item>    </layout>   </widget> - <customwidgets> -  <customwidget> -   <class>GHotkeysDialog</class> -   <extends>QWidget</extends> -   <header>hotkeys.h</header> -   <container>1</container> -  </customwidget> - </customwidgets>   <resources/>   <connections/>  </ui> diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp new file mode 100644 index 000000000..bfb562535 --- /dev/null +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -0,0 +1,121 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <QMessageBox> +#include <QStandardItemModel> +#include "core/settings.h" +#include "ui_configure_hotkeys.h" +#include "yuzu/configuration/configure_hotkeys.h" +#include "yuzu/hotkeys.h" +#include "yuzu/util/sequence_dialog/sequence_dialog.h" + +ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) +    : QWidget(parent), ui(std::make_unique<Ui::ConfigureHotkeys>()) { +    ui->setupUi(this); +    setFocusPolicy(Qt::ClickFocus); + +    model = new QStandardItemModel(this); +    model->setColumnCount(3); +    model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")}); + +    connect(ui->hotkey_list, &QTreeView::doubleClicked, this, &ConfigureHotkeys::Configure); +    ui->hotkey_list->setModel(model); + +    // TODO(Kloen): Make context configurable as well (hiding the column for now) +    ui->hotkey_list->hideColumn(2); + +    ui->hotkey_list->setColumnWidth(0, 200); +    ui->hotkey_list->resizeColumnToContents(1); +} + +ConfigureHotkeys::~ConfigureHotkeys() = default; + +void ConfigureHotkeys::EmitHotkeysChanged() { +    emit HotkeysChanged(GetUsedKeyList()); +} + +QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() const { +    QList<QKeySequence> list; +    for (int r = 0; r < model->rowCount(); r++) { +        const QStandardItem* parent = model->item(r, 0); +        for (int r2 = 0; r2 < parent->rowCount(); r2++) { +            const QStandardItem* keyseq = parent->child(r2, 1); +            list << QKeySequence::fromString(keyseq->text(), QKeySequence::NativeText); +        } +    } +    return list; +} + +void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { +    for (const auto& group : registry.hotkey_groups) { +        auto* parent_item = new QStandardItem(group.first); +        parent_item->setEditable(false); +        for (const auto& hotkey : group.second) { +            auto* action = new QStandardItem(hotkey.first); +            auto* keyseq = +                new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); +            action->setEditable(false); +            keyseq->setEditable(false); +            parent_item->appendRow({action, keyseq}); +        } +        model->appendRow(parent_item); +    } + +    ui->hotkey_list->expandAll(); +} + +void ConfigureHotkeys::Configure(QModelIndex index) { +    if (index.parent() == QModelIndex()) +        return; + +    index = index.sibling(index.row(), 1); +    auto* model = ui->hotkey_list->model(); +    auto previous_key = model->data(index); + +    auto* hotkey_dialog = new SequenceDialog; +    int return_code = hotkey_dialog->exec(); + +    auto key_sequence = hotkey_dialog->GetSequence(); + +    if (return_code == QDialog::Rejected || key_sequence.isEmpty()) +        return; + +    if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { +        QMessageBox::critical(this, tr("Error in inputted key"), +                              tr("You're using a key that's already bound.")); +    } else { +        model->setData(index, key_sequence.toString(QKeySequence::NativeText)); +        EmitHotkeysChanged(); +    } +} + +bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) { +    return GetUsedKeyList().contains(key_sequence); +} + +void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { +    for (int key_id = 0; key_id < model->rowCount(); key_id++) { +        const QStandardItem* parent = model->item(key_id, 0); +        for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) { +            const QStandardItem* action = parent->child(key_column_id, 0); +            const QStandardItem* keyseq = parent->child(key_column_id, 1); +            for (auto& [group, sub_actions] : registry.hotkey_groups) { +                if (group != parent->text()) +                    continue; +                for (auto& [action_name, hotkey] : sub_actions) { +                    if (action_name != action->text()) +                        continue; +                    hotkey.keyseq = QKeySequence(keyseq->text()); +                } +            } +        } +    } + +    registry.SaveHotkeys(); +    Settings::Apply(); +} + +void ConfigureHotkeys::retranslateUi() { +    ui->retranslateUi(this); +} diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h new file mode 100644 index 000000000..cd203aad6 --- /dev/null +++ b/src/yuzu/configuration/configure_hotkeys.h @@ -0,0 +1,48 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <QWidget> +#include "core/settings.h" + +namespace Ui { +class ConfigureHotkeys; +} + +class HotkeyRegistry; +class QStandardItemModel; + +class ConfigureHotkeys : public QWidget { +    Q_OBJECT + +public: +    explicit ConfigureHotkeys(QWidget* parent = nullptr); +    ~ConfigureHotkeys() override; + +    void applyConfiguration(HotkeyRegistry& registry); +    void retranslateUi(); + +    void EmitHotkeysChanged(); + +    /** +     * Populates the hotkey list widget using data from the provided registry. +     * Called everytime the Configure dialog is opened. +     * @param registry The HotkeyRegistry whose data is used to populate the list. +     */ +    void Populate(const HotkeyRegistry& registry); + +signals: +    void HotkeysChanged(QList<QKeySequence> new_key_list); + +private: +    void Configure(QModelIndex index); +    bool IsUsedKey(QKeySequence key_sequence); +    QList<QKeySequence> GetUsedKeyList() const; + +    std::unique_ptr<Ui::ConfigureHotkeys> ui; + +    QStandardItemModel* model; +}; diff --git a/src/yuzu/configuration/configure_hotkeys.ui b/src/yuzu/configuration/configure_hotkeys.ui new file mode 100644 index 000000000..0d0b70f38 --- /dev/null +++ b/src/yuzu/configuration/configure_hotkeys.ui @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ConfigureHotkeys</class> + <widget class="QWidget" name="ConfigureHotkeys"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>363</width> +    <height>388</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Hotkey Settings</string> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout"> +   <item> +    <layout class="QVBoxLayout" name="verticalLayout_2"> +     <item> +      <widget class="QLabel" name="label_2"> +       <property name="text"> +        <string>Double-click on a binding to change it.</string> +       </property> +      </widget> +     </item> +     <item> +      <widget class="QTreeView" name="hotkey_list"> +       <property name="editTriggers"> +        <set>QAbstractItemView::NoEditTriggers</set> +       </property> +       <property name="sortingEnabled"> +        <bool>false</bool> +       </property> +      </widget> +     </item> +    </layout> +   </item> +  </layout> + </widget> + <resources/> + <connections/> +</ui>
\ No newline at end of file | 
