// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2024 A-La-Karte Contributors #include "gamemodel.h" #include GameModel::GameModel(QObject *parent) : QAbstractListModel(parent) { } int GameModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return m_filteredGames.count(); } QVariant GameModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= m_filteredGames.count()) { return {}; } Game *game = m_filteredGames.at(index.row()); switch (role) { case IdRole: return game->id(); case NameRole: case Qt::DisplayRole: return game->name(); case DescriptionRole: return game->description(); case DeveloperRole: return game->developer(); case PublisherRole: return game->publisher(); case CoverUrlRole: return game->coverUrl(); case IconUrlRole: return game->iconUrl(); case LaunchCommandRole: return game->launchCommand(); case PlatformRole: return game->platform(); case PlatformIdRole: return game->platformId(); case LastPlayedRole: return game->lastPlayed(); case PlayTimeRole: return game->playTime(); case FavoriteRole: return game->favorite(); case HiddenRole: return game->hidden(); case InstalledRole: return game->installed(); case RunningRole: return game->running(); case GameObjectRole: return QVariant::fromValue(game); } return {}; } bool GameModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || index.row() < 0 || index.row() >= m_filteredGames.count()) { return false; } Game *game = m_filteredGames.at(index.row()); switch (role) { case FavoriteRole: game->setFavorite(value.toBool()); break; case HiddenRole: game->setHidden(value.toBool()); break; default: return false; } Q_EMIT dataChanged(index, index, {role}); return true; } Qt::ItemFlags GameModel::flags(const QModelIndex &index) const { if (!index.isValid()) { return Qt::NoItemFlags; } return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; } QHash GameModel::roleNames() const { return {{IdRole, "gameId"}, {NameRole, "name"}, {DescriptionRole, "description"}, {DeveloperRole, "developer"}, {PublisherRole, "publisher"}, {CoverUrlRole, "coverUrl"}, {IconUrlRole, "iconUrl"}, {LaunchCommandRole, "launchCommand"}, {PlatformRole, "platform"}, {PlatformIdRole, "platformId"}, {LastPlayedRole, "lastPlayed"}, {PlayTimeRole, "playTime"}, {FavoriteRole, "favorite"}, {HiddenRole, "hidden"}, {InstalledRole, "installed"}, {RunningRole, "running"}, {GameObjectRole, "gameObject"}}; } int GameModel::count() const { return m_filteredGames.count(); } QString GameModel::filterText() const { return m_filterText; } void GameModel::setFilterText(const QString &text) { if (m_filterText != text) { m_filterText = text; applyFilter(); Q_EMIT filterTextChanged(); } } QString GameModel::filterPlatform() const { return m_filterPlatform; } void GameModel::setFilterPlatform(const QString &platform) { if (m_filterPlatform != platform) { m_filterPlatform = platform; applyFilter(); Q_EMIT filterPlatformChanged(); } } bool GameModel::showHidden() const { return m_showHidden; } void GameModel::setShowHidden(bool show) { if (m_showHidden != show) { m_showHidden = show; applyFilter(); Q_EMIT showHiddenChanged(); } } bool GameModel::favoritesOnly() const { return m_favoritesOnly; } void GameModel::setFavoritesOnly(bool favorites) { if (m_favoritesOnly != favorites) { m_favoritesOnly = favorites; applyFilter(); Q_EMIT favoritesOnlyChanged(); } } GameModel::SortMode GameModel::sortMode() const { return m_sortMode; } void GameModel::setSortMode(SortMode mode) { if (m_sortMode != mode) { m_sortMode = mode; applySort(); Q_EMIT sortModeChanged(); } } void GameModel::addGame(Game *game) { if (!game) return; // Check for duplicates for (Game *existing : m_games) { if (existing->platform() == game->platform() && existing->platformId() == game->platformId()) { delete game; return; } } game->setParent(this); beginInsertRows(QModelIndex(), m_games.count(), m_games.count()); m_games.append(game); endInsertRows(); applyFilter(); Q_EMIT countChanged(); } void GameModel::removeGame(const QString &id) { for (int i = 0; i < m_games.count(); ++i) { if (m_games.at(i)->id() == id) { int filteredIndex = m_filteredGames.indexOf(m_games.at(i)); if (filteredIndex >= 0) { beginRemoveRows(QModelIndex(), filteredIndex, filteredIndex); m_filteredGames.removeAt(filteredIndex); endRemoveRows(); } delete m_games.takeAt(i); Q_EMIT countChanged(); return; } } } Game *GameModel::gameAt(int index) const { if (index < 0 || index >= m_filteredGames.count()) { return nullptr; } return m_filteredGames.at(index); } Game *GameModel::gameById(const QString &id) const { for (Game *game : m_games) { if (game->id() == id) { return game; } } return nullptr; } void GameModel::clear() { beginResetModel(); qDeleteAll(m_games); m_games.clear(); m_filteredGames.clear(); endResetModel(); Q_EMIT countChanged(); } QStringList GameModel::platforms() const { QStringList result; for (Game *game : m_games) { if (!result.contains(game->platform())) { result.append(game->platform()); } } result.sort(); return result; } bool GameModel::matchesFilter(Game *game) const { if (!m_showHidden && game->hidden()) { return false; } if (m_favoritesOnly && !game->favorite()) { return false; } if (!m_filterPlatform.isEmpty() && game->platform() != m_filterPlatform) { return false; } if (!m_filterText.isEmpty()) { bool matches = game->name().contains(m_filterText, Qt::CaseInsensitive) || game->developer().contains(m_filterText, Qt::CaseInsensitive) || game->publisher().contains(m_filterText, Qt::CaseInsensitive); if (!matches) { return false; } } return true; } void GameModel::applyFilter() { beginResetModel(); m_filteredGames.clear(); for (Game *game : m_games) { if (matchesFilter(game)) { m_filteredGames.append(game); } } applySort(); endResetModel(); Q_EMIT countChanged(); } void GameModel::applySort() { std::sort(m_filteredGames.begin(), m_filteredGames.end(), [this](Game *a, Game *b) { // Favorites always first if (a->favorite() != b->favorite()) { return a->favorite(); } switch (m_sortMode) { case SortByName: return a->name().compare(b->name(), Qt::CaseInsensitive) < 0; case SortByLastPlayed: return a->lastPlayed() > b->lastPlayed(); case SortByPlayTime: return a->playTime() > b->playTime(); case SortByPlatform: if (a->platform() != b->platform()) { return a->platform() < b->platform(); } return a->name().compare(b->name(), Qt::CaseInsensitive) < 0; case SortByRecent: return a->lastPlayed() > b->lastPlayed(); } return false; }); }