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 "GameController.h"
9#include "GDBWindow.h"
10#include "GDBController.h"
11
12using namespace QGBA;
13
14Window::Window(QWidget* parent)
15 : QMainWindow(parent)
16#ifdef USE_GDB_STUB
17 , m_gdbController(nullptr)
18#endif
19{
20 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
21 setMinimumSize(240, 160);
22
23 m_controller = new GameController(this);
24 m_display = new Display();
25 setCentralWidget(m_display);
26 connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*)));
27 connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing()));
28 connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped()));
29 connect(this, SIGNAL(startDrawing(const uint32_t*, GBAThread*)), m_display, SLOT(startDrawing(const uint32_t*, GBAThread*)), Qt::QueuedConnection);
30 connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing()));
31 connect(this, SIGNAL(audioBufferSamplesChanged(int)), m_controller, SLOT(setAudioBufferSamples(int)));
32
33 setupMenu(menuBar());
34}
35
36GBAKey Window::mapKey(int qtKey) {
37 switch (qtKey) {
38 case Qt::Key_Z:
39 return GBA_KEY_A;
40 break;
41 case Qt::Key_X:
42 return GBA_KEY_B;
43 break;
44 case Qt::Key_A:
45 return GBA_KEY_L;
46 break;
47 case Qt::Key_S:
48 return GBA_KEY_R;
49 break;
50 case Qt::Key_Return:
51 return GBA_KEY_START;
52 break;
53 case Qt::Key_Backspace:
54 return GBA_KEY_SELECT;
55 break;
56 case Qt::Key_Up:
57 return GBA_KEY_UP;
58 break;
59 case Qt::Key_Down:
60 return GBA_KEY_DOWN;
61 break;
62 case Qt::Key_Left:
63 return GBA_KEY_LEFT;
64 break;
65 case Qt::Key_Right:
66 return GBA_KEY_RIGHT;
67 break;
68 default:
69 return GBA_KEY_NONE;
70 }
71}
72
73void Window::selectROM() {
74 QString filename = QFileDialog::getOpenFileName(this, tr("Select ROM"));
75 if (!filename.isEmpty()) {
76 m_controller->loadGame(filename);
77 }
78}
79
80#ifdef USE_GDB_STUB
81void Window::gdbOpen() {
82 if (!m_gdbController) {
83 m_gdbController = new GDBController(m_controller, this);
84 }
85 GDBWindow* window = new GDBWindow(m_gdbController);
86 window->show();
87}
88#endif
89
90void Window::keyPressEvent(QKeyEvent* event) {
91 if (event->isAutoRepeat()) {
92 QWidget::keyPressEvent(event);
93 return;
94 }
95 GBAKey key = mapKey(event->key());
96 if (key == GBA_KEY_NONE) {
97 QWidget::keyPressEvent(event);
98 return;
99 }
100 m_controller->keyPressed(key);
101 event->accept();
102}
103
104void Window::keyReleaseEvent(QKeyEvent* event) {
105 if (event->isAutoRepeat()) {
106 QWidget::keyReleaseEvent(event);
107 return;
108 }
109 GBAKey key = mapKey(event->key());
110 if (key == GBA_KEY_NONE) {
111 QWidget::keyPressEvent(event);
112 return;
113 }
114 m_controller->keyReleased(key);
115 event->accept();
116}
117
118void Window::closeEvent(QCloseEvent* event) {
119 emit shutdown();
120 QMainWindow::closeEvent(event);
121}
122
123void Window::gameStarted(GBAThread* context) {
124 emit startDrawing(m_controller->drawContext(), context);
125 foreach (QAction* action, m_gameActions) {
126 action->setDisabled(false);
127 }
128}
129
130void Window::gameStopped() {
131 foreach (QAction* action, m_gameActions) {
132 action->setDisabled(true);
133 }
134}
135
136void Window::setBuffers512() {
137 emit audioBufferSamplesChanged(512);
138}
139
140void Window::setBuffers1024() {
141 emit audioBufferSamplesChanged(1024);
142}
143
144void Window::setBuffers2048() {
145 emit audioBufferSamplesChanged(2048);
146}
147
148void Window::setBuffers4096() {
149 emit audioBufferSamplesChanged(4096);
150}
151
152void Window::setupMenu(QMenuBar* menubar) {
153 menubar->clear();
154 QMenu* fileMenu = menubar->addMenu(tr("&File"));
155 fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open);
156
157 QMenu* emulationMenu = menubar->addMenu(tr("&Emulation"));
158 QAction* reset = new QAction(tr("&Reset"), nullptr);
159 reset->setShortcut(tr("Ctrl+R"));
160 connect(reset, SIGNAL(triggered()), m_controller, SLOT(reset()));
161 m_gameActions.append(reset);
162 emulationMenu->addAction(reset);
163 emulationMenu->addAction(tr("Sh&utdown"), m_controller, SLOT(closeGame()));
164 emulationMenu->addSeparator();
165
166 QAction* pause = new QAction(tr("&Pause"), nullptr);
167 pause->setChecked(false);
168 pause->setCheckable(true);
169 pause->setShortcut(tr("Ctrl+P"));
170 connect(pause, SIGNAL(triggered(bool)), m_controller, SLOT(setPaused(bool)));
171 m_gameActions.append(pause);
172 emulationMenu->addAction(pause);
173
174 QAction* frameAdvance = new QAction(tr("&Next frame"), nullptr);
175 frameAdvance->setShortcut(tr("Ctrl+N"));
176 connect(frameAdvance, SIGNAL(triggered()), m_controller, SLOT(frameAdvance()));
177 m_gameActions.append(frameAdvance);
178 emulationMenu->addAction(frameAdvance);
179
180 QMenu* soundMenu = menubar->addMenu(tr("&Sound"));
181 QMenu* buffersMenu = soundMenu->addMenu(tr("Buffer &size"));
182 buffersMenu->addAction(tr("512"), this, SLOT(setBuffers512()));
183 buffersMenu->addAction(tr("1024"), this, SLOT(setBuffers1024()));
184 buffersMenu->addAction(tr("2048"), this, SLOT(setBuffers2048()));
185 buffersMenu->addAction(tr("4096"), this, SLOT(setBuffers4096()));
186
187 QMenu* debuggingMenu = menubar->addMenu(tr("&Debugging"));
188#ifdef USE_GDB_STUB
189 QAction* gdbWindow = new QAction(tr("Start &GDB server..."), nullptr);
190 connect(gdbWindow, SIGNAL(triggered()), this, SLOT(gdbOpen()));
191 debuggingMenu->addAction(gdbWindow);
192#endif
193
194 foreach (QAction* action, m_gameActions) {
195 action->setDisabled(true);
196 }
197}