src/platform/qt/CheatsView.cpp (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "CheatsView.h"
7
8#include "GBAApp.h"
9#include "GameController.h"
10
11#include <QClipboard>
12#include <QPushButton>
13
14extern "C" {
15#include "core/cheats.h"
16#ifdef M_CORE_GBA
17#include "gba/cheats.h"
18#endif
19#ifdef M_CORE_GB
20#include "gb/cheats.h"
21#endif
22}
23
24using namespace QGBA;
25
26CheatsView::CheatsView(GameController* controller, QWidget* parent)
27 : QWidget(parent)
28 , m_controller(controller)
29 , m_model(controller->cheatDevice())
30{
31 m_ui.setupUi(this);
32
33 m_ui.cheatList->installEventFilter(this);
34 m_ui.cheatList->setModel(&m_model);
35
36 connect(m_ui.load, SIGNAL(clicked()), this, SLOT(load()));
37 connect(m_ui.save, SIGNAL(clicked()), this, SLOT(save()));
38 connect(m_ui.addSet, SIGNAL(clicked()), this, SLOT(addSet()));
39 connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet()));
40 connect(controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
41 connect(controller, SIGNAL(stateLoaded(mCoreThread*)), &m_model, SLOT(invalidated()));
42
43 QPushButton* add;
44 switch (controller->platform()) {
45#ifdef M_CORE_GBA
46 case PLATFORM_GBA:
47 connect(m_ui.add, &QPushButton::clicked, [this]() {
48 enterCheat(GBA_CHEAT_AUTODETECT);
49 });
50
51 add = new QPushButton("Add GameShark");
52 m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
53 connect(add, &QPushButton::clicked, [this]() {
54 enterCheat(GBA_CHEAT_GAMESHARK);
55 });
56
57 add = new QPushButton("Add Pro Action Replay");
58 m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
59 connect(add, &QPushButton::clicked, [this]() {
60 enterCheat(GBA_CHEAT_PRO_ACTION_REPLAY);
61 });
62
63 add = new QPushButton("Add CodeBreaker");
64 m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
65 connect(add, &QPushButton::clicked, [this]() {
66 enterCheat(GBA_CHEAT_CODEBREAKER);
67 });
68 break;
69#endif
70#ifdef M_CORE_GB
71 case PLATFORM_GB:
72 connect(m_ui.add, &QPushButton::clicked, [this]() {
73 enterCheat(GB_CHEAT_AUTODETECT);
74 });
75
76 add = new QPushButton("Add GameShark");
77 m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
78 connect(add, &QPushButton::clicked, [this]() {
79 enterCheat(GB_CHEAT_GAMESHARK);
80 });
81
82 add = new QPushButton("Add GameGenie");
83 m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
84 connect(add, &QPushButton::clicked, [this]() {
85 enterCheat(GB_CHEAT_GAME_GENIE);
86 });
87 break;
88#endif
89 default:
90 break;
91 }
92
93 // Stretch the cheat list back into place
94 int index = m_ui.gridLayout->indexOf(m_ui.cheatList);
95 m_ui.gridLayout->takeAt(index);
96 m_ui.gridLayout->addWidget(m_ui.cheatList, 0, 0, -1, 1);
97}
98
99bool CheatsView::eventFilter(QObject* object, QEvent* event) {
100 if (object != m_ui.cheatList) {
101 return false;
102 }
103 if (event->type() != QEvent::KeyPress) {
104 return false;
105 }
106 if (static_cast<QKeyEvent*>(event) == QKeySequence::Copy) {
107 QApplication::clipboard()->setText(m_model.toString(m_ui.cheatList->selectionModel()->selectedIndexes()));
108 return true;
109 }
110 return false;
111}
112
113void CheatsView::load() {
114 QString filename = GBAApp::app()->getOpenFileName(this, tr("Select cheats file"));
115 if (!filename.isEmpty()) {
116 m_model.loadFile(filename);
117 }
118}
119
120void CheatsView::save() {
121 QString filename = GBAApp::app()->getSaveFileName(this, tr("Select cheats file"));
122 if (!filename.isEmpty()) {
123 m_model.saveFile(filename);
124 }
125}
126
127void CheatsView::addSet() {
128 m_controller->threadInterrupt();
129 mCheatSet* set = m_controller->cheatDevice()->createSet(m_controller->cheatDevice(), nullptr);
130 m_model.addSet(set);
131 m_controller->threadContinue();
132}
133
134void CheatsView::removeSet() {
135 GBACheatSet* set;
136 QModelIndexList selection = m_ui.cheatList->selectionModel()->selectedIndexes();
137 if (selection.count() < 1) {
138 return;
139 }
140 m_controller->threadInterrupt();
141 for (const QModelIndex& index : selection) {
142 m_model.removeAt(selection[0]);
143 }
144 m_controller->threadContinue();
145}
146
147void CheatsView::enterCheat(int codeType) {
148 mCheatSet* set = nullptr;
149 QModelIndexList selection = m_ui.cheatList->selectionModel()->selectedIndexes();
150 QModelIndex index;
151 if (selection.count() == 0) {
152 set = m_controller->cheatDevice()->createSet(m_controller->cheatDevice(), nullptr);
153 } else if (selection.count() == 1) {
154 index = selection[0];
155 set = m_model.itemAt(index);
156 }
157
158 if (!set) {
159 return;
160 }
161 m_controller->threadInterrupt();
162 if (selection.count() == 0) {
163 m_model.addSet(set);
164 index = m_model.index(m_model.rowCount() - 1, 0, QModelIndex());
165 m_ui.cheatList->selectionModel()->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
166 }
167 QStringList cheats = m_ui.codeEntry->toPlainText().split('\n', QString::SkipEmptyParts);
168 for (const QString& string : cheats) {
169 m_model.beginAppendRow(index);
170 mCheatAddLine(set, string.toUtf8().constData(), codeType);
171 m_model.endAppendRow();
172 }
173 set->refresh(set, m_controller->cheatDevice());
174 m_controller->threadContinue();
175 m_ui.codeEntry->clear();
176}