diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index 10336986de..935627b901 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -452,6 +452,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -577,6 +582,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -712,6 +722,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -837,6 +852,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -861,6 +881,7 @@
+
@@ -1302,6 +1323,24 @@
.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"
+
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing save_manager_dialog.h...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing save_manager_dialog.h...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing save_manager_dialog.h...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing save_manager_dialog.h...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"
+
Moc%27ing welcome_dialog.h...
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index 162d4c67bd..89f7b1459a 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -479,6 +479,21 @@
Gui\saves
+
+ Gui\saves
+
+
+ Generated Files\Release - LLVM
+
+
+ Generated Files\Debug
+
+
+ Generated Files\Release
+
+
+ Generated Files\Debug - LLVM
+
@@ -639,6 +654,9 @@
Gui\saves
+
+ Gui\saves
+
diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp
index 1a7222ad08..8e56bb924b 100644
--- a/rpcs3/rpcs3qt/main_window.cpp
+++ b/rpcs3/rpcs3qt/main_window.cpp
@@ -9,7 +9,7 @@
#include
#include "vfs_dialog.h"
-#include "save_data_list_dialog.h"
+#include "save_manager_dialog.h"
#include "kernel_explorer.h"
#include "game_list_frame.h"
#include "debugger_frame.h"
@@ -1141,7 +1141,8 @@ void main_window::CreateConnects()
gameListFrame->Refresh(true); // dev-hdd0 may have changed. Refresh just in case.
});
connect(ui->confSavedataManagerAct, &QAction::triggered, [=](){
- save_data_list_dialog* sdid = new save_data_list_dialog({}, 0, false, this);
+
+ save_manager_dialog* sdid = new save_manager_dialog();
sdid->show();
});
connect(ui->toolsCgDisasmAct, &QAction::triggered, [=](){
diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui
index dfa8d98e96..a4a463e997 100644
--- a/rpcs3/rpcs3qt/main_window.ui
+++ b/rpcs3/rpcs3qt/main_window.ui
@@ -141,7 +141,7 @@
0
0
1058
- 21
+ 26
@@ -475,7 +475,7 @@
- false
+ true
Save Data
diff --git a/rpcs3/rpcs3qt/save_data_list_dialog.cpp b/rpcs3/rpcs3qt/save_data_list_dialog.cpp
index 4b5766eb83..3e9e384920 100644
--- a/rpcs3/rpcs3qt/save_data_list_dialog.cpp
+++ b/rpcs3/rpcs3qt/save_data_list_dialog.cpp
@@ -69,8 +69,6 @@ save_data_list_dialog::save_data_list_dialog(const std::vector& e
Q_UNUSED(cr); Q_UNUSED(pr); Q_UNUSED(pc);
});
- // TODO: Unstub functions inside of this context menu so it makes sense to show this menu
- //connect(m_list, &QTableWidget::customContextMenuRequested, this, &save_data_list_dialog::ShowContextMenu);
connect(m_list->horizontalHeader(), &QHeaderView::sectionClicked, [=](int col) {
OnSort(col);
});
@@ -86,7 +84,6 @@ save_data_list_dialog::save_data_list_dialog(const std::vector& e
vbox_main->addLayout(hbox_action);
setLayout(vbox_main);
- LoadEntries();
UpdateList();
connect(m_list, &QTableWidget::cellChanged, [&](int row, int col) {
@@ -152,30 +149,6 @@ void save_data_list_dialog::OnSort(int idx)
}
}
-//Copy a existing save, need to get more arguments. maybe a new dialog.
-void save_data_list_dialog::OnEntryCopy()
-{
- int idx = m_list->currentRow();
- if (idx != -1)
- {
- LOG_WARNING(HLE, "Stub - save_data_utility: save_data_list_dialog: OnEntryCopy called.");
- //Some Operations?
- UpdateList();
- }
-}
-
-//Remove a save file, need to be confirmed.
-void save_data_list_dialog::OnEntryRemove()
-{
- int idx = m_list->currentRow();
- if (idx != -1)
- {
- LOG_WARNING(HLE, "Stub - save_data_utility: save_data_list_dialog: OnEntryRemove called.");
- //Some Operations?
- UpdateList();
- }
-}
-
//Display info dialog directly.
void save_data_list_dialog::OnEntryInfo()
{
@@ -188,55 +161,7 @@ void save_data_list_dialog::OnEntryInfo()
}
}
-//Pop-up a small context-menu, being a replacement for save_data_manage_dialog
-void save_data_list_dialog::ShowContextMenu(const QPoint &pos)
-{
- QPoint globalPos = m_list->mapToGlobal(pos);
- QMenu* menu = new QMenu();
- int idx = m_list->currentRow();
-
- saveIDAct = new QAction(tr("SaveID"), this);
- titleAct = new QAction(tr("Title"), this);
- subtitleAct = new QAction(tr("Subtitle"), this);
- copyAct = new QAction(tr("&Copy"), this);
- removeAct = new QAction(tr("&Remove"), this);
- infoAct = new QAction(tr("&Info"), this);
-
- //This is also a stub for the sort setting. Ids is set according to their sort-type integer.
- m_sort_options = new QMenu(tr("&Sort"));
- m_sort_options->addAction(titleAct);
- m_sort_options->addAction(subtitleAct);
- m_sort_options->addAction(saveIDAct);
-
- menu->addMenu(m_sort_options);
- menu->addSeparator();
- menu->addAction(copyAct);
- menu->addAction(removeAct);
- menu->addSeparator();
- menu->addAction(infoAct);
-
- copyAct->setEnabled(idx != -1);
- removeAct->setEnabled(idx != -1);
-
- //Events
- connect(copyAct, &QAction::triggered, this, &save_data_list_dialog::OnEntryCopy);
- connect(removeAct, &QAction::triggered, this, &save_data_list_dialog::OnEntryRemove);
- connect(infoAct, &QAction::triggered, this, &save_data_list_dialog::OnEntryInfo);
-
- connect(titleAct, &QAction::triggered, this, [=] {OnSort(0); });
- connect(subtitleAct, &QAction::triggered, this, [=] {OnSort(1); });
- connect(saveIDAct, &QAction::triggered, this, [=] {OnSort(2); });
-
- menu->exec(globalPos);
-}
-
-//This is intended to load the save data list from a way. However that is not certain for a stub. Does nothing now.
-void save_data_list_dialog::LoadEntries(void)
-{
-
-}
-
-void save_data_list_dialog::UpdateList(void)
+void save_data_list_dialog::UpdateList()
{
m_list->clearContents();
m_list->setRowCount(m_save_entries.size());
diff --git a/rpcs3/rpcs3qt/save_data_list_dialog.h b/rpcs3/rpcs3qt/save_data_list_dialog.h
index 622a64bcec..0c78574ccf 100644
--- a/rpcs3/rpcs3qt/save_data_list_dialog.h
+++ b/rpcs3/rpcs3qt/save_data_list_dialog.h
@@ -2,6 +2,7 @@
// I just want the struct for the save data.
#include "stdafx.h"
+#include "Emu/System.h"
#include "Emu/Memory/Memory.h"
#include "Emu/Cell/Modules/cellSaveData.h"
@@ -20,13 +21,9 @@ public:
s32 GetSelection();
private Q_SLOTS:
- void OnEntryCopy();
- void OnEntryRemove();
void OnEntryInfo();
- void ShowContextMenu(const QPoint &pos);
private:
void UpdateSelectionLabel(void);
- void LoadEntries(void);
void UpdateList(void);
void OnSort(int id);
@@ -36,15 +33,6 @@ private:
QTableWidget* m_list;
std::vector m_save_entries;
- QMenu* m_sort_options;
-
int m_sortColumn;
bool m_sortAscending;
-
- QAction* saveIDAct;
- QAction* titleAct;
- QAction* subtitleAct;
- QAction* copyAct;
- QAction* removeAct;
- QAction* infoAct;
};
diff --git a/rpcs3/rpcs3qt/save_manager_dialog.cpp b/rpcs3/rpcs3qt/save_manager_dialog.cpp
new file mode 100644
index 0000000000..3b904babaa
--- /dev/null
+++ b/rpcs3/rpcs3qt/save_manager_dialog.cpp
@@ -0,0 +1,290 @@
+#include "save_manager_dialog.h"
+
+#include "save_data_info_dialog.h"
+#include "gui_settings.h"
+
+#include "Emu/System.h"
+#include "Emu/VFS.h"
+#include "Loader/PSF.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace
+{
+ // Helper converters
+ inline QString qstr(const std::string& _in) { return QString::fromUtf8(_in.data(), _in.size()); }
+ inline std::string sstr(const QString& _in) { return _in.toUtf8().toStdString(); }
+
+ /**
+ * This certainly isn't ideal for this code, as it essentially copies cellSaveData. But, I have no other choice without adding public methods to cellSaveData.
+ */
+ std::vector GetSaveEntries(const std::string& base_dir)
+ {
+
+ std::vector save_entries;
+
+ // get the saves matching the supplied prefix
+ for (const auto& entry : fs::dir(base_dir))
+ {
+ if (!entry.is_directory)
+ {
+ continue;
+ }
+
+ // PSF parameters
+ const auto& psf = psf::load_object(fs::file(base_dir + entry.name + "/PARAM.SFO"));
+
+ if (psf.empty())
+ {
+ continue;
+ }
+
+ SaveDataEntry save_entry2;
+ save_entry2.dirName = psf.at("SAVEDATA_DIRECTORY").as_string();
+ save_entry2.listParam = psf.at("SAVEDATA_LIST_PARAM").as_string();
+ save_entry2.title = psf.at("TITLE").as_string();
+ save_entry2.subtitle = psf.at("SUB_TITLE").as_string();
+ save_entry2.details = psf.at("DETAIL").as_string();
+
+ save_entry2.size = 0;
+
+ for (const auto entry2 : fs::dir(base_dir + entry.name))
+ {
+ save_entry2.size += entry2.size;
+ }
+
+ save_entry2.atime = entry.atime;
+ save_entry2.mtime = entry.mtime;
+ save_entry2.ctime = entry.ctime;
+ if (fs::is_file(base_dir + entry.name + "/ICON0.PNG"))
+ {
+ fs::file icon = fs::file(base_dir + entry.name + "/ICON0.PNG");
+ u32 iconSize = icon.size();
+ std::vector iconData;
+ icon.read(iconData, iconSize);
+ save_entry2.iconBuf = iconData;
+ }
+ save_entry2.isNew = false;
+ save_entries.emplace_back(save_entry2);
+ }
+ return save_entries;
+ }
+}
+
+save_manager_dialog::save_manager_dialog(std::string dir, QWidget* parent) : QDialog(parent),
+ m_save_entries(), m_dir(dir), m_sortColumn(1), m_sortAscending(true)
+{
+ setWindowTitle(tr("Save Manager"));
+ setWindowIcon(QIcon(":/rpcs3.ico"));
+ setMinimumSize(QSize(400, 400));
+
+ Init(dir);
+}
+
+/*
+ * Future proofing. Makes it easier in future if I add ability to change directories
+ */
+void save_manager_dialog::Init(std::string dir)
+{
+ // Table
+ m_list = new QTableWidget(this);
+
+ //m_list->setItemDelegate(new table_item_delegate(this)); // to get rid of cell selection rectangles include "table_item_delegate.h"
+ m_list->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
+ m_list->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_list->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_list->setColumnCount(4);
+ m_list->setHorizontalHeaderLabels(QStringList() << tr("Title") << tr("Subtitle") << tr("Save ID") << tr("Entry Notes"));
+
+ // Button Layout
+ QHBoxLayout* hbox_buttons = new QHBoxLayout();
+
+ QPushButton* push_close = new QPushButton(tr("&Close"), this);
+ push_close->setAutoDefault(true);
+ hbox_buttons->addStretch();
+ hbox_buttons->addWidget(push_close);
+
+ // main layout
+ QVBoxLayout* vbox_main = new QVBoxLayout();
+ vbox_main->setAlignment(Qt::AlignCenter);
+ vbox_main->addWidget(m_list);
+ vbox_main->addLayout(hbox_buttons);
+
+ setLayout(vbox_main);
+
+ UpdateList();
+
+
+ // Connects and events
+ connect(push_close, &QAbstractButton::clicked, this, &save_manager_dialog::close);
+ connect(m_list, &QTableWidget::itemDoubleClicked, this, &save_manager_dialog::OnEntryInfo);
+
+ connect(m_list, &QTableWidget::customContextMenuRequested, this, &save_manager_dialog::ShowContextMenu);
+ connect(m_list->horizontalHeader(), &QHeaderView::sectionClicked, [=](int col) {
+ OnSort(col);
+ });
+
+ connect(m_list, &QTableWidget::cellChanged, [&](int row, int col) {
+ int originalIndex = m_list->item(row, 0)->data(Qt::UserRole).toInt();
+ SaveDataEntry originalEntry = m_save_entries[originalIndex];
+ QString originalDirName = qstr(originalEntry.dirName);
+ gui_settings settings(this);
+ QVariantMap currNotes = settings.GetValue(GUI::m_saveNotes).toMap();
+ currNotes[originalDirName] = m_list->item(row, col)->text();
+ settings.SetValue(GUI::m_saveNotes, currNotes);
+ });
+}
+
+void save_manager_dialog::UpdateList()
+{
+ if (m_dir == "")
+ {
+ m_dir = Emu.GetHddDir() + "home/00000001/savedata/";
+ }
+
+ m_save_entries = GetSaveEntries(m_dir);
+
+ m_list->clearContents();
+ m_list->setRowCount(m_save_entries.size());
+ gui_settings settings(this);
+
+ int row = 0;
+ for (SaveDataEntry entry : m_save_entries)
+ {
+ QString title = qstr(entry.title);
+ QString subtitle = qstr(entry.subtitle);
+ QString dirName = qstr(entry.dirName);
+
+ QTableWidgetItem* titleItem = new QTableWidgetItem(title);
+ titleItem->setData(Qt::UserRole, row); // For sorting to work properly
+ titleItem->setFlags(titleItem->flags() & ~Qt::ItemIsEditable);
+
+ m_list->setItem(row, 0, titleItem);
+ QTableWidgetItem* subtitleItem = new QTableWidgetItem(subtitle);
+ subtitleItem->setFlags(subtitleItem->flags() & ~Qt::ItemIsEditable);
+ m_list->setItem(row, 1, subtitleItem);
+
+ QTableWidgetItem* dirNameItem = new QTableWidgetItem(dirName);
+ dirNameItem->setFlags(dirNameItem->flags() & ~Qt::ItemIsEditable);
+ m_list->setItem(row, 2, dirNameItem);
+
+ QVariantMap currNotes = settings.GetValue(GUI::m_saveNotes).toMap();
+ QTableWidgetItem* noteItem = new QTableWidgetItem();
+ noteItem->setFlags(noteItem->flags() | Qt::ItemIsEditable);
+ if (currNotes.contains(dirName))
+ {
+ noteItem->setText(currNotes[dirName].toString());
+ }
+ else
+ {
+ currNotes[dirName] = "";
+ settings.SetValue(GUI::m_saveNotes, currNotes);
+ }
+ m_list->setItem(row, 3, noteItem);
+ ++row;
+ }
+
+ m_list->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
+ m_list->verticalHeader()->resizeSections(QHeaderView::ResizeToContents);
+
+ QSize tableSize = QSize(
+ m_list->verticalHeader()->width() + m_list->horizontalHeader()->length() + m_list->frameWidth() * 2,
+ m_list->horizontalHeader()->height() + m_list->verticalHeader()->length() + m_list->frameWidth() * 2);
+
+ resize(minimumSize().expandedTo(sizeHint() - m_list->sizeHint() + tableSize));
+
+}
+
+/**
+* Copied method to do sort from save_data_list_dialog
+*/
+void save_manager_dialog::OnSort(int idx)
+{
+ if (idx >= 0)
+ {
+ if (idx == m_sortColumn)
+ {
+ m_sortAscending ^= true;
+ }
+ else
+ {
+ m_sortAscending = true;
+ }
+ Qt::SortOrder colSortOrder = m_sortAscending ? Qt::AscendingOrder : Qt::DescendingOrder;
+ m_list->sortByColumn(m_sortColumn, colSortOrder);
+ m_sortColumn = idx;
+ }
+}
+
+/**
+ *Display info dialog directly. Copied from save_data_list_dialog
+ */
+void save_manager_dialog::OnEntryInfo()
+{
+ int idx = m_list->currentRow();
+ if (idx != -1)
+ {
+ idx = m_list->item(idx, 0)->data(Qt::UserRole).toInt();
+ save_data_info_dialog* infoDialog = new save_data_info_dialog(m_save_entries[idx], this);
+ infoDialog->setModal(true);
+ infoDialog->show();
+ }
+}
+
+//Remove a save file, need to be confirmed.
+void save_manager_dialog::OnEntryRemove()
+{
+ int idx = m_list->currentRow();
+ if (idx != -1)
+ {
+ idx = m_list->item(idx, 0)->data(Qt::UserRole).toInt();
+ if (QMessageBox::question(this, "Delete Confirmation", "Are you sure you want to delete:\n" + qstr(m_save_entries[idx].title) + "?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
+ {
+ fs::remove_all(m_dir + m_save_entries[idx].dirName + "/");
+ UpdateList();
+ }
+ }
+}
+
+//Pop-up a small context-menu, being a replacement for save_data_manage_dialog
+void save_manager_dialog::ShowContextMenu(const QPoint &pos)
+{
+ QPoint globalPos = m_list->mapToGlobal(pos);
+ QMenu* menu = new QMenu();
+ int idx = m_list->currentRow();
+
+ saveIDAct = new QAction(tr("SaveID"), this);
+ titleAct = new QAction(tr("Title"), this);
+ subtitleAct = new QAction(tr("Subtitle"), this);
+ removeAct = new QAction(tr("&Remove"), this);
+ infoAct = new QAction(tr("&Info"), this);
+
+ //This is also a stub for the sort setting. Ids is set according to their sort-type integer.
+ m_sort_options = new QMenu(tr("&Sort"));
+ m_sort_options->addAction(titleAct);
+ m_sort_options->addAction(subtitleAct);
+ m_sort_options->addAction(saveIDAct);
+
+ menu->addMenu(m_sort_options);
+ menu->addSeparator();
+ menu->addAction(removeAct);
+ menu->addSeparator();
+ menu->addAction(infoAct);
+
+ removeAct->setEnabled(idx != -1);
+
+ //Events
+ connect(removeAct, &QAction::triggered, this, &save_manager_dialog::OnEntryRemove);
+ connect(infoAct, &QAction::triggered, this, &save_manager_dialog::OnEntryInfo);
+
+ connect(titleAct, &QAction::triggered, this, [=] {OnSort(0); });
+ connect(subtitleAct, &QAction::triggered, this, [=] {OnSort(1); });
+ connect(saveIDAct, &QAction::triggered, this, [=] {OnSort(2); });
+
+ menu->exec(globalPos);
+}
diff --git a/rpcs3/rpcs3qt/save_manager_dialog.h b/rpcs3/rpcs3qt/save_manager_dialog.h
new file mode 100644
index 0000000000..e756079c1b
--- /dev/null
+++ b/rpcs3/rpcs3qt/save_manager_dialog.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "stdafx.h"
+#include "Emu/Memory/Memory.h"
+#include "Emu/Cell/Modules/cellSaveData.h"
+
+#include
+#include
+
+class save_manager_dialog : public QDialog
+{
+ Q_OBJECT
+public:
+ /**
+ * Class which will handle the managing of saves from all games.
+ * You may think I should just modify save_data_list_dialog. But, that wouldn't be ideal long term since that class will be refactored into an overlay.
+ * Plus, there's the added complexity of an additional way in which the dialog will spawn differently.
+ * There'll be some duplicated code. But, in the future, there'll be no duplicated code. So, I don't care.
+ */
+ explicit save_manager_dialog(std::string dir = "", QWidget* parent = nullptr);
+private Q_SLOTS:
+ void OnEntryInfo();
+ void OnEntryRemove();
+private:
+ void Init(std::string dir);
+ void UpdateList();
+
+ void OnSort(int id);
+
+ void ShowContextMenu(const QPoint &pos);
+
+ QTableWidget* m_list;
+ std::string m_dir;
+ std::vector m_save_entries;
+
+ QMenu* m_sort_options;
+
+ int m_sortColumn;
+ bool m_sortAscending;
+
+ QAction* saveIDAct;
+ QAction* titleAct;
+ QAction* subtitleAct;
+ QAction* removeAct;
+ QAction* infoAct;
+};