You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.6 KiB
140 lines
4.6 KiB
#include "GameListModel.h"
|
|
|
|
#include <QDirIterator>
|
|
#include <QGuiApplication>
|
|
#include <QThreadPool>
|
|
|
|
#include "GameIconProvider.h"
|
|
#include "GameListWorker.h"
|
|
#include "common/logging/filter.h"
|
|
#include "core/hle/service/filesystem/filesystem.h"
|
|
#include "hid_core/hid_core.h"
|
|
#include "qt_common/qt_common.h"
|
|
#include "qt_common/qt_meta.h"
|
|
|
|
GameListModel::GameListModel(QObject *parent, QQmlEngine *engine) {
|
|
QHash<int, QByteArray> rez = QStandardItemModel::roleNames();
|
|
rez.insert(GLMRoleTypes::NAME, "name");
|
|
rez.insert(GLMRoleTypes::PATH, "path");
|
|
rez.insert(GLMRoleTypes::FILESIZE, "size");
|
|
rez.insert(GLMRoleTypes::ICON, "icon");
|
|
|
|
QStandardItemModel::setItemRoleNames(rez);
|
|
|
|
QtCommon::Meta::RegisterMetaTypes();
|
|
QtCommon::system->HIDCore().ReloadInputDevices();
|
|
QtCommon::system->SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
|
QtCommon::system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual,
|
|
QtCommon::provider.get());
|
|
QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
|
|
|
|
m_provider = new GameIconProvider;
|
|
engine->addImageProvider(QStringLiteral("games"), m_provider);
|
|
|
|
watcher = new QFileSystemWatcher(this);
|
|
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameListModel::RefreshGameDirectory);
|
|
|
|
populateAsync(UISettings::values.game_dirs);
|
|
}
|
|
|
|
QVariant GameListModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid())
|
|
return QVariant();
|
|
|
|
if (role == GLMRoleTypes::NAME) {
|
|
return itemFromIndex(index)->text();
|
|
}
|
|
|
|
return QStandardItemModel::data(index, role);
|
|
}
|
|
|
|
// void GameListModel::addDir(const QString &toAdd)
|
|
// {
|
|
// QString name = toAdd;
|
|
// #ifdef Q_OS_WINDOWS
|
|
// name.replace("file:///", "");
|
|
// #else
|
|
// name.replace("file://", "");
|
|
// #endif
|
|
|
|
// UISettings::GameDir game_dir{name.toStdString(), false, true};
|
|
// if (!UISettings::values.game_dirs.contains(game_dir)) {
|
|
// UISettings::values.game_dirs.append(game_dir);
|
|
// populateAsync(UISettings::values.game_dirs);
|
|
// } else {
|
|
// LOG_WARNING(Frontend, "Selected directory is already in the game list");
|
|
// }
|
|
|
|
// QtCommon::system->ApplySettings();
|
|
|
|
// // TODO
|
|
// // config->SaveAllValues();
|
|
// }
|
|
|
|
void GameListModel::RefreshGameDirectory()
|
|
{
|
|
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
|
|
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
|
|
populateAsync(UISettings::values.game_dirs);
|
|
}
|
|
}
|
|
|
|
void GameListModel::addEntry(QStandardItem *entry, const UISettings::GameDir &parent_dir) {
|
|
// TODO: Directory grouping
|
|
QString text = entry->data(GLMRoleTypes::NAME).toString();
|
|
QPixmap pixmap = entry->data(GLMRoleTypes::ICON).value<QPixmap>();
|
|
|
|
qDebug() << "Adding pixmap" << text;
|
|
m_provider->addPixmap(text, pixmap);
|
|
invisibleRootItem()->appendRow(entry);
|
|
}
|
|
|
|
// TODO
|
|
void GameListModel::addDirEntry(const UISettings::GameDir &dir) {}
|
|
|
|
// TODO
|
|
void GameListModel::donePopulating(QStringList watch_list) {
|
|
// emit ShowList(!empt());
|
|
|
|
// Clear out the old directories to watch for changes and add the new ones
|
|
auto watch_dirs = watcher->directories();
|
|
if (!watch_dirs.isEmpty()) {
|
|
watcher->removePaths(watch_dirs);
|
|
}
|
|
// Workaround: Add the watch paths in chunks to allow the gui to refresh
|
|
// This prevents the UI from stalling when a large number of watch paths are added
|
|
// Also artificially caps the watcher to a certain number of directories
|
|
constexpr int LIMIT_WATCH_DIRECTORIES = 5000;
|
|
constexpr int SLICE_SIZE = 25;
|
|
int len = (std::min)(static_cast<int>(watch_list.size()), LIMIT_WATCH_DIRECTORIES);
|
|
for (int i = 0; i < len; i += SLICE_SIZE) {
|
|
watcher->addPaths(watch_list.mid(i, i + SLICE_SIZE));
|
|
QGuiApplication::processEvents();
|
|
}
|
|
}
|
|
|
|
// TODO: Disable view
|
|
void GameListModel::populateAsync(QVector<UISettings::GameDir> &game_dirs) {
|
|
// Cancel any existing worker.
|
|
current_worker.reset();
|
|
|
|
/// clear image provider
|
|
m_provider->clear();
|
|
|
|
// Delete any rows that might already exist if we're repopulating
|
|
removeRows(0, rowCount());
|
|
|
|
current_worker = std::make_unique<GameListWorker>(game_dirs);
|
|
|
|
// Get events from the worker as data becomes available
|
|
connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameListModel::WorkerEvent,
|
|
Qt::QueuedConnection);
|
|
|
|
QThreadPool::globalInstance()->start(current_worker.get());
|
|
}
|
|
|
|
// Worker-related slots
|
|
void GameListModel::WorkerEvent() {
|
|
current_worker->ProcessEvents(this);
|
|
}
|