game_list: Implement context menu for items in list

* Add a context menu with a "Open Save Data Location" action
This commit is contained in:
MerryMage 2016-12-15 09:55:03 +00:00
parent 351b5d23f4
commit f50dcc88bf
3 changed files with 32 additions and 4 deletions

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <QHeaderView> #include <QHeaderView>
#include <QMenu>
#include <QThreadPool> #include <QThreadPool>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "common/common_paths.h" #include "common/common_paths.h"
@ -28,6 +29,7 @@ GameList::GameList(QWidget* parent) : QWidget{parent} {
tree_view->setSortingEnabled(true); tree_view->setSortingEnabled(true);
tree_view->setEditTriggers(QHeaderView::NoEditTriggers); tree_view->setEditTriggers(QHeaderView::NoEditTriggers);
tree_view->setUniformRowHeights(true); tree_view->setUniformRowHeights(true);
tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
item_model->insertColumns(0, COLUMN_COUNT); item_model->insertColumns(0, COLUMN_COUNT);
item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); 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"); item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size");
connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry); 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 // We must register all custom types with the Qt Automoc system so that we are able to use it
// with // with signals/slots. In this case, QList falls under the umbrells of custom types.
// signals/slots. In this case, QList falls under the umbrells of custom types.
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
layout->addWidget(tree_view); layout->addWidget(tree_view);
@ -71,6 +73,23 @@ void GameList::DonePopulating() {
tree_view->setEnabled(true); 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) { void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
if (!FileUtil::Exists(dir_path.toStdString()) || if (!FileUtil::Exists(dir_path.toStdString()) ||
!FileUtil::IsDirectory(dir_path.toStdString())) { !FileUtil::IsDirectory(dir_path.toStdString())) {
@ -128,8 +147,11 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
std::vector<u8> smdh; std::vector<u8> smdh;
loader->ReadIcon(smdh); loader->ReadIcon(smdh);
u64 program_id = 0;
loader->ReadProgramId(program_id);
emit EntryReady({ emit EntryReady({
new GameListItemPath(QString::fromStdString(physical_name), smdh), new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id),
new GameListItem( new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(FileUtil::GetSize(physical_name)), new GameListItemSize(FileUtil::GetSize(physical_name)),

View file

@ -36,12 +36,15 @@ public:
signals: signals:
void GameChosen(QString game_path); void GameChosen(QString game_path);
void ShouldCancelWorker(); void ShouldCancelWorker();
void OpenSaveFolderRequested(u64 program_id);
private: private:
void AddEntry(const QList<QStandardItem*>& entry_items); void AddEntry(const QList<QStandardItem*>& entry_items);
void ValidateEntry(const QModelIndex& item); void ValidateEntry(const QModelIndex& item);
void DonePopulating(); void DonePopulating();
void PopupContextMenu(const QPoint& menu_location);
QTreeView* tree_view = nullptr; QTreeView* tree_view = nullptr;
QStandardItemModel* item_model = nullptr; QStandardItemModel* item_model = nullptr;
GameListWorker* current_worker = nullptr; GameListWorker* current_worker = nullptr;

View file

@ -71,10 +71,13 @@ class GameListItemPath : public GameListItem {
public: public:
static const int FullPathRole = Qt::UserRole + 1; static const int FullPathRole = Qt::UserRole + 1;
static const int TitleRole = Qt::UserRole + 2; static const int TitleRole = Qt::UserRole + 2;
static const int ProgramIdRole = Qt::UserRole + 3;
GameListItemPath() : GameListItem() {} 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(game_path, FullPathRole);
setData(qulonglong(program_id), ProgramIdRole);
if (!Loader::IsValidSMDH(smdh_data)) { if (!Loader::IsValidSMDH(smdh_data)) {
// SMDH is not valid, set a default icon // SMDH is not valid, set a default icon