all repos — mgba @ 6dd39389e0738df072656f561dae7a2b854b3095

mGBA Game Boy Advance Emulator

src/platform/qt/GBAApp.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 "GBAApp.h"
  7
  8#include "AudioProcessor.h"
  9#include "Display.h"
 10#include "GameController.h"
 11#include "Window.h"
 12#include "VFileDevice.h"
 13
 14#include <QFileInfo>
 15#include <QFileOpenEvent>
 16#include <QIcon>
 17
 18extern "C" {
 19#include "core/version.h"
 20#include "feature/commandline.h"
 21#include "util/nointro.h"
 22#include "util/socket.h"
 23}
 24
 25using namespace QGBA;
 26
 27static GBAApp* g_app = nullptr;
 28
 29mLOG_DEFINE_CATEGORY(QT, "Qt");
 30
 31GBAApp::GBAApp(int& argc, char* argv[])
 32	: QApplication(argc, argv)
 33	, m_windows{}
 34	, m_db(nullptr)
 35{
 36	g_app = this;
 37
 38#ifdef BUILD_SDL
 39	SDL_Init(SDL_INIT_NOPARACHUTE);
 40#endif
 41
 42#ifndef Q_OS_MAC
 43	setWindowIcon(QIcon(":/res/mgba-1024.png"));
 44#endif
 45
 46	SocketSubsystemInit();
 47	qRegisterMetaType<const uint32_t*>("const uint32_t*");
 48	qRegisterMetaType<mCoreThread*>("mCoreThread*");
 49
 50	QApplication::setApplicationName(projectName);
 51	QApplication::setApplicationVersion(projectVersion);
 52
 53	if (!m_configController.getQtOption("displayDriver").isNull()) {
 54		Display::setDriver(static_cast<Display::Driver>(m_configController.getQtOption("displayDriver").toInt()));
 55	}
 56
 57	mArguments args;
 58	mGraphicsOpts graphicsOpts;
 59	mSubParser subparser;
 60	initParserForGraphics(&subparser, &graphicsOpts);
 61	bool loaded = m_configController.parseArguments(&args, argc, argv, &subparser);
 62	if (loaded && args.showHelp) {
 63		usage(argv[0], subparser.usage);
 64		::exit(0);
 65		return;
 66	}
 67
 68	reloadGameDB();
 69
 70	if (!m_configController.getQtOption("audioDriver").isNull()) {
 71		AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt()));
 72	}
 73	Window* w = new Window(&m_configController);
 74	connect(w, &Window::destroyed, [this]() {
 75		m_windows[0] = nullptr;
 76	});
 77	m_windows[0] = w;
 78
 79	if (loaded) {
 80		w->argumentsPassed(&args);
 81	} else {
 82		w->loadConfig();
 83	}
 84	freeArguments(&args);
 85
 86	if (graphicsOpts.multiplier) {
 87		w->resizeFrame(QSize(VIDEO_HORIZONTAL_PIXELS * graphicsOpts.multiplier, VIDEO_VERTICAL_PIXELS * graphicsOpts.multiplier));
 88	}
 89	if (graphicsOpts.fullscreen) {
 90		w->enterFullScreen();
 91	}
 92
 93	w->show();
 94
 95	w->controller()->setMultiplayerController(&m_multiplayer);
 96	w->multiplayerChanged();
 97}
 98
 99bool GBAApp::event(QEvent* event) {
100	if (event->type() == QEvent::FileOpen) {
101		m_windows[0]->controller()->loadGame(static_cast<QFileOpenEvent*>(event)->file());
102		return true;
103	}
104	return QApplication::event(event);
105}
106
107Window* GBAApp::newWindow() {
108	if (m_multiplayer.attached() >= MAX_GBAS) {
109		return nullptr;
110	}
111	Window* w = new Window(&m_configController, m_multiplayer.attached());
112	int windowId = m_multiplayer.attached();
113	connect(w, &Window::destroyed, [this, windowId]() {
114		m_windows[windowId] = nullptr;
115	});
116	m_windows[windowId] = w;
117	w->setAttribute(Qt::WA_DeleteOnClose);
118	w->loadConfig();
119	w->show();
120	w->controller()->setMultiplayerController(&m_multiplayer);
121	w->multiplayerChanged();
122	return w;
123}
124
125GBAApp* GBAApp::app() {
126	return g_app;
127}
128
129void GBAApp::pauseAll(QList<int>* paused) {
130	for (int i = 0; i < MAX_GBAS; ++i) {
131		if (!m_windows[i] || !m_windows[i]->controller()->isLoaded() || m_windows[i]->controller()->isPaused()) {
132			continue;
133		}
134		m_windows[i]->controller()->setPaused(true);
135		paused->append(i);
136	}
137}
138
139void GBAApp::continueAll(const QList<int>* paused) {
140	for (int i : *paused) {
141		m_windows[i]->controller()->setPaused(false);
142	}
143}
144
145QString GBAApp::getOpenFileName(QWidget* owner, const QString& title, const QString& filter) {
146	QList<int> paused;
147	pauseAll(&paused);
148	QString filename = QFileDialog::getOpenFileName(owner, title, m_configController.getQtOption("lastDirectory").toString(), filter);
149	continueAll(&paused);
150	if (!filename.isEmpty()) {
151		m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path());
152	}
153	return filename;
154}
155
156QString GBAApp::getSaveFileName(QWidget* owner, const QString& title, const QString& filter) {
157	QList<int> paused;
158	pauseAll(&paused);
159	QString filename = QFileDialog::getSaveFileName(owner, title, m_configController.getQtOption("lastDirectory").toString(), filter);
160	continueAll(&paused);
161	if (!filename.isEmpty()) {
162		m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path());
163	}
164	return filename;
165}
166
167QString GBAApp::getOpenDirectoryName(QWidget* owner, const QString& title) {
168	QList<int> paused;
169	pauseAll(&paused);
170	QString filename = QFileDialog::getExistingDirectory(owner, title, m_configController.getQtOption("lastDirectory").toString());
171	continueAll(&paused);
172	if (!filename.isEmpty()) {
173		m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path());
174	}
175	return filename;
176}
177
178QFileDialog* GBAApp::getOpenFileDialog(QWidget* owner, const QString& title, const QString& filter) {
179	FileDialog* dialog = new FileDialog(this, owner, title, filter);
180	dialog->setAcceptMode(QFileDialog::AcceptOpen);
181	return dialog;
182}
183
184QFileDialog* GBAApp::getSaveFileDialog(QWidget* owner, const QString& title, const QString& filter) {
185	FileDialog* dialog = new FileDialog(this, owner, title, filter);
186	dialog->setAcceptMode(QFileDialog::AcceptSave);
187	return dialog;
188}
189
190QString GBAApp::dataDir() {
191#ifdef DATADIR
192	QString path = QString::fromUtf8(DATADIR);
193#else
194	QString path = QCoreApplication::applicationDirPath();
195#ifdef Q_OS_MAC
196	path += QLatin1String("/../Resources");
197#endif
198#endif
199	return path;
200}
201
202bool GBAApp::reloadGameDB() {
203	NoIntroDB* db = nullptr;
204	VFile* vf = VFileDevice::open(dataDir() + "/nointro.dat", O_RDONLY);
205	if (vf) {
206		db = NoIntroDBLoad(vf);
207		vf->close(vf);
208	}
209	if (db && m_db) {
210		NoIntroDBDestroy(m_db);
211	}
212	if (db) {
213		m_db = db;
214		return true;
215	}
216	return false;
217}
218
219GBAApp::FileDialog::FileDialog(GBAApp* app, QWidget* parent, const QString& caption, const QString& filter)
220	: QFileDialog(parent, caption, app->m_configController.getQtOption("lastDirectory").toString(), filter)
221	, m_app(app)
222{
223}
224
225int GBAApp::FileDialog::exec() {
226	QList<int> paused;
227	m_app->pauseAll(&paused);
228	bool didAccept = QFileDialog::exec() == QDialog::Accepted;
229	QStringList filenames = selectedFiles();
230	if (!filenames.isEmpty()) {
231		m_app->m_configController.setQtOption("lastDirectory", QFileInfo(filenames[0]).dir().path());
232	}
233	m_app->continueAll(&paused);
234	return didAccept;
235}