all repos — mgba @ a9f0fabdd278ea847af78822023cd8651aa34af8

mGBA Game Boy Advance Emulator

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}