Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Qt/mainwindow.h
5651 views
1
#pragma once
2
3
#include <queue>
4
#include <mutex>
5
#include <string>
6
7
#include <QtCore>
8
#include <QMenuBar>
9
#include <QMainWindow>
10
#include <QActionGroup>
11
12
#include "ppsspp_config.h"
13
#include "Common/System/System.h"
14
#include "Common/System/NativeApp.h"
15
#include "Common/System/Display.h"
16
#if PPSSPP_PLATFORM(WINDOWS)
17
#include "Common/Log/ConsoleListener.h"
18
#endif
19
#include "Core/Core.h"
20
#include "Core/Config.h"
21
#include "Core/System.h"
22
#include "Qt/QtMain.h"
23
24
extern bool g_TakeScreenshot;
25
26
class MenuAction;
27
class MenuTree;
28
29
enum {
30
FB_NON_BUFFERED_MODE = 0,
31
FB_BUFFERED_MODE = 1,
32
};
33
34
// hacky, should probably use qt signals or something, but whatever..
35
enum class MainWindowMsg {
36
BOOT_DONE,
37
WINDOW_TITLE_CHANGED,
38
};
39
40
class MainWindow : public QMainWindow
41
{
42
Q_OBJECT
43
44
public:
45
explicit MainWindow(QWidget *parent = nullptr, bool fullscreen = false);
46
~MainWindow() { };
47
48
CoreState GetNextState() { return nextState; }
49
50
void updateMenuGroupInt(QActionGroup *group, int value);
51
52
void updateMenus();
53
54
void Notify(MainWindowMsg msg) {
55
std::unique_lock<std::mutex> lock(msgMutex_);
56
msgQueue_.push(msg);
57
}
58
59
void SetWindowTitleAsync(std::string title) {
60
std::unique_lock<std::mutex> lock(titleMutex_);
61
newWindowTitle_ = title;
62
Notify(MainWindowMsg::WINDOW_TITLE_CHANGED);
63
}
64
65
protected:
66
void changeEvent(QEvent *e)
67
{
68
QMainWindow::changeEvent(e);
69
// Does not work on Linux for Qt5.2 or Qt5.3 (Qt bug)
70
if(e->type() == QEvent::WindowStateChange)
71
Native_NotifyWindowHidden(isMinimized());
72
}
73
74
void closeEvent(QCloseEvent *) { exitAct(); }
75
76
signals:
77
void retranslate();
78
void updateMenu();
79
80
public slots:
81
void newFrame();
82
83
private slots:
84
// File
85
void loadAct();
86
void closeAct();
87
void openmsAct();
88
void saveStateGroup_triggered(QAction *action) { g_Config.iCurrentStateSlot = action->data().toInt(); }
89
void qlstateAct();
90
void qsstateAct();
91
void lstateAct();
92
void sstateAct();
93
void recordDisplayAct();
94
void useLosslessVideoCodecAct();
95
void useOutputBufferAct();
96
void recordAudioAct();
97
void exitAct();
98
99
// Emulation
100
void runAct();
101
void pauseAct();
102
void stopAct();
103
void resetAct();
104
void switchUMDAct();
105
void displayRotationGroup_triggered(QAction *action) {
106
DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
107
config.iInternalScreenRotation = action->data().toInt();
108
}
109
110
// Debug
111
void breakonloadAct();
112
void ignoreIllegalAct() { g_Config.bIgnoreBadMemAccess = !g_Config.bIgnoreBadMemAccess; }
113
void lmapAct();
114
void smapAct();
115
void lsymAct();
116
void ssymAct();
117
void resetTableAct();
118
void dumpNextAct();
119
void takeScreen() { g_TakeScreenshot = true; }
120
void consoleAct();
121
122
// Game settings
123
void languageAct() { System_PostUIMessage(UIMessage::SHOW_LANGUAGE_SCREEN); }
124
void controlMappingAct() { System_PostUIMessage(UIMessage::SHOW_CONTROL_MAPPING); }
125
void displayLayoutEditorAct() { System_PostUIMessage(UIMessage::SHOW_DISPLAY_LAYOUT_EDITOR); }
126
void moreSettingsAct() { System_PostUIMessage(UIMessage::SHOW_SETTINGS); }
127
128
void bufferRenderAct() {
129
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED);
130
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
131
}
132
void linearAct() { g_Config.iTexFiltering = (g_Config.iTexFiltering != 0) ? 0 : 3; }
133
134
void renderingResolutionGroup_triggered(QAction *action) {
135
g_Config.iInternalResolution = action->data().toInt();
136
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED);
137
}
138
void windowGroup_triggered(QAction *action) { SetWindowScale(action->data().toInt()); }
139
140
void autoframeskipAct() {
141
g_Config.bAutoFrameSkip = !g_Config.bAutoFrameSkip;
142
if (g_Config.bSkipBufferEffects) {
143
g_Config.bSkipBufferEffects = false;
144
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
145
}
146
}
147
void frameSkippingGroup_triggered(QAction *action) { g_Config.iFrameSkip = action->data().toInt(); }
148
void textureFilteringGroup_triggered(QAction *action) { g_Config.iTexFiltering = action->data().toInt(); }
149
void screenScalingFilterGroup_triggered(QAction *action) {
150
DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
151
config.iDisplayFilter = action->data().toInt();
152
}
153
void textureScalingLevelGroup_triggered(QAction *action) {
154
g_Config.iTexScalingLevel = action->data().toInt();
155
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
156
}
157
void textureScalingTypeGroup_triggered(QAction *action) {
158
g_Config.iTexScalingType = action->data().toInt();
159
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
160
}
161
void deposterizeAct() {
162
g_Config.bTexDeposterize = !g_Config.bTexDeposterize;
163
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
164
}
165
void transformAct() {
166
g_Config.bHardwareTransform = !g_Config.bHardwareTransform;
167
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
168
}
169
void frameskipAct() { g_Config.iFrameSkip = !g_Config.iFrameSkip; }
170
171
// Sound
172
void audioAct() {
173
g_Config.bEnableSound = !g_Config.bEnableSound;
174
}
175
176
// Cheats
177
void cheatsAct() { g_Config.bEnableCheats = !g_Config.bEnableCheats; }
178
179
// Chat
180
void chatAct() {
181
if (GetUIState() == UISTATE_INGAME) {
182
System_PostUIMessage(UIMessage::SHOW_CHAT_SCREEN);
183
}
184
}
185
186
void fullscrAct();
187
void raiseTopMost();
188
189
// Help
190
void websiteAct();
191
void forumAct();
192
void goldAct();
193
void gitAct();
194
void discordAct();
195
void aboutAct();
196
197
// Others
198
void langChanged(QAction *action) { loadLanguage(action->data().toString(), true); }
199
200
private:
201
void bootDone();
202
void SetWindowScale(int zoom);
203
void SetGameTitle(QString text);
204
void SetFullScreen(bool fullscreen);
205
void loadLanguage(const QString &language, bool retranslate);
206
void createMenus();
207
208
QTranslator translator;
209
QString currentLanguage;
210
211
CoreState nextState;
212
GlobalUIState lastUIState;
213
214
QActionGroup *windowGroup,
215
*textureScalingLevelGroup, *textureScalingTypeGroup,
216
*screenScalingFilterGroup, *textureFilteringGroup,
217
*frameSkippingGroup, *renderingResolutionGroup,
218
*displayRotationGroup, *saveStateGroup;
219
220
std::queue<MainWindowMsg> msgQueue_;
221
std::mutex msgMutex_;
222
223
std::string newWindowTitle_;
224
std::mutex titleMutex_;
225
};
226
227
class MenuAction : public QAction
228
{
229
Q_OBJECT
230
231
public:
232
// Add to QMenu
233
MenuAction(QWidget* parent, const char *callback, const char *text, QKeySequence key = 0) :
234
QAction(parent), _text(text)
235
{
236
if (key != (QKeySequence)0) {
237
this->setShortcut(key);
238
parent->addAction(this); // So we don't lose the shortcut when menubar is hidden
239
}
240
connect(this, SIGNAL(triggered()), parent, callback);
241
connect(parent, SIGNAL(retranslate()), this, SLOT(retranslate()));
242
connect(parent, SIGNAL(updateMenu()), this, SLOT(update()));
243
}
244
// Add to QActionGroup
245
MenuAction(QWidget* parent, QActionGroup* group, QVariant data, QString text, QKeySequence key = 0) :
246
QAction(parent)
247
{
248
this->setCheckable(true);
249
this->setData(data);
250
this->setText(text); // Not translatable, yet
251
if (key != (QKeySequence)0) {
252
this->setShortcut(key);
253
parent->addAction(this); // So we don't lose the shortcut when menubar is hidden
254
}
255
group->addAction(this);
256
}
257
// Event which causes it to be checked
258
void addEventChecked(bool* event) {
259
this->setCheckable(true);
260
_eventCheck = event;
261
}
262
// TODO: Possibly handle compares
263
void addEventChecked(int* event) {
264
this->setCheckable(true);
265
_eventCheck = (bool*)event;
266
}
267
// Event which causes it to be unchecked
268
void addEventUnchecked(bool* event) {
269
this->setCheckable(true);
270
_eventUncheck = event;
271
}
272
// UI State which causes it to be enabled
273
void addEnableState(int state) {
274
_enabledFunc = nullptr;
275
_stateEnable = state;
276
_stateDisable = -1;
277
}
278
void addDisableState(int state) {
279
_enabledFunc = nullptr;
280
_stateEnable = -1;
281
_stateDisable = state;
282
}
283
void SetEnabledFunc(std::function<bool()> func) {
284
_enabledFunc = func;
285
_stateEnable = -1;
286
_stateDisable = -1;
287
}
288
public slots:
289
void retranslate() {
290
setText(qApp->translate("MainWindow", _text));
291
}
292
void update() {
293
if (_eventCheck)
294
setChecked(*_eventCheck);
295
if (_eventUncheck)
296
setChecked(!*_eventUncheck);
297
if (_stateEnable >= 0)
298
setEnabled(GetUIState() == _stateEnable);
299
if (_stateDisable >= 0)
300
setEnabled(GetUIState() != _stateDisable);
301
if (_enabledFunc)
302
setEnabled(_enabledFunc());
303
}
304
private:
305
const char *_text;
306
bool *_eventCheck = nullptr;
307
bool *_eventUncheck = nullptr;
308
int _stateEnable = -1;
309
int _stateDisable = -1;
310
std::function<bool()> _enabledFunc;
311
};
312
313
class MenuActionGroup : public QActionGroup
314
{
315
Q_OBJECT
316
public:
317
MenuActionGroup(QWidget* parent, QMenu* menu, const char* callback, QStringList nameList,
318
QList<int> valueList, QList<int> keyList = QList<int>()) :
319
QActionGroup(parent)
320
{
321
QListIterator<int> i(valueList);
322
QListIterator<int> k(keyList);
323
foreach(QString name, nameList) {
324
new MenuAction(parent, this, i.next(), name, keyList.size() ? k.next() : 0);
325
}
326
connect(this, SIGNAL(triggered(QAction *)), parent, callback);
327
menu->addActions(this->actions());
328
}
329
};
330
331
class MenuTree : public QMenu
332
{
333
Q_OBJECT
334
public:
335
MenuTree(QWidget* parent, QMenuBar* menu, const char *text) :
336
QMenu(parent), _text(text)
337
{
338
menu->addMenu(this);
339
connect(parent, SIGNAL(retranslate()), this, SLOT(retranslate()));
340
}
341
MenuTree(QWidget* parent, QMenu* menu, const char *text) :
342
QMenu(parent), _text(text)
343
{
344
menu->addMenu(this);
345
connect(parent, SIGNAL(retranslate()), this, SLOT(retranslate()));
346
}
347
MenuAction* add(MenuAction* action)
348
{
349
addAction(action);
350
return action;
351
}
352
public slots:
353
void retranslate() {
354
setTitle(qApp->translate("MainWindow", _text));
355
}
356
private:
357
const char *_text;
358
};
359
360