src/platform/qt/Window.cpp (view raw)
1#include "Window.h"
2
3#include <QFileDialog>
4#include <QKeyEvent>
5#include <QKeySequence>
6#include <QMenuBar>
7
8#include "GDBWindow.h"
9#include "GDBController.h"
10
11using namespace QGBA;
12
13Window::Window(QWidget* parent)
14 : QMainWindow(parent)
15#ifdef USE_GDB_STUB
16 , m_gdbController(nullptr)
17#endif
18{
19 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
20 setMinimumSize(240, 160);
21
22 m_controller = new GameController(this);
23 m_display = new Display();
24 setCentralWidget(m_display);
25 connect(m_controller, SIGNAL(audioDeviceAvailable(GBAAudio*)), this, SLOT(setupAudio(GBAAudio*)));
26 connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*)));
27 connect(this, SIGNAL(startDrawing(const uint32_t*, GBAThread*)), m_display, SLOT(startDrawing(const uint32_t*, GBAThread*)), Qt::QueuedConnection);
28 connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing()));
29
30 setupMenu(menuBar());
31}
32
33GBAKey Window::mapKey(int qtKey) {
34 switch (qtKey) {
35 case Qt::Key_Z:
36 return GBA_KEY_A;
37 break;
38 case Qt::Key_X:
39 return GBA_KEY_B;
40 break;
41 case Qt::Key_A:
42 return GBA_KEY_L;
43 break;
44 case Qt::Key_S:
45 return GBA_KEY_R;
46 break;
47 case Qt::Key_Return:
48 return GBA_KEY_START;
49 break;
50 case Qt::Key_Backspace:
51 return GBA_KEY_SELECT;
52 break;
53 case Qt::Key_Up:
54 return GBA_KEY_UP;
55 break;
56 case Qt::Key_Down:
57 return GBA_KEY_DOWN;
58 break;
59 case Qt::Key_Left:
60 return GBA_KEY_LEFT;
61 break;
62 case Qt::Key_Right:
63 return GBA_KEY_RIGHT;
64 break;
65 default:
66 return GBA_KEY_NONE;
67 }
68}
69
70void Window::selectROM() {
71 QString filename = QFileDialog::getOpenFileName(this, tr("Select ROM"));
72 if (!filename.isEmpty()) {
73 m_controller->loadGame(filename);
74 }
75}
76
77#ifdef USE_GDB_STUB
78void Window::gdbOpen() {
79 if (!m_gdbController) {
80 m_gdbController = new GDBController(m_controller, this);
81 }
82 GDBWindow* window = new GDBWindow(m_gdbController);
83 window->show();
84}
85#endif
86
87void Window::keyPressEvent(QKeyEvent* event) {
88 if (event->isAutoRepeat()) {
89 QWidget::keyPressEvent(event);
90 return;
91 }
92 GBAKey key = mapKey(event->key());
93 if (key == GBA_KEY_NONE) {
94 QWidget::keyPressEvent(event);
95 return;
96 }
97 m_controller->keyPressed(key);
98 event->accept();
99}
100
101void Window::keyReleaseEvent(QKeyEvent* event) {
102 if (event->isAutoRepeat()) {
103 QWidget::keyReleaseEvent(event);
104 return;
105 }
106 GBAKey key = mapKey(event->key());
107 if (key == GBA_KEY_NONE) {
108 QWidget::keyPressEvent(event);
109 return;
110 }
111 m_controller->keyReleased(key);
112 event->accept();
113}
114
115void Window::closeEvent(QCloseEvent* event) {
116 emit shutdown();
117 QMainWindow::closeEvent(event);
118}
119
120void Window::gameStarted(GBAThread* context) {
121 emit startDrawing(m_controller->drawContext(), context);
122 foreach (QAction* action, m_gameActions) {
123 action->setDisabled(false);
124 }
125}
126
127void Window::setupAudio(GBAAudio* audio) {
128 AudioThread* thread = new AudioThread(this);
129 thread->setInput(audio);
130 thread->start(QThread::HighPriority);
131 connect(this, SIGNAL(shutdown()), thread, SLOT(shutdown()));
132}
133
134void Window::setupMenu(QMenuBar* menubar) {
135 menubar->clear();
136 QMenu* fileMenu = menubar->addMenu(tr("&File"));
137 fileMenu->addAction(tr("Load &ROM"), this, SLOT(selectROM()), QKeySequence::Open);
138
139 QMenu* emulationMenu = menubar->addMenu(tr("&Emulation"));
140 QAction* pause = new QAction(tr("&Pause"), 0);
141 pause->setChecked(false);
142 pause->setCheckable(true);
143 pause->setShortcut(tr("Ctrl+P"));
144 pause->setDisabled(true);
145 connect(pause, SIGNAL(triggered(bool)), m_controller, SLOT(setPaused(bool)));
146 m_gameActions.append(pause);
147 emulationMenu->addAction(pause);
148
149 QAction* frameAdvance = new QAction(tr("&Next frame"), 0);
150 frameAdvance->setShortcut(tr("Ctrl+N"));
151 frameAdvance->setDisabled(true);
152 connect(frameAdvance, SIGNAL(triggered()), m_controller, SLOT(frameAdvance()));
153 m_gameActions.append(frameAdvance);
154 emulationMenu->addAction(frameAdvance);
155
156 QMenu* debuggingMenu = menubar->addMenu(tr("&Debugging"));
157#ifdef USE_GDB_STUB
158 QAction* gdbWindow = new QAction(tr("Start &GDB server"), nullptr);
159 connect(gdbWindow, SIGNAL(triggered()), this, SLOT(gdbOpen()));
160 debuggingMenu->addAction(gdbWindow);
161#endif
162}