From f50dcc88bf160100336c94673aa7679403405cdd Mon Sep 17 00:00:00 2001 From: MerryMage Date: Thu, 15 Dec 2016 09:55:03 +0000 Subject: [PATCH] game_list: Implement context menu for items in list * Add a context menu with a "Open Save Data Location" action --- src/citra_qt/game_list.cpp | 28 +++++++++++++++++++++++++--- src/citra_qt/game_list.h | 3 +++ src/citra_qt/game_list_p.h | 5 ++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index e536628dd..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 +#include #include #include #include "common/common_paths.h" @@ -28,6 +29,7 @@ GameList::GameList(QWidget* parent) : 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"); @@ -35,10 +37,10 @@ GameList::GameList(QWidget* parent) : QWidget{parent} { item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); 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"); layout->addWidget(tree_view); @@ -71,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())) { @@ -128,8 +147,11 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign std::vector 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)), diff --git a/src/citra_qt/game_list.h b/src/citra_qt/game_list.h index 30b2c79a8..1abf10051 100644 --- a/src/citra_qt/game_list.h +++ b/src/citra_qt/game_list.h @@ -36,12 +36,15 @@ public: signals: void GameChosen(QString game_path); void ShouldCancelWorker(); + void OpenSaveFolderRequested(u64 program_id); private: void AddEntry(const QList& 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& smdh_data) : GameListItem() { + GameListItemPath(const QString& game_path, const std::vector& 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