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; +};