CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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