all repos — mgba @ 556209e75f3bf9d36af956d71c76b3211d4e3601

mGBA Game Boy Advance Emulator

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}