diff options
Diffstat (limited to 'src/citra_qt/game_list.cpp')
| -rw-r--r-- | src/citra_qt/game_list.cpp | 65 |
1 files changed, 28 insertions, 37 deletions
diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index 1910da3ac..07bc35308 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp | |||
| @@ -5,19 +5,15 @@ | |||
| 5 | #include <QHeaderView> | 5 | #include <QHeaderView> |
| 6 | #include <QThreadPool> | 6 | #include <QThreadPool> |
| 7 | #include <QVBoxLayout> | 7 | #include <QVBoxLayout> |
| 8 | |||
| 9 | #include "game_list.h" | ||
| 10 | #include "game_list_p.h" | ||
| 11 | #include "ui_settings.h" | ||
| 12 | |||
| 13 | #include "core/loader/loader.h" | ||
| 14 | |||
| 15 | #include "common/common_paths.h" | 8 | #include "common/common_paths.h" |
| 16 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 17 | #include "common/string_util.h" | 10 | #include "common/string_util.h" |
| 11 | #include "core/loader/loader.h" | ||
| 12 | #include "game_list.h" | ||
| 13 | #include "game_list_p.h" | ||
| 14 | #include "ui_settings.h" | ||
| 18 | 15 | ||
| 19 | GameList::GameList(QWidget* parent) | 16 | GameList::GameList(QWidget* parent) { |
| 20 | { | ||
| 21 | QVBoxLayout* layout = new QVBoxLayout; | 17 | QVBoxLayout* layout = new QVBoxLayout; |
| 22 | 18 | ||
| 23 | tree_view = new QTreeView; | 19 | tree_view = new QTreeView; |
| @@ -38,9 +34,11 @@ GameList::GameList(QWidget* parent) | |||
| 38 | item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); | 34 | item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); |
| 39 | item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); | 35 | item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); |
| 40 | 36 | ||
| 41 | connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, SLOT(ValidateEntry(const QModelIndex&))); | 37 | connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, |
| 38 | SLOT(ValidateEntry(const QModelIndex&))); | ||
| 42 | 39 | ||
| 43 | // We must register all custom types with the Qt Automoc system so that we are able to use it with | 40 | // We must register all custom types with the Qt Automoc system so that we are able to use it |
| 41 | // with | ||
| 44 | // signals/slots. In this case, QList falls under the umbrells of custom types. | 42 | // signals/slots. In this case, QList falls under the umbrells of custom types. |
| 45 | qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); | 43 | qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); |
| 46 | 44 | ||
| @@ -48,18 +46,15 @@ GameList::GameList(QWidget* parent) | |||
| 48 | setLayout(layout); | 46 | setLayout(layout); |
| 49 | } | 47 | } |
| 50 | 48 | ||
| 51 | GameList::~GameList() | 49 | GameList::~GameList() { |
| 52 | { | ||
| 53 | emit ShouldCancelWorker(); | 50 | emit ShouldCancelWorker(); |
| 54 | } | 51 | } |
| 55 | 52 | ||
| 56 | void GameList::AddEntry(QList<QStandardItem*> entry_items) | 53 | void GameList::AddEntry(QList<QStandardItem*> entry_items) { |
| 57 | { | ||
| 58 | item_model->invisibleRootItem()->appendRow(entry_items); | 54 | item_model->invisibleRootItem()->appendRow(entry_items); |
| 59 | } | 55 | } |
| 60 | 56 | ||
| 61 | void GameList::ValidateEntry(const QModelIndex& item) | 57 | void GameList::ValidateEntry(const QModelIndex& item) { |
| 62 | { | ||
| 63 | // We don't care about the individual QStandardItem that was selected, but its row. | 58 | // We don't care about the individual QStandardItem that was selected, but its row. |
| 64 | int row = item_model->itemFromIndex(item)->row(); | 59 | int row = item_model->itemFromIndex(item)->row(); |
| 65 | QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME); | 60 | QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME); |
| @@ -73,14 +68,13 @@ void GameList::ValidateEntry(const QModelIndex& item) | |||
| 73 | emit GameChosen(file_path); | 68 | emit GameChosen(file_path); |
| 74 | } | 69 | } |
| 75 | 70 | ||
| 76 | void GameList::DonePopulating() | 71 | void GameList::DonePopulating() { |
| 77 | { | ||
| 78 | tree_view->setEnabled(true); | 72 | tree_view->setEnabled(true); |
| 79 | } | 73 | } |
| 80 | 74 | ||
| 81 | void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) | 75 | void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { |
| 82 | { | 76 | if (!FileUtil::Exists(dir_path.toStdString()) || |
| 83 | if (!FileUtil::Exists(dir_path.toStdString()) || !FileUtil::IsDirectory(dir_path.toStdString())) { | 77 | !FileUtil::IsDirectory(dir_path.toStdString())) { |
| 84 | LOG_ERROR(Frontend, "Could not find game list folder at %s", dir_path.toLocal8Bit().data()); | 78 | LOG_ERROR(Frontend, "Could not find game list folder at %s", dir_path.toLocal8Bit().data()); |
| 85 | return; | 79 | return; |
| 86 | } | 80 | } |
| @@ -92,22 +86,22 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) | |||
| 92 | emit ShouldCancelWorker(); | 86 | emit ShouldCancelWorker(); |
| 93 | GameListWorker* worker = new GameListWorker(dir_path, deep_scan); | 87 | GameListWorker* worker = new GameListWorker(dir_path, deep_scan); |
| 94 | 88 | ||
| 95 | connect(worker, SIGNAL(EntryReady(QList<QStandardItem*>)), this, SLOT(AddEntry(QList<QStandardItem*>)), Qt::QueuedConnection); | 89 | connect(worker, SIGNAL(EntryReady(QList<QStandardItem*>)), this, |
| 90 | SLOT(AddEntry(QList<QStandardItem*>)), Qt::QueuedConnection); | ||
| 96 | connect(worker, SIGNAL(Finished()), this, SLOT(DonePopulating()), Qt::QueuedConnection); | 91 | connect(worker, SIGNAL(Finished()), this, SLOT(DonePopulating()), Qt::QueuedConnection); |
| 97 | // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to cancel without delay. | 92 | // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to cancel |
| 93 | // without delay. | ||
| 98 | connect(this, SIGNAL(ShouldCancelWorker()), worker, SLOT(Cancel()), Qt::DirectConnection); | 94 | connect(this, SIGNAL(ShouldCancelWorker()), worker, SLOT(Cancel()), Qt::DirectConnection); |
| 99 | 95 | ||
| 100 | QThreadPool::globalInstance()->start(worker); | 96 | QThreadPool::globalInstance()->start(worker); |
| 101 | current_worker = std::move(worker); | 97 | current_worker = std::move(worker); |
| 102 | } | 98 | } |
| 103 | 99 | ||
| 104 | void GameList::SaveInterfaceLayout() | 100 | void GameList::SaveInterfaceLayout() { |
| 105 | { | ||
| 106 | UISettings::values.gamelist_header_state = tree_view->header()->saveState(); | 101 | UISettings::values.gamelist_header_state = tree_view->header()->saveState(); |
| 107 | } | 102 | } |
| 108 | 103 | ||
| 109 | void GameList::LoadInterfaceLayout() | 104 | void GameList::LoadInterfaceLayout() { |
| 110 | { | ||
| 111 | auto header = tree_view->header(); | 105 | auto header = tree_view->header(); |
| 112 | if (!header->restoreState(UISettings::values.gamelist_header_state)) { | 106 | if (!header->restoreState(UISettings::values.gamelist_header_state)) { |
| 113 | // We are using the name column to display icons and titles | 107 | // We are using the name column to display icons and titles |
| @@ -118,10 +112,8 @@ void GameList::LoadInterfaceLayout() | |||
| 118 | item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); | 112 | item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); |
| 119 | } | 113 | } |
| 120 | 114 | ||
| 121 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) | 115 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { |
| 122 | { | 116 | const auto callback = [this, recursion](unsigned* num_entries_out, const std::string& directory, |
| 123 | const auto callback = [this, recursion](unsigned* num_entries_out, | ||
| 124 | const std::string& directory, | ||
| 125 | const std::string& virtual_name) -> bool { | 117 | const std::string& virtual_name) -> bool { |
| 126 | std::string physical_name = directory + DIR_SEP + virtual_name; | 118 | std::string physical_name = directory + DIR_SEP + virtual_name; |
| 127 | 119 | ||
| @@ -138,7 +130,8 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | |||
| 138 | 130 | ||
| 139 | emit EntryReady({ | 131 | emit EntryReady({ |
| 140 | new GameListItemPath(QString::fromStdString(physical_name), smdh), | 132 | new GameListItemPath(QString::fromStdString(physical_name), smdh), |
| 141 | new GameListItem(QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), | 133 | new GameListItem( |
| 134 | QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), | ||
| 142 | new GameListItemSize(FileUtil::GetSize(physical_name)), | 135 | new GameListItemSize(FileUtil::GetSize(physical_name)), |
| 143 | }); | 136 | }); |
| 144 | } else if (recursion > 0) { | 137 | } else if (recursion > 0) { |
| @@ -151,15 +144,13 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | |||
| 151 | FileUtil::ForeachDirectoryEntry(nullptr, dir_path, callback); | 144 | FileUtil::ForeachDirectoryEntry(nullptr, dir_path, callback); |
| 152 | } | 145 | } |
| 153 | 146 | ||
| 154 | void GameListWorker::run() | 147 | void GameListWorker::run() { |
| 155 | { | ||
| 156 | stop_processing = false; | 148 | stop_processing = false; |
| 157 | AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); | 149 | AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); |
| 158 | emit Finished(); | 150 | emit Finished(); |
| 159 | } | 151 | } |
| 160 | 152 | ||
| 161 | void GameListWorker::Cancel() | 153 | void GameListWorker::Cancel() { |
| 162 | { | ||
| 163 | disconnect(this, 0, 0, 0); | 154 | disconnect(this, 0, 0, 0); |
| 164 | stop_processing = true; | 155 | stop_processing = true; |
| 165 | } | 156 | } |