all repos — mgba @ 03ca7515b3e79a1d2c34ca93e7d5d1c487820a7a

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