Duckstation/src/duckstation-qt/mainwindow.h

309 lines
10 KiB
C
Raw Normal View History

// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
2019-12-31 06:17:17 +00:00
#pragma once
#include "controllersettingsdialog.h"
#include "displaywidget.h"
#include "settingsdialog.h"
#include "ui_mainwindow.h"
#include "core/types.h"
#include "util/window_info.h"
2019-12-31 06:17:17 +00:00
#include <QtCore/QThread>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QStackedWidget>
2019-12-31 06:17:17 +00:00
#include <memory>
#include <optional>
2019-12-31 06:17:17 +00:00
class QLabel;
class QThread;
class QProgressBar;
2019-12-31 06:17:17 +00:00
class GameListWidget;
class EmuThread;
2020-08-06 12:08:22 +00:00
class AutoUpdaterDialog;
2020-09-18 14:28:07 +00:00
class MemoryCardEditorDialog;
2020-10-19 15:14:49 +00:00
class CheatManagerDialog;
2020-12-16 15:18:13 +00:00
class DebuggerWindow;
class MainWindow;
2019-12-31 06:17:17 +00:00
class GPUDevice;
2023-09-07 10:13:48 +00:00
namespace Achievements {
enum class LoginRequestReason;
}
namespace GameList {
struct Entry;
}
class MainWindow final : public QMainWindow
2019-12-31 06:17:17 +00:00
{
Q_OBJECT
public:
/// This class is a scoped lock on the system, which prevents it from running while
/// the object exists. Its purpose is to be used for blocking/modal popup boxes,
/// where the VM needs to exit fullscreen temporarily.
class SystemLock
{
public:
SystemLock(SystemLock&& lock);
SystemLock(const SystemLock&) = delete;
~SystemLock();
/// Returns the parent widget, which can be used for any popup dialogs.
ALWAYS_INLINE QWidget* getDialogParent() const { return m_dialog_parent; }
/// Cancels any pending unpause/fullscreen transition.
/// Call when you're going to destroy the system anyway.
void cancelResume();
private:
SystemLock(QWidget* dialog_parent, bool was_paused, bool was_fullscreen);
friend MainWindow;
QWidget* m_dialog_parent;
bool m_was_paused;
bool m_was_fullscreen;
};
public:
explicit MainWindow();
2019-12-31 06:17:17 +00:00
~MainWindow();
/// Sets application theme according to settings.
static void updateApplicationTheme();
/// Initializes the window. Call once at startup.
void initialize();
2020-08-06 12:08:22 +00:00
/// Performs update check if enabled in settings.
void startupUpdateCheck();
/// Opens memory card editor with the specified paths.
void openMemoryCardEditor(const QString& card_a_path, const QString& card_b_path);
/// Locks the system by pausing it, while a popup dialog is displayed.
SystemLock pauseAndLockSystem();
/// Accessors for the status bar widgets, updated by the emulation thread.
ALWAYS_INLINE QLabel* getStatusRendererWidget() const { return m_status_renderer_widget; }
ALWAYS_INLINE QLabel* getStatusResolutionWidget() const { return m_status_resolution_widget; }
ALWAYS_INLINE QLabel* getStatusFPSWidget() const { return m_status_fps_widget; }
ALWAYS_INLINE QLabel* getStatusVPSWidget() const { return m_status_vps_widget; }
2021-03-03 09:14:01 +00:00
2020-08-18 14:01:57 +00:00
public Q_SLOTS:
/// Updates debug menu visibility (hides if disabled).
void updateDebugMenuVisibility();
void refreshGameList(bool invalidate_cache);
void cancelGameListRefresh();
void runOnUIThread(const std::function<void()>& func);
bool requestShutdown(bool allow_confirm = true, bool allow_save_to_state = true, bool save_state = true);
void requestExit(bool allow_confirm = true);
void checkForSettingChanges();
void getWindowInfo(WindowInfo* wi);
2020-12-21 16:47:48 +00:00
void checkForUpdates(bool display_message);
void* getNativeWindowId();
2020-01-06 06:27:39 +00:00
private Q_SLOTS:
void reportError(const QString& title, const QString& message);
bool confirmMessage(const QString& title, const QString& message);
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main,
bool surfaceless, bool use_main_window_pos);
void displayResizeRequested(qint32 width, qint32 height);
void releaseRenderWindow();
void focusDisplayWidget();
2020-12-27 04:08:13 +00:00
void onMouseModeRequested(bool relative_mode, bool hide_cursor);
2021-07-09 03:05:52 +00:00
void onSettingsResetToDefault();
void onSystemStarting();
void onSystemStarted();
void onSystemDestroyed();
void onSystemPaused();
void onSystemResumed();
2022-10-05 08:29:08 +00:00
void onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
2023-09-07 10:13:48 +00:00
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
void onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points,
quint32 unread_messages);
2023-09-18 12:29:47 +00:00
void onAchievementsChallengeModeChanged(bool enabled);
void onApplicationStateChanged(Qt::ApplicationState state);
2019-12-31 06:17:17 +00:00
void onStartFileActionTriggered();
2019-12-31 06:17:17 +00:00
void onStartDiscActionTriggered();
void onStartBIOSActionTriggered();
2020-01-24 04:50:40 +00:00
void onChangeDiscFromFileActionTriggered();
void onChangeDiscFromGameListActionTriggered();
void onChangeDiscFromDeviceActionTriggered();
2021-03-27 04:14:52 +00:00
void onChangeDiscMenuAboutToShow();
void onChangeDiscMenuAboutToHide();
void onLoadStateMenuAboutToShow();
void onSaveStateMenuAboutToShow();
2020-09-09 13:44:21 +00:00
void onCheatsMenuAboutToShow();
2023-09-05 10:12:54 +00:00
void onStartFullscreenUITriggered();
void onFullscreenUIStateChange(bool running);
void onRemoveDiscActionTriggered();
2020-08-20 13:39:29 +00:00
void onViewToolbarActionToggled(bool checked);
2021-02-09 13:56:24 +00:00
void onViewLockToolbarActionToggled(bool checked);
2020-08-20 13:39:29 +00:00
void onViewStatusBarActionToggled(bool checked);
void onViewGameListActionTriggered();
2020-09-23 14:02:13 +00:00
void onViewGameGridActionTriggered();
2020-08-20 13:39:29 +00:00
void onViewSystemDisplayTriggered();
void onViewGamePropertiesActionTriggered();
2019-12-31 06:17:17 +00:00
void onGitHubRepositoryActionTriggered();
void onIssueTrackerActionTriggered();
void onDiscordServerActionTriggered();
2019-12-31 06:17:17 +00:00
void onAboutActionTriggered();
void onCheckForUpdatesActionTriggered();
2020-09-18 14:28:07 +00:00
void onToolsMemoryCardEditorTriggered();
2022-09-13 10:29:17 +00:00
void onToolsCoverDownloaderTriggered();
2020-10-19 15:14:49 +00:00
void onToolsCheatManagerTriggered();
void onToolsOpenDataDirectoryTriggered();
void onSettingsTriggeredFromToolbar();
2019-12-31 06:17:17 +00:00
void onGameListRefreshComplete();
void onGameListRefreshProgress(const QString& status, int current, int total);
void onGameListSelectionChanged();
void onGameListEntryActivated();
void onGameListEntryContextMenuRequested(const QPoint& point);
2020-08-06 12:08:22 +00:00
void onUpdateCheckComplete();
void openCPUDebugger();
void onCPUDebuggerClosed();
protected:
void showEvent(QShowEvent* event) override;
void closeEvent(QCloseEvent* event) override;
void changeEvent(QEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent* event) override;
2022-10-23 04:09:54 +00:00
#ifdef _WIN32
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
#endif
2019-12-31 06:17:17 +00:00
private:
static void setStyleFromSettings();
static void setIconThemeFromSettings();
2019-12-31 06:17:17 +00:00
void setupAdditionalUi();
void connectSignals();
2021-03-03 09:14:01 +00:00
void updateEmulationActions(bool starting, bool running, bool cheevos_challenge_mode);
void updateStatusBarWidgetVisibility();
void updateWindowTitle();
void updateWindowState(bool force_visible = false);
void setProgressBar(int current, int total);
void clearProgressBar();
QWidget* getContentParent();
QWidget* getDisplayContainer() const;
2020-09-23 14:02:13 +00:00
bool isShowingGameList() const;
bool isRenderingFullscreen() const;
bool isRenderingToMain() const;
bool shouldHideMouseCursor() const;
bool shouldHideMainWindow() const;
2019-12-31 06:17:17 +00:00
void switchToGameListView();
void switchToEmulationView();
2022-07-22 13:38:23 +00:00
void saveGeometryToConfig();
void restoreGeometryFromConfig();
void saveDisplayWindowGeometryToConfig();
void restoreDisplayWindowGeometryFromConfig();
void createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos);
void destroyDisplayWidget(bool show_game_list);
2022-08-10 06:32:55 +00:00
void updateDisplayWidgetCursor();
void updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen);
SettingsDialog* getSettingsDialog();
void doSettings(const char* category = nullptr);
ControllerSettingsDialog* getControllerSettingsDialog();
void doControllerSettings(ControllerSettingsDialog::Category category = ControllerSettingsDialog::Category::Count);
2020-02-05 08:43:25 +00:00
void updateDebugMenuCPUExecutionMode();
2020-01-24 04:49:51 +00:00
void updateDebugMenuGPURenderer();
void updateDebugMenuCropMode();
2021-08-15 04:23:14 +00:00
void updateMenuSelectedTheme();
std::string getDeviceDiscPath(const QString& title);
void setGameListEntryCoverImage(const GameList::Entry* entry);
2023-01-11 10:21:27 +00:00
void clearGameListEntryPlayTime(const GameList::Entry* entry);
void setTheme(const QString& theme);
void updateTheme();
2023-09-16 14:22:39 +00:00
void reloadThemeSpecificImages();
void recreate();
2019-12-31 06:17:17 +00:00
2022-10-23 04:09:54 +00:00
void registerForDeviceNotifications();
void unregisterForDeviceNotifications();
/// Fills menu with save state info and handlers.
void populateGameListContextMenu(const GameList::Entry* entry, QWidget* parent_window, QMenu* menu);
2022-10-05 08:29:08 +00:00
void populateLoadStateMenu(const char* game_serial, QMenu* menu);
void populateSaveStateMenu(const char* game_serial, QMenu* menu);
/// Fills menu with the current playlist entries. The disc index is marked as checked.
void populateChangeDiscSubImageMenu(QMenu* menu, QActionGroup* action_group);
/// Fills menu with the current cheat options.
void populateCheatsMenu(QMenu* menu);
std::optional<bool> promptForResumeState(const std::string& save_state_path);
void startFile(std::string path, std::optional<std::string> save_path, std::optional<bool> fast_boot);
void startFileOrChangeDisc(const QString& path);
void promptForDiscChange(const QString& path);
2019-12-31 06:17:17 +00:00
Ui::MainWindow m_ui;
GameListWidget* m_game_list_widget = nullptr;
DisplayWidget* m_display_widget = nullptr;
DisplayContainer* m_display_container = nullptr;
2019-12-31 06:17:17 +00:00
QProgressBar* m_status_progress_widget = nullptr;
QLabel* m_status_renderer_widget = nullptr;
QLabel* m_status_fps_widget = nullptr;
QLabel* m_status_vps_widget = nullptr;
QLabel* m_status_resolution_widget = nullptr;
QMenu* m_settings_toolbar_menu = nullptr;
2019-12-31 06:17:17 +00:00
SettingsDialog* m_settings_dialog = nullptr;
ControllerSettingsDialog* m_controller_settings_dialog = nullptr;
2020-08-06 12:08:22 +00:00
AutoUpdaterDialog* m_auto_updater_dialog = nullptr;
2020-09-18 14:28:07 +00:00
MemoryCardEditorDialog* m_memory_card_editor_dialog = nullptr;
2020-10-19 15:14:49 +00:00
CheatManagerDialog* m_cheat_manager_dialog = nullptr;
2020-12-16 15:18:13 +00:00
DebuggerWindow* m_debugger_window = nullptr;
2019-12-31 06:17:17 +00:00
2023-08-23 08:12:10 +00:00
QString m_current_game_path;
QString m_current_game_title;
QString m_current_game_serial;
bool m_was_paused_by_focus_loss = false;
bool m_open_debugger_on_start = false;
2020-12-27 04:08:13 +00:00
bool m_relative_mouse_mode = false;
2022-08-10 06:32:55 +00:00
bool m_hide_mouse_cursor = false;
2020-12-17 17:32:29 +00:00
bool m_display_created = false;
bool m_save_states_invalidated = false;
bool m_was_paused_on_surface_loss = false;
bool m_was_disc_change_request = false;
bool m_is_closing = false;
2022-10-23 04:09:54 +00:00
#ifdef _WIN32
void* m_device_notification_handle = nullptr;
#endif
2019-12-31 06:17:17 +00:00
};
extern MainWindow* g_main_window;