Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Merge pull request #5984 from spycrab/qt_gecko
Qt/GameList: Implement "Gecko codes" Tab
- Loading branch information
Showing
17 changed files
with
443 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| // Copyright 2017 Dolphin Emulator Project | ||
| // Licensed under GPLv2+ | ||
| // Refer to the license.txt file included. | ||
|
|
||
| #include "DolphinQt2/Config/CheatWarningWidget.h" | ||
|
|
||
| #include <QHBoxLayout> | ||
| #include <QLabel> | ||
| #include <QPixmap> | ||
| #include <QPushButton> | ||
| #include <QStyle> | ||
|
|
||
| #include <iostream> | ||
|
|
||
| #include "Core/ConfigManager.h" | ||
| #include "Core/Core.h" | ||
| #include "DolphinQt2/Settings.h" | ||
|
|
||
| CheatWarningWidget::CheatWarningWidget(const std::string& game_id) : m_game_id(game_id) | ||
| { | ||
| CreateWidgets(); | ||
| ConnectWidgets(); | ||
|
|
||
| connect(&Settings::Instance(), &Settings::EnableCheatsChanged, | ||
| [this] { Update(Core::IsRunning()); }); | ||
| connect(&Settings::Instance(), &Settings::EmulationStateChanged, [this](Core::State state) { | ||
| std::cout << (state == Core::State::Running) << std::endl; | ||
| Update(state == Core::State::Running); | ||
| }); | ||
|
|
||
| Update(Core::IsRunning()); | ||
| } | ||
|
|
||
| void CheatWarningWidget::CreateWidgets() | ||
| { | ||
| auto* icon = new QLabel; | ||
|
|
||
| const auto size = 1.5 * QFontMetrics(font()).height(); | ||
|
|
||
| QPixmap warning_icon = style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(size, size); | ||
|
|
||
| icon->setPixmap(warning_icon); | ||
|
|
||
| m_text = new QLabel(); | ||
| m_config_button = new QPushButton(tr("Configure Dolphin")); | ||
|
|
||
| m_config_button->setHidden(true); | ||
|
|
||
| auto* layout = new QHBoxLayout; | ||
|
|
||
| layout->addWidget(icon); | ||
| layout->addWidget(m_text, 1); | ||
| layout->addWidget(m_config_button); | ||
|
|
||
| layout->setContentsMargins(0, 0, 0, 0); | ||
|
|
||
| setLayout(layout); | ||
| } | ||
|
|
||
| void CheatWarningWidget::Update(bool running) | ||
| { | ||
| bool hide_widget = true; | ||
| bool hide_config_button = true; | ||
|
|
||
| if (running && SConfig::GetInstance().GetGameID() == m_game_id) | ||
| { | ||
| hide_widget = false; | ||
| m_text->setText(tr("Changing cheats will only take effect when the game is restarted.")); | ||
| } | ||
|
|
||
| if (!Settings::Instance().GetCheatsEnabled()) | ||
| { | ||
| hide_widget = false; | ||
| hide_config_button = false; | ||
| m_text->setText(tr("Dolphin's cheat system is currently disabled.")); | ||
| } | ||
|
|
||
| setHidden(hide_widget); | ||
| m_config_button->setHidden(hide_config_button); | ||
| } | ||
|
|
||
| void CheatWarningWidget::ConnectWidgets() | ||
| { | ||
| connect(m_config_button, &QPushButton::pressed, this, | ||
| &CheatWarningWidget::OpenCheatEnableSettings); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // Copyright 2017 Dolphin Emulator Project | ||
| // Licensed under GPLv2+ | ||
| // Refer to the license.txt file included. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <QWidget> | ||
|
|
||
| #include <string> | ||
|
|
||
| class QLabel; | ||
| class QPushButton; | ||
|
|
||
| class CheatWarningWidget : public QWidget | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
| explicit CheatWarningWidget(const std::string& game_id); | ||
|
|
||
| signals: | ||
| void OpenCheatEnableSettings(); | ||
|
|
||
| private: | ||
| void CreateWidgets(); | ||
| void ConnectWidgets(); | ||
|
|
||
| void Update(bool running); | ||
|
|
||
| QLabel* m_text; | ||
| QPushButton* m_config_button; | ||
| const std::string m_game_id; | ||
| }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,207 @@ | ||
| // Copyright 2017 Dolphin Emulator Project | ||
| // Licensed under GPLv2+ | ||
| // Refer to the license.txt file included. | ||
|
|
||
| #include "DolphinQt2/Config/GeckoCodeWidget.h" | ||
|
|
||
| #include <QFontDatabase> | ||
| #include <QFormLayout> | ||
| #include <QLabel> | ||
| #include <QListWidget> | ||
| #include <QMessageBox> | ||
| #include <QPushButton> | ||
| #include <QTextEdit> | ||
| #include <QVBoxLayout> | ||
|
|
||
| #include "Common/FileUtil.h" | ||
| #include "Common/IniFile.h" | ||
| #include "Core/ConfigManager.h" | ||
| #include "Core/GeckoCodeConfig.h" | ||
| #include "DolphinQt2/Config/CheatWarningWidget.h" | ||
| #include "DolphinQt2/GameList/GameFile.h" | ||
|
|
||
| GeckoCodeWidget::GeckoCodeWidget(const GameFile& game) | ||
| : m_game(game), m_game_id(game.GetGameID().toStdString()), m_game_revision(game.GetRevision()) | ||
| { | ||
| CreateWidgets(); | ||
| ConnectWidgets(); | ||
|
|
||
| IniFile game_ini_local; | ||
|
|
||
| // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI | ||
| // will always be stored in GS/${GAMEID}.ini | ||
| game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); | ||
|
|
||
| IniFile game_ini_default = SConfig::GetInstance().LoadDefaultGameIni(m_game_id, m_game_revision); | ||
| m_gecko_codes = Gecko::LoadCodes(game_ini_default, game_ini_local); | ||
|
|
||
| UpdateList(); | ||
| } | ||
|
|
||
| void GeckoCodeWidget::CreateWidgets() | ||
| { | ||
| m_warning = new CheatWarningWidget(m_game_id); | ||
| m_code_list = new QListWidget; | ||
| m_name_label = new QLabel; | ||
| m_creator_label = new QLabel; | ||
|
|
||
| QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); | ||
|
|
||
| const auto line_height = QFontMetrics(font()).lineSpacing(); | ||
|
|
||
| m_code_description = new QTextEdit; | ||
| m_code_description->setFont(monospace); | ||
| m_code_description->setReadOnly(true); | ||
| m_code_description->setFixedHeight(line_height * 5); | ||
|
|
||
| m_code_view = new QTextEdit; | ||
| m_code_view->setFont(monospace); | ||
| m_code_view->setReadOnly(true); | ||
| m_code_view->setFixedHeight(line_height * 10); | ||
|
|
||
| m_download_codes = new QPushButton(tr("Download Codes (WiiRD Database)")); | ||
| m_download_codes->setEnabled(!m_game_id.empty()); | ||
| m_download_codes->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); | ||
|
|
||
| auto* layout = new QVBoxLayout; | ||
|
|
||
| layout->addWidget(m_warning); | ||
| layout->addWidget(m_code_list); | ||
|
|
||
| auto* info_layout = new QFormLayout; | ||
|
|
||
| info_layout->addRow(tr("Name:"), m_name_label); | ||
| info_layout->addRow(tr("Creator:"), m_creator_label); | ||
| info_layout->addRow(tr("Description:"), static_cast<QWidget*>(nullptr)); | ||
|
|
||
| info_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop); | ||
|
|
||
| for (QLabel* label : {m_name_label, m_creator_label}) | ||
| { | ||
| label->setTextInteractionFlags(Qt::TextSelectableByMouse); | ||
| label->setCursor(Qt::IBeamCursor); | ||
| } | ||
|
|
||
| layout->addLayout(info_layout); | ||
| layout->addWidget(m_code_description); | ||
| layout->addWidget(m_code_view); | ||
| layout->addWidget(m_download_codes, 0, Qt::AlignRight); | ||
|
|
||
| setLayout(layout); | ||
| } | ||
|
|
||
| void GeckoCodeWidget::ConnectWidgets() | ||
| { | ||
| connect(m_code_list, &QListWidget::itemSelectionChanged, this, | ||
| &GeckoCodeWidget::OnSelectionChanged); | ||
| connect(m_code_list, &QListWidget::itemChanged, this, &GeckoCodeWidget::OnItemChanged); | ||
|
|
||
| connect(m_download_codes, &QPushButton::pressed, this, &GeckoCodeWidget::DownloadCodes); | ||
|
|
||
| connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this, | ||
| &GeckoCodeWidget::OpenGeneralSettings); | ||
| } | ||
|
|
||
| void GeckoCodeWidget::OnSelectionChanged() | ||
| { | ||
| auto items = m_code_list->selectedItems(); | ||
|
|
||
| if (items.empty()) | ||
| return; | ||
|
|
||
| auto selected = items[0]; | ||
|
|
||
| const auto& code = m_gecko_codes[m_code_list->row(selected)]; | ||
|
|
||
| m_name_label->setText(QString::fromStdString(code.name)); | ||
| m_creator_label->setText(QString::fromStdString(code.creator)); | ||
|
|
||
| m_code_description->clear(); | ||
|
|
||
| if (code.notes.empty()) | ||
| m_code_description->append(tr("N/A")); | ||
|
|
||
| for (const auto& line : code.notes) | ||
| m_code_description->append(QString::fromStdString(line)); | ||
|
|
||
| m_code_view->clear(); | ||
|
|
||
| for (const auto& c : code.codes) | ||
| m_code_view->append(QStringLiteral("%1 %2") | ||
| .arg(c.address, 8, 16, QLatin1Char('0')) | ||
| .arg(c.data, 8, 16, QLatin1Char('0'))); | ||
| } | ||
|
|
||
| void GeckoCodeWidget::OnItemChanged(QListWidgetItem* item) | ||
| { | ||
| m_gecko_codes[m_code_list->row(item)].enabled = (item->checkState() == Qt::Checked); | ||
|
|
||
| SaveCodes(); | ||
| } | ||
|
|
||
| void GeckoCodeWidget::SaveCodes() | ||
| { | ||
| IniFile game_ini_local; | ||
| game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); | ||
| Gecko::SaveCodes(game_ini_local, m_gecko_codes); | ||
|
|
||
| game_ini_local.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); | ||
| } | ||
|
|
||
| void GeckoCodeWidget::UpdateList() | ||
| { | ||
| m_code_list->clear(); | ||
|
|
||
| for (size_t i = 0; i < m_gecko_codes.size(); i++) | ||
| { | ||
| const auto& code = m_gecko_codes[i]; | ||
|
|
||
| auto* item = new QListWidgetItem(QString::fromStdString(code.name) | ||
| .replace(QStringLiteral("<"), QStringLiteral("<")) | ||
| .replace(QStringLiteral(">"), QStringLiteral(">"))); | ||
|
|
||
| item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); | ||
| item->setCheckState(code.enabled ? Qt::Checked : Qt::Unchecked); | ||
|
|
||
| m_code_list->addItem(item); | ||
| } | ||
| } | ||
|
|
||
| void GeckoCodeWidget::DownloadCodes() | ||
| { | ||
| bool success; | ||
|
|
||
| std::vector<Gecko::GeckoCode> codes = Gecko::DownloadCodes(m_game_id, &success); | ||
|
|
||
| if (!success) | ||
| { | ||
| QMessageBox::critical(this, tr("Error"), tr("Failed to download codes.")); | ||
| return; | ||
| } | ||
|
|
||
| if (codes.empty()) | ||
| { | ||
| QMessageBox::critical(this, tr("Error"), tr("File contained no codes.")); | ||
| return; | ||
| } | ||
|
|
||
| size_t added_count = 0; | ||
|
|
||
| for (const auto& code : codes) | ||
| { | ||
| auto it = std::find(m_gecko_codes.begin(), m_gecko_codes.end(), code); | ||
|
|
||
| if (it == m_gecko_codes.end()) | ||
| { | ||
| m_gecko_codes.push_back(code); | ||
| added_count++; | ||
| } | ||
| } | ||
|
|
||
| UpdateList(); | ||
| SaveCodes(); | ||
|
|
||
| QMessageBox::information(this, tr("Download complete"), | ||
| tr("Downloaded %1 codes. (added %2)") | ||
| .arg(QString::number(codes.size()), QString::number(added_count))); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // Copyright 2017 Dolphin Emulator Project | ||
| // Licensed under GPLv2+ | ||
| // Refer to the license.txt file included. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <QWidget> | ||
|
|
||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include "Common/CommonTypes.h" | ||
| #include "Core/GeckoCode.h" | ||
|
|
||
| class CheatWarningWidget; | ||
| class GameFile; | ||
| class QLabel; | ||
| class QListWidget; | ||
| class QListWidgetItem; | ||
| class QTextEdit; | ||
| class QPushButton; | ||
|
|
||
| class GeckoCodeWidget : public QWidget | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
| explicit GeckoCodeWidget(const GameFile& game); | ||
|
|
||
| signals: | ||
| void OpenGeneralSettings(); | ||
|
|
||
| private: | ||
| void OnSelectionChanged(); | ||
| void OnItemChanged(QListWidgetItem* item); | ||
|
|
||
| void CreateWidgets(); | ||
| void ConnectWidgets(); | ||
| void UpdateList(); | ||
| void DownloadCodes(); | ||
| void SaveCodes(); | ||
|
|
||
| const GameFile& m_game; | ||
| std::string m_game_id; | ||
| u8 m_game_revision; | ||
|
|
||
| CheatWarningWidget* m_warning; | ||
| QListWidget* m_code_list; | ||
| QLabel* m_name_label; | ||
| QLabel* m_creator_label; | ||
| QTextEdit* m_code_description; | ||
| QTextEdit* m_code_view; | ||
| QPushButton* m_download_codes; | ||
| std::vector<Gecko::GeckoCode> m_gecko_codes; | ||
| }; |
Oops, something went wrong.