diff options
| author | 2016-12-15 09:55:03 +0000 | |
|---|---|---|
| committer | 2016-12-15 18:43:10 +0000 | |
| commit | f50dcc88bf160100336c94673aa7679403405cdd (patch) | |
| tree | 14e2f9682f5f58568eff94b42711b7b80e986e91 /src | |
| parent | loader: Implement ReadProgramId (diff) | |
| download | yuzu-f50dcc88bf160100336c94673aa7679403405cdd.tar.gz yuzu-f50dcc88bf160100336c94673aa7679403405cdd.tar.xz yuzu-f50dcc88bf160100336c94673aa7679403405cdd.zip | |
game_list: Implement context menu for items in list
* Add a context menu with a "Open Save Data Location" action
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra_qt/game_list.cpp | 28 | ||||
| -rw-r--r-- | src/citra_qt/game_list.h | 3 | ||||
| -rw-r--r-- | 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 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QHeaderView> | 5 | #include <QHeaderView> |
| 6 | #include <QMenu> | ||
| 6 | #include <QThreadPool> | 7 | #include <QThreadPool> |
| 7 | #include <QVBoxLayout> | 8 | #include <QVBoxLayout> |
| 8 | #include "common/common_paths.h" | 9 | #include "common/common_paths.h" |
| @@ -28,6 +29,7 @@ GameList::GameList(QWidget* parent) : QWidget{parent} { | |||
| 28 | tree_view->setSortingEnabled(true); | 29 | tree_view->setSortingEnabled(true); |
| 29 | tree_view->setEditTriggers(QHeaderView::NoEditTriggers); | 30 | tree_view->setEditTriggers(QHeaderView::NoEditTriggers); |
| 30 | tree_view->setUniformRowHeights(true); | 31 | tree_view->setUniformRowHeights(true); |
| 32 | tree_view->setContextMenuPolicy(Qt::CustomContextMenu); | ||
| 31 | 33 | ||
| 32 | item_model->insertColumns(0, COLUMN_COUNT); | 34 | item_model->insertColumns(0, COLUMN_COUNT); |
| 33 | item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); | 35 | item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); |
| @@ -35,10 +37,10 @@ GameList::GameList(QWidget* parent) : QWidget{parent} { | |||
| 35 | item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); | 37 | item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); |
| 36 | 38 | ||
| 37 | connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry); | 39 | connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry); |
| 40 | connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu); | ||
| 38 | 41 | ||
| 39 | // We must register all custom types with the Qt Automoc system so that we are able to use it | 42 | // We must register all custom types with the Qt Automoc system so that we are able to use it |
| 40 | // with | 43 | // with signals/slots. In this case, QList falls under the umbrells of custom types. |
| 41 | // signals/slots. In this case, QList falls under the umbrells of custom types. | ||
| 42 | qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); | 44 | qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); |
| 43 | 45 | ||
| 44 | layout->addWidget(tree_view); | 46 | layout->addWidget(tree_view); |
| @@ -71,6 +73,23 @@ void GameList::DonePopulating() { | |||
| 71 | tree_view->setEnabled(true); | 73 | tree_view->setEnabled(true); |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 76 | void GameList::PopupContextMenu(const QPoint& menu_location) { | ||
| 77 | QModelIndex item = tree_view->indexAt(menu_location); | ||
| 78 | if (!item.isValid()) | ||
| 79 | return; | ||
| 80 | |||
| 81 | int row = item_model->itemFromIndex(item)->row(); | ||
| 82 | QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME); | ||
| 83 | u64 program_id = child_file->data(GameListItemPath::ProgramIdRole).toULongLong(); | ||
| 84 | |||
| 85 | QMenu context_menu; | ||
| 86 | QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); | ||
| 87 | open_save_location->setEnabled(program_id != 0); | ||
| 88 | connect(open_save_location, &QAction::triggered, | ||
| 89 | [&]() { emit OpenSaveFolderRequested(program_id); }); | ||
| 90 | context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); | ||
| 91 | } | ||
| 92 | |||
| 74 | void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { | 93 | void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { |
| 75 | if (!FileUtil::Exists(dir_path.toStdString()) || | 94 | if (!FileUtil::Exists(dir_path.toStdString()) || |
| 76 | !FileUtil::IsDirectory(dir_path.toStdString())) { | 95 | !FileUtil::IsDirectory(dir_path.toStdString())) { |
| @@ -128,8 +147,11 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | |||
| 128 | std::vector<u8> smdh; | 147 | std::vector<u8> smdh; |
| 129 | loader->ReadIcon(smdh); | 148 | loader->ReadIcon(smdh); |
| 130 | 149 | ||
| 150 | u64 program_id = 0; | ||
| 151 | loader->ReadProgramId(program_id); | ||
| 152 | |||
| 131 | emit EntryReady({ | 153 | emit EntryReady({ |
| 132 | new GameListItemPath(QString::fromStdString(physical_name), smdh), | 154 | new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id), |
| 133 | new GameListItem( | 155 | new GameListItem( |
| 134 | QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), | 156 | QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), |
| 135 | new GameListItemSize(FileUtil::GetSize(physical_name)), | 157 | 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: | |||
| 36 | signals: | 36 | signals: |
| 37 | void GameChosen(QString game_path); | 37 | void GameChosen(QString game_path); |
| 38 | void ShouldCancelWorker(); | 38 | void ShouldCancelWorker(); |
| 39 | void OpenSaveFolderRequested(u64 program_id); | ||
| 39 | 40 | ||
| 40 | private: | 41 | private: |
| 41 | void AddEntry(const QList<QStandardItem*>& entry_items); | 42 | void AddEntry(const QList<QStandardItem*>& entry_items); |
| 42 | void ValidateEntry(const QModelIndex& item); | 43 | void ValidateEntry(const QModelIndex& item); |
| 43 | void DonePopulating(); | 44 | void DonePopulating(); |
| 44 | 45 | ||
| 46 | void PopupContextMenu(const QPoint& menu_location); | ||
| 47 | |||
| 45 | QTreeView* tree_view = nullptr; | 48 | QTreeView* tree_view = nullptr; |
| 46 | QStandardItemModel* item_model = nullptr; | 49 | QStandardItemModel* item_model = nullptr; |
| 47 | GameListWorker* current_worker = nullptr; | 50 | 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 { | |||
| 71 | public: | 71 | public: |
| 72 | static const int FullPathRole = Qt::UserRole + 1; | 72 | static const int FullPathRole = Qt::UserRole + 1; |
| 73 | static const int TitleRole = Qt::UserRole + 2; | 73 | static const int TitleRole = Qt::UserRole + 2; |
| 74 | static const int ProgramIdRole = Qt::UserRole + 3; | ||
| 74 | 75 | ||
| 75 | GameListItemPath() : GameListItem() {} | 76 | GameListItemPath() : GameListItem() {} |
| 76 | GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data) : GameListItem() { | 77 | GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id) |
| 78 | : GameListItem() { | ||
| 77 | setData(game_path, FullPathRole); | 79 | setData(game_path, FullPathRole); |
| 80 | setData(qulonglong(program_id), ProgramIdRole); | ||
| 78 | 81 | ||
| 79 | if (!Loader::IsValidSMDH(smdh_data)) { | 82 | if (!Loader::IsValidSMDH(smdh_data)) { |
| 80 | // SMDH is not valid, set a default icon | 83 | // SMDH is not valid, set a default icon |