summaryrefslogtreecommitdiff
path: root/src/citra_qt
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt')
-rw-r--r--src/citra_qt/bootmanager.h4
-rw-r--r--src/citra_qt/citra-qt.rc2
-rw-r--r--src/citra_qt/debugger/callstack.h4
-rw-r--r--src/citra_qt/debugger/disassembler.h2
-rw-r--r--src/citra_qt/debugger/graphics.h2
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.h4
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.h4
-rw-r--r--src/citra_qt/debugger/graphics_surface.h7
-rw-r--r--src/citra_qt/debugger/graphics_tracing.h4
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.h2
-rw-r--r--src/citra_qt/debugger/profiler.h6
-rw-r--r--src/citra_qt/debugger/ramview.h4
-rw-r--r--src/citra_qt/debugger/registers.h4
-rw-r--r--src/citra_qt/debugger/wait_tree.cpp4
-rw-r--r--src/citra_qt/debugger/wait_tree.h26
-rw-r--r--src/citra_qt/game_list.cpp46
-rw-r--r--src/citra_qt/game_list.h16
-rw-r--r--src/citra_qt/game_list_p.h5
-rw-r--r--src/citra_qt/hotkeys.h2
-rw-r--r--src/citra_qt/main.cpp19
-rw-r--r--src/citra_qt/main.h1
-rw-r--r--src/citra_qt/util/spinbox.h2
22 files changed, 114 insertions, 56 deletions
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index 67228b94f..af52f369b 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#pragma once
+
#include <atomic>
#include <condition_variable>
#include <mutex>
@@ -21,7 +23,7 @@ class EmuThread : public QThread {
Q_OBJECT
public:
- EmuThread(GRenderWindow* render_window);
+ explicit EmuThread(GRenderWindow* render_window);
/**
* Start emulation (on new thread)
diff --git a/src/citra_qt/citra-qt.rc b/src/citra_qt/citra-qt.rc
index 3c7239853..fea603004 100644
--- a/src/citra_qt/citra-qt.rc
+++ b/src/citra_qt/citra-qt.rc
@@ -5,5 +5,5 @@
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
-IDI_ICON1 ICON "..\\..\\dist\\citra.ico"
+CITRA_ICON ICON "../../dist/citra.ico"
diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h
index 765757986..f04ab9c7e 100644
--- a/src/citra_qt/debugger/callstack.h
+++ b/src/citra_qt/debugger/callstack.h
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#pragma once
+
#include <QDockWidget>
#include "ui_callstack.h"
@@ -11,7 +13,7 @@ class CallstackWidget : public QDockWidget {
Q_OBJECT
public:
- CallstackWidget(QWidget* parent = nullptr);
+ explicit CallstackWidget(QWidget* parent = nullptr);
public slots:
void OnDebugModeEntered();
diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h
index 2ca6c2bd4..895f6ac89 100644
--- a/src/citra_qt/debugger/disassembler.h
+++ b/src/citra_qt/debugger/disassembler.h
@@ -17,7 +17,7 @@ class DisassemblerModel : public QAbstractListModel {
Q_OBJECT
public:
- DisassemblerModel(QObject* parent);
+ explicit DisassemblerModel(QObject* parent);
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
diff --git a/src/citra_qt/debugger/graphics.h b/src/citra_qt/debugger/graphics.h
index bedf3e596..8837fb792 100644
--- a/src/citra_qt/debugger/graphics.h
+++ b/src/citra_qt/debugger/graphics.h
@@ -13,7 +13,7 @@ class GPUCommandStreamItemModel : public QAbstractListModel,
Q_OBJECT
public:
- GPUCommandStreamItemModel(QObject* parent);
+ explicit GPUCommandStreamItemModel(QObject* parent);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
diff --git a/src/citra_qt/debugger/graphics_breakpoints.h b/src/citra_qt/debugger/graphics_breakpoints.h
index 5fc40c916..bec72a2db 100644
--- a/src/citra_qt/debugger/graphics_breakpoints.h
+++ b/src/citra_qt/debugger/graphics_breakpoints.h
@@ -20,8 +20,8 @@ class GraphicsBreakPointsWidget : public QDockWidget, Pica::DebugContext::BreakP
using Event = Pica::DebugContext::Event;
public:
- GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context,
- QWidget* parent = nullptr);
+ explicit GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context,
+ QWidget* parent = nullptr);
void OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) override;
void OnPicaResume() override;
diff --git a/src/citra_qt/debugger/graphics_cmdlists.h b/src/citra_qt/debugger/graphics_cmdlists.h
index fa2b9122b..8f40b94c5 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.h
+++ b/src/citra_qt/debugger/graphics_cmdlists.h
@@ -20,7 +20,7 @@ public:
CommandIdRole = Qt::UserRole,
};
- GPUCommandListModel(QObject* parent);
+ explicit GPUCommandListModel(QObject* parent);
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
@@ -39,7 +39,7 @@ class GPUCommandListWidget : public QDockWidget {
Q_OBJECT
public:
- GPUCommandListWidget(QWidget* parent = nullptr);
+ explicit GPUCommandListWidget(QWidget* parent = nullptr);
public slots:
void OnToggleTracing();
diff --git a/src/citra_qt/debugger/graphics_surface.h b/src/citra_qt/debugger/graphics_surface.h
index 21e6b5b8b..19ffb55fb 100644
--- a/src/citra_qt/debugger/graphics_surface.h
+++ b/src/citra_qt/debugger/graphics_surface.h
@@ -18,7 +18,8 @@ class SurfacePicture : public QLabel {
Q_OBJECT
public:
- SurfacePicture(QWidget* parent = 0, GraphicsSurfaceWidget* surface_widget = nullptr);
+ explicit SurfacePicture(QWidget* parent = nullptr,
+ GraphicsSurfaceWidget* surface_widget = nullptr);
~SurfacePicture();
protected slots:
@@ -71,8 +72,8 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock {
static unsigned int NibblesPerPixel(Format format);
public:
- GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
- QWidget* parent = nullptr);
+ explicit GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
+ QWidget* parent = nullptr);
void Pick(int x, int y);
public slots:
diff --git a/src/citra_qt/debugger/graphics_tracing.h b/src/citra_qt/debugger/graphics_tracing.h
index e04a3dac3..20acc91e7 100644
--- a/src/citra_qt/debugger/graphics_tracing.h
+++ b/src/citra_qt/debugger/graphics_tracing.h
@@ -12,8 +12,8 @@ class GraphicsTracingWidget : public BreakPointObserverDock {
Q_OBJECT
public:
- GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context,
- QWidget* parent = nullptr);
+ explicit GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context,
+ QWidget* parent = nullptr);
private slots:
void StartRecording();
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.h b/src/citra_qt/debugger/graphics_vertex_shader.h
index ec42f24bb..6e62fbb9b 100644
--- a/src/citra_qt/debugger/graphics_vertex_shader.h
+++ b/src/citra_qt/debugger/graphics_vertex_shader.h
@@ -19,7 +19,7 @@ class GraphicsVertexShaderModel : public QAbstractTableModel {
Q_OBJECT
public:
- GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent);
+ explicit GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent);
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h
index d8c6487aa..c8912fd5a 100644
--- a/src/citra_qt/debugger/profiler.h
+++ b/src/citra_qt/debugger/profiler.h
@@ -15,7 +15,7 @@ class ProfilerModel : public QAbstractItemModel {
Q_OBJECT
public:
- ProfilerModel(QObject* parent);
+ explicit ProfilerModel(QObject* parent);
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
@@ -37,7 +37,7 @@ class ProfilerWidget : public QDockWidget {
Q_OBJECT
public:
- ProfilerWidget(QWidget* parent = nullptr);
+ explicit ProfilerWidget(QWidget* parent = nullptr);
private slots:
void setProfilingInfoUpdateEnabled(bool enable);
@@ -53,7 +53,7 @@ class MicroProfileDialog : public QWidget {
Q_OBJECT
public:
- MicroProfileDialog(QWidget* parent = nullptr);
+ explicit MicroProfileDialog(QWidget* parent = nullptr);
/// Returns a QAction that can be used to toggle visibility of this dialog.
QAction* toggleViewAction();
diff --git a/src/citra_qt/debugger/ramview.h b/src/citra_qt/debugger/ramview.h
index 8043c59e8..d01cea93b 100644
--- a/src/citra_qt/debugger/ramview.h
+++ b/src/citra_qt/debugger/ramview.h
@@ -2,13 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#pragma once
+
#include "qhexedit.h"
class GRamView : public QHexEdit {
Q_OBJECT
public:
- GRamView(QWidget* parent = nullptr);
+ explicit GRamView(QWidget* parent = nullptr);
public slots:
void OnCPUStepped();
diff --git a/src/citra_qt/debugger/registers.h b/src/citra_qt/debugger/registers.h
index 54c9a8155..55bda5b59 100644
--- a/src/citra_qt/debugger/registers.h
+++ b/src/citra_qt/debugger/registers.h
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#pragma once
+
#include <QDockWidget>
#include "ui_registers.h"
@@ -13,7 +15,7 @@ class RegistersWidget : public QDockWidget {
Q_OBJECT
public:
- RegistersWidget(QWidget* parent = nullptr);
+ explicit RegistersWidget(QWidget* parent = nullptr);
public slots:
void OnDebugModeEntered();
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp
index be5a51e52..5a308bf7f 100644
--- a/src/citra_qt/debugger/wait_tree.cpp
+++ b/src/citra_qt/debugger/wait_tree.cpp
@@ -8,7 +8,6 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/semaphore.h"
-#include "core/hle/kernel/session.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
@@ -230,7 +229,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes));
}
if (thread.status == THREADSTATUS_WAIT_SYNCH) {
- list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, thread.wait_all));
+ list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
+ thread.IsSleepingOnWaitAll()));
}
return list;
diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h
index 5d1d964d1..ee9708fc1 100644
--- a/src/citra_qt/debugger/wait_tree.h
+++ b/src/citra_qt/debugger/wait_tree.h
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#pragma once
+
#include <boost/container/flat_set.hpp>
#include <QAbstractItemModel>
@@ -49,7 +51,7 @@ private:
class WaitTreeText : public WaitTreeItem {
Q_OBJECT
public:
- WaitTreeText(const QString& text);
+ explicit WaitTreeText(const QString& text);
QString GetText() const override;
private:
@@ -65,7 +67,7 @@ public:
class WaitTreeWaitObject : public WaitTreeExpandableItem {
Q_OBJECT
public:
- WaitTreeWaitObject(const Kernel::WaitObject& object);
+ explicit WaitTreeWaitObject(const Kernel::WaitObject& object);
static std::unique_ptr<WaitTreeWaitObject> make(const Kernel::WaitObject& object);
QString GetText() const override;
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
@@ -92,7 +94,7 @@ private:
class WaitTreeThread : public WaitTreeWaitObject {
Q_OBJECT
public:
- WaitTreeThread(const Kernel::Thread& thread);
+ explicit WaitTreeThread(const Kernel::Thread& thread);
QString GetText() const override;
QColor GetColor() const override;
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
@@ -101,35 +103,37 @@ public:
class WaitTreeEvent : public WaitTreeWaitObject {
Q_OBJECT
public:
- WaitTreeEvent(const Kernel::Event& object);
+ explicit WaitTreeEvent(const Kernel::Event& object);
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
};
class WaitTreeMutex : public WaitTreeWaitObject {
Q_OBJECT
public:
- WaitTreeMutex(const Kernel::Mutex& object);
+ explicit WaitTreeMutex(const Kernel::Mutex& object);
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
};
class WaitTreeSemaphore : public WaitTreeWaitObject {
Q_OBJECT
public:
- WaitTreeSemaphore(const Kernel::Semaphore& object);
+ explicit WaitTreeSemaphore(const Kernel::Semaphore& object);
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
};
class WaitTreeTimer : public WaitTreeWaitObject {
Q_OBJECT
public:
- WaitTreeTimer(const Kernel::Timer& object);
+ explicit WaitTreeTimer(const Kernel::Timer& object);
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
};
class WaitTreeMutexList : public WaitTreeExpandableItem {
Q_OBJECT
public:
- WaitTreeMutexList(const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list);
+ explicit WaitTreeMutexList(
+ const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list);
+
QString GetText() const override;
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
@@ -140,7 +144,7 @@ private:
class WaitTreeThreadList : public WaitTreeExpandableItem {
Q_OBJECT
public:
- WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list);
+ explicit WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list);
QString GetText() const override;
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
@@ -152,7 +156,7 @@ class WaitTreeModel : public QAbstractItemModel {
Q_OBJECT
public:
- WaitTreeModel(QObject* parent = nullptr);
+ explicit WaitTreeModel(QObject* parent = nullptr);
QVariant data(const QModelIndex& index, int role) const override;
QModelIndex index(int row, int column, const QModelIndex& parent) const override;
@@ -171,7 +175,7 @@ class WaitTreeWidget : public QDockWidget {
Q_OBJECT
public:
- WaitTreeWidget(QWidget* parent = nullptr);
+ explicit WaitTreeWidget(QWidget* parent = nullptr);
public slots:
void OnDebugModeEntered();
diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp
index 07bc35308..09469f3c5 100644
--- a/src/citra_qt/game_list.cpp
+++ b/src/citra_qt/game_list.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <QHeaderView>
+#include <QMenu>
#include <QThreadPool>
#include <QVBoxLayout>
#include "common/common_paths.h"
@@ -13,7 +14,7 @@
#include "game_list_p.h"
#include "ui_settings.h"
-GameList::GameList(QWidget* parent) {
+GameList::GameList(QWidget* parent) : QWidget{parent} {
QVBoxLayout* layout = new QVBoxLayout;
tree_view = new QTreeView;
@@ -28,18 +29,18 @@ GameList::GameList(QWidget* parent) {
tree_view->setSortingEnabled(true);
tree_view->setEditTriggers(QHeaderView::NoEditTriggers);
tree_view->setUniformRowHeights(true);
+ tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
item_model->insertColumns(0, COLUMN_COUNT);
item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name");
item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type");
item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size");
- connect(tree_view, SIGNAL(activated(const QModelIndex&)), this,
- SLOT(ValidateEntry(const QModelIndex&)));
+ connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);
+ connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
// We must register all custom types with the Qt Automoc system so that we are able to use it
- // with
- // signals/slots. In this case, QList falls under the umbrells of custom types.
+ // with signals/slots. In this case, QList falls under the umbrells of custom types.
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
layout->addWidget(tree_view);
@@ -50,7 +51,7 @@ GameList::~GameList() {
emit ShouldCancelWorker();
}
-void GameList::AddEntry(QList<QStandardItem*> entry_items) {
+void GameList::AddEntry(const QList<QStandardItem*>& entry_items) {
item_model->invisibleRootItem()->appendRow(entry_items);
}
@@ -72,6 +73,23 @@ void GameList::DonePopulating() {
tree_view->setEnabled(true);
}
+void GameList::PopupContextMenu(const QPoint& menu_location) {
+ QModelIndex item = tree_view->indexAt(menu_location);
+ if (!item.isValid())
+ return;
+
+ int row = item_model->itemFromIndex(item)->row();
+ QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME);
+ u64 program_id = child_file->data(GameListItemPath::ProgramIdRole).toULongLong();
+
+ QMenu context_menu;
+ QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
+ open_save_location->setEnabled(program_id != 0);
+ connect(open_save_location, &QAction::triggered,
+ [&]() { emit OpenSaveFolderRequested(program_id); });
+ context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location));
+}
+
void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
if (!FileUtil::Exists(dir_path.toStdString()) ||
!FileUtil::IsDirectory(dir_path.toStdString())) {
@@ -86,12 +104,13 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
emit ShouldCancelWorker();
GameListWorker* worker = new GameListWorker(dir_path, deep_scan);
- connect(worker, SIGNAL(EntryReady(QList<QStandardItem*>)), this,
- SLOT(AddEntry(QList<QStandardItem*>)), Qt::QueuedConnection);
- connect(worker, SIGNAL(Finished()), this, SLOT(DonePopulating()), Qt::QueuedConnection);
+ connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection);
+ connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating,
+ Qt::QueuedConnection);
// Use DirectConnection here because worker->Cancel() is thread-safe and we want it to cancel
// without delay.
- connect(this, SIGNAL(ShouldCancelWorker()), worker, SLOT(Cancel()), Qt::DirectConnection);
+ connect(this, &GameList::ShouldCancelWorker, worker, &GameListWorker::Cancel,
+ Qt::DirectConnection);
QThreadPool::globalInstance()->start(worker);
current_worker = std::move(worker);
@@ -128,8 +147,11 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
std::vector<u8> smdh;
loader->ReadIcon(smdh);
+ u64 program_id = 0;
+ loader->ReadProgramId(program_id);
+
emit EntryReady({
- new GameListItemPath(QString::fromStdString(physical_name), smdh),
+ new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id),
new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(FileUtil::GetSize(physical_name)),
@@ -151,6 +173,6 @@ void GameListWorker::run() {
}
void GameListWorker::Cancel() {
- disconnect(this, 0, 0, 0);
+ disconnect(this, nullptr, nullptr, nullptr);
stop_processing = true;
}
diff --git a/src/citra_qt/game_list.h b/src/citra_qt/game_list.h
index a22e9bc60..1abf10051 100644
--- a/src/citra_qt/game_list.h
+++ b/src/citra_qt/game_list.h
@@ -25,7 +25,7 @@ public:
COLUMN_COUNT, // Number of columns
};
- GameList(QWidget* parent = nullptr);
+ explicit GameList(QWidget* parent = nullptr);
~GameList() override;
void PopulateAsync(const QString& dir_path, bool deep_scan);
@@ -33,18 +33,18 @@ public:
void SaveInterfaceLayout();
void LoadInterfaceLayout();
-public slots:
- void AddEntry(QList<QStandardItem*> entry_items);
-
-private slots:
- void ValidateEntry(const QModelIndex& item);
- void DonePopulating();
-
signals:
void GameChosen(QString game_path);
void ShouldCancelWorker();
+ void OpenSaveFolderRequested(u64 program_id);
private:
+ void AddEntry(const QList<QStandardItem*>& entry_items);
+ void ValidateEntry(const QModelIndex& item);
+ void DonePopulating();
+
+ void PopupContextMenu(const QPoint& menu_location);
+
QTreeView* tree_view = nullptr;
QStandardItemModel* item_model = nullptr;
GameListWorker* current_worker = nullptr;
diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h
index 5ca3fe991..a15f06c5f 100644
--- a/src/citra_qt/game_list_p.h
+++ b/src/citra_qt/game_list_p.h
@@ -71,10 +71,13 @@ class GameListItemPath : public GameListItem {
public:
static const int FullPathRole = Qt::UserRole + 1;
static const int TitleRole = Qt::UserRole + 2;
+ static const int ProgramIdRole = Qt::UserRole + 3;
GameListItemPath() : GameListItem() {}
- GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data) : GameListItem() {
+ GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id)
+ : GameListItem() {
setData(game_path, FullPathRole);
+ setData(qulonglong(program_id), ProgramIdRole);
if (!Loader::IsValidSMDH(smdh_data)) {
// SMDH is not valid, set a default icon
diff --git a/src/citra_qt/hotkeys.h b/src/citra_qt/hotkeys.h
index 350103c6f..46f48c2d8 100644
--- a/src/citra_qt/hotkeys.h
+++ b/src/citra_qt/hotkeys.h
@@ -55,7 +55,7 @@ class GHotkeysDialog : public QWidget {
Q_OBJECT
public:
- GHotkeysDialog(QWidget* parent = nullptr);
+ explicit GHotkeysDialog(QWidget* parent = nullptr);
private:
Ui::hotkeys ui;
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index a3887f9ab..ad6221739 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cinttypes>
#include <clocale>
#include <memory>
#include <thread>
@@ -41,6 +42,7 @@
#include "common/string_util.h"
#include "core/arm/disassembler/load_symbol_map.h"
#include "core/core.h"
+#include "core/file_sys/archive_source_sd_savedata.h"
#include "core/gdbstub/gdbstub.h"
#include "core/loader/loader.h"
#include "core/settings.h"
@@ -171,6 +173,8 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
// Setup connections
connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)),
Qt::DirectConnection);
+ connect(game_list, SIGNAL(OpenSaveFolderRequested(u64)), this,
+ SLOT(OnGameListOpenSaveFolder(u64)), Qt::DirectConnection);
connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure()));
connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),
Qt::DirectConnection);
@@ -460,6 +464,21 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
BootGame(game_path.toStdString());
}
+void GMainWindow::OnGameListOpenSaveFolder(u64 program_id) {
+ std::string sdmc_dir = FileUtil::GetUserPath(D_SDMC_IDX);
+ std::string path = FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor(sdmc_dir, program_id);
+ QString qpath = QString::fromStdString(path);
+
+ QDir dir(qpath);
+ if (!dir.exists()) {
+ QMessageBox::critical(this, tr("Error Opening Save Folder"), tr("Folder does not exist!"));
+ return;
+ }
+
+ LOG_INFO(Frontend, "Opening save data path for program_id=%" PRIu64, program_id);
+ QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
+}
+
void GMainWindow::OnMenuLoadFile() {
QString filename =
QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path,
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index f87178227..035b68a35 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -105,6 +105,7 @@ private slots:
void OnStopGame();
/// Called whenever a user selects a game in the game list widget.
void OnGameListLoadFile(QString game_path);
+ void OnGameListOpenSaveFolder(u64 program_id);
void OnMenuLoadFile();
void OnMenuLoadSymbolMap();
/// Called whenever a user selects the "File->Select Game List Root" menu item
diff --git a/src/citra_qt/util/spinbox.h b/src/citra_qt/util/spinbox.h
index a57355cd6..2fa1db3a4 100644
--- a/src/citra_qt/util/spinbox.h
+++ b/src/citra_qt/util/spinbox.h
@@ -42,7 +42,7 @@ class CSpinBox : public QAbstractSpinBox {
Q_OBJECT
public:
- CSpinBox(QWidget* parent = nullptr);
+ explicit CSpinBox(QWidget* parent = nullptr);
void stepBy(int steps) override;
StepEnabled stepEnabled() const override;