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