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