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