src/platform/qt/LoadSaveState.cpp (view raw)
1/* Copyright (c) 2013-2014 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 "LoadSaveState.h"
7
8#include "GameController.h"
9#include "GamepadButtonEvent.h"
10#include "VFileDevice.h"
11
12#include <QKeyEvent>
13#include <QPainter>
14
15extern "C" {
16#include "gba-serialize.h"
17#include "gba-video.h"
18}
19
20using namespace QGBA;
21
22LoadSaveState::LoadSaveState(GameController* controller, QWidget* parent)
23 : QWidget(parent)
24 , m_controller(controller)
25 , m_currentFocus(0)
26{
27 m_ui.setupUi(this);
28
29 m_slots[0] = m_ui.state1;
30 m_slots[1] = m_ui.state2;
31 m_slots[2] = m_ui.state3;
32 m_slots[3] = m_ui.state4;
33 m_slots[4] = m_ui.state5;
34 m_slots[5] = m_ui.state6;
35 m_slots[6] = m_ui.state7;
36 m_slots[7] = m_ui.state8;
37 m_slots[8] = m_ui.state9;
38
39 int i;
40 for (i = 0; i < NUM_SLOTS; ++i) {
41 loadState(i + 1);
42 m_slots[i]->installEventFilter(this);
43 connect(m_slots[i], &QAbstractButton::clicked, this, [this, i]() { triggerState(i + 1); });
44 }
45}
46
47void LoadSaveState::setMode(LoadSave mode) {
48 m_mode = mode;
49 QString text = mode == LoadSave::LOAD ? tr("Load State") : tr("Save State");
50 setWindowTitle(text);
51 m_ui.lsLabel->setText(text);
52}
53
54bool LoadSaveState::eventFilter(QObject* object, QEvent* event) {
55 if (event->type() == QEvent::KeyPress) {
56 int column = m_currentFocus % 3;
57 int row = m_currentFocus - column;
58 switch (static_cast<QKeyEvent*>(event)->key()) {
59 case Qt::Key_Up:
60 row += 6;
61 break;
62 case Qt::Key_Down:
63 row += 3;
64 break;
65 case Qt::Key_Left:
66 column += 2;
67 break;
68 case Qt::Key_Right:
69 column += 1;
70 break;
71 case Qt::Key_1:
72 case Qt::Key_2:
73 case Qt::Key_3:
74 case Qt::Key_4:
75 case Qt::Key_5:
76 case Qt::Key_6:
77 case Qt::Key_7:
78 case Qt::Key_8:
79 case Qt::Key_9:
80 triggerState(static_cast<QKeyEvent*>(event)->key() - Qt::Key_1 + 1);
81 break;
82 case Qt::Key_Escape:
83 close();
84 break;
85 case Qt::Key_Enter:
86 case Qt::Key_Return:
87 triggerState(m_currentFocus + 1);
88 break;
89 default:
90 return false;
91 }
92 column %= 3;
93 row %= 9;
94 m_currentFocus = column + row;
95 m_slots[m_currentFocus]->setFocus();
96 return true;
97 }
98 if (event->type() == QEvent::Enter) {
99 int i;
100 for (i = 0; i < 9; ++i) {
101 if (m_slots[i] == object) {
102 m_currentFocus = i;
103 m_slots[m_currentFocus]->setFocus();
104 return true;
105 }
106 }
107 }
108 if (event->type() == GamepadButtonEvent::Down()) {
109 int column = m_currentFocus % 3;
110 int row = m_currentFocus - column;
111 switch (static_cast<GamepadButtonEvent*>(event)->gbaKey()) {
112 case GBA_KEY_UP:
113 row += 6;
114 break;
115 case GBA_KEY_DOWN:
116 row += 3;
117 break;
118 case GBA_KEY_LEFT:
119 column += 2;
120 break;
121 case GBA_KEY_RIGHT:
122 column += 1;
123 break;
124 case GBA_KEY_B:
125 event->accept();
126 close();
127 return true;
128 case GBA_KEY_A:
129 case GBA_KEY_START:
130 event->accept();
131 triggerState(m_currentFocus + 1);
132 return true;
133 default:
134 return false;
135 }
136 column %= 3;
137 row %= 9;
138 m_currentFocus = column + row;
139 m_slots[m_currentFocus]->setFocus();
140 event->accept();
141 return true;
142 }
143 return false;
144}
145
146void LoadSaveState::loadState(int slot) {
147 GBAThread* thread = m_controller->thread();
148 VFile* vf = GBAGetState(thread->gba, thread->stateDir, slot, false);
149 if (!vf) {
150 m_slots[slot - 1]->setText(tr("Empty"));
151 return;
152 }
153 VFileDevice vdev(vf);
154 QImage stateImage;
155 stateImage.load(&vdev, "PNG");
156 if (!stateImage.isNull()) {
157 QPixmap statePixmap;
158 statePixmap.convertFromImage(stateImage);
159 m_slots[slot - 1]->setIcon(statePixmap);
160 m_slots[slot - 1]->setText(QString());
161 } else {
162 m_slots[slot - 1]->setText(tr("Slot %1").arg(slot));
163 }
164}
165
166void LoadSaveState::triggerState(int slot) {
167 if (m_mode == LoadSave::SAVE) {
168 m_controller->saveState(slot);
169 } else {
170 m_controller->loadState(slot);
171 }
172 close();
173}
174
175void LoadSaveState::closeEvent(QCloseEvent* event) {
176 emit closed();
177 QWidget::closeEvent(event);
178}
179
180void LoadSaveState::showEvent(QShowEvent* event) {
181 m_slots[m_currentFocus]->setFocus();
182 QWidget::showEvent(event);
183}
184
185void LoadSaveState::paintEvent(QPaintEvent*) {
186 QPainter painter(this);
187 QRect full(QPoint(), size());
188 painter.drawPixmap(full, m_currentImage);
189 painter.fillRect(full, QColor(0, 0, 0, 128));
190}