game_list: Mark games as favorite to make them appear at the top
Co-Authored-By: Colin E. <5352197+Kewlan@users.noreply.github.com>
This commit is contained in:
parent
fdc29d05d5
commit
1d1b66fe4e
16 changed files with 159 additions and 5 deletions
3
dist/license.md
vendored
3
dist/license.md
vendored
|
@ -15,6 +15,7 @@ qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/default/icons/48x48/no_avatar.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/default/icons/48x48/no_avatar.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||||
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
qt_themes/default/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/16x16/connected_notification.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/16x16/connected_notification.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/16x16/disconnected.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/16x16/disconnected.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
@ -26,6 +27,7 @@ qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/48x48/no_avatar.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/48x48/no_avatar.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||||
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
qt_themes/qdarkstyle/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/16x16/connected_notification.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/16x16/connected_notification.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/16x16/disconnected.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/16x16/disconnected.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
@ -36,6 +38,7 @@ qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/48x48/plus.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/48x48/plus.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
qt_themes/colorful/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful_dark/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful_dark/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
|
||||||
<!-- TODO (B3N30): Add the license of the citra icon -->
|
<!-- TODO (B3N30): Add the license of the citra icon -->
|
||||||
|
|
BIN
dist/qt_themes/colorful/icons/48x48/star.png
vendored
Normal file
BIN
dist/qt_themes/colorful/icons/48x48/star.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
1
dist/qt_themes/colorful/style.qrc
vendored
1
dist/qt_themes/colorful/style.qrc
vendored
|
@ -10,6 +10,7 @@
|
||||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="colorful">
|
<qresource prefix="colorful">
|
||||||
|
|
1
dist/qt_themes/colorful_dark/style.qrc
vendored
1
dist/qt_themes/colorful_dark/style.qrc
vendored
|
@ -11,6 +11,7 @@
|
||||||
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
|
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
|
||||||
<file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">../colorful/icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
||||||
|
|
1
dist/qt_themes/default/default.qrc
vendored
1
dist/qt_themes/default/default.qrc
vendored
|
@ -13,6 +13,7 @@
|
||||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/citra.png">icons/256x256/citra.png</file>
|
<file alias="256x256/citra.png">icons/256x256/citra.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
BIN
dist/qt_themes/default/icons/48x48/star.png
vendored
Normal file
BIN
dist/qt_themes/default/icons/48x48/star.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
BIN
dist/qt_themes/qdarkstyle/icons/48x48/star.png
vendored
Normal file
BIN
dist/qt_themes/qdarkstyle/icons/48x48/star.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
1
dist/qt_themes/qdarkstyle/style.qrc
vendored
1
dist/qt_themes/qdarkstyle/style.qrc
vendored
|
@ -11,6 +11,7 @@
|
||||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="qss_icons">
|
<qresource prefix="qss_icons">
|
||||||
|
|
BIN
dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png
vendored
Normal file
BIN
dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 725 B |
|
@ -11,6 +11,7 @@
|
||||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="qss_icons">
|
<qresource prefix="qss_icons">
|
||||||
|
|
|
@ -356,3 +356,4 @@ folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
plus.png (Default, Dark) | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
plus.png (Default, Dark) | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||||
plus.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
plus.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||||
sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
|
|
@ -791,6 +791,14 @@ void Config::ReadUIGameListValues() {
|
||||||
ReadBasicSetting(UISettings::values.show_type_column);
|
ReadBasicSetting(UISettings::values.show_type_column);
|
||||||
ReadBasicSetting(UISettings::values.show_size_column);
|
ReadBasicSetting(UISettings::values.show_size_column);
|
||||||
|
|
||||||
|
const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites"));
|
||||||
|
for (int i = 0; i < favorites_size; i++) {
|
||||||
|
qt_config->setArrayIndex(i);
|
||||||
|
UISettings::values.favorited_ids.append(
|
||||||
|
ReadSetting(QStringLiteral("program_id")).toULongLong());
|
||||||
|
}
|
||||||
|
qt_config->endArray();
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1265,6 +1273,14 @@ void Config::SaveUIGameListValues() {
|
||||||
WriteBasicSetting(UISettings::values.show_type_column);
|
WriteBasicSetting(UISettings::values.show_type_column);
|
||||||
WriteBasicSetting(UISettings::values.show_size_column);
|
WriteBasicSetting(UISettings::values.show_size_column);
|
||||||
|
|
||||||
|
qt_config->beginWriteArray(QStringLiteral("favorites"));
|
||||||
|
for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
|
||||||
|
qt_config->setArrayIndex(i);
|
||||||
|
WriteSetting(QStringLiteral("program_id"),
|
||||||
|
QVariant::fromValue(UISettings::values.favorited_ids[i]));
|
||||||
|
}
|
||||||
|
qt_config->endArray();
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QList>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
|
@ -105,6 +106,10 @@ void GameListSearchField::setFilterResult(int visible, int total) {
|
||||||
QStringLiteral("%1 %2 %3 %4").arg(visible).arg(result_of_text).arg(total).arg(result_text));
|
QStringLiteral("%1 %2 %3 %4").arg(visible).arg(result_of_text).arg(total).arg(result_text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameListSearchField::IsEmpty() const {
|
||||||
|
return edit_filter->text().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
QString GameList::GetLastFilterResultItem() const {
|
QString GameList::GetLastFilterResultItem() const {
|
||||||
QString file_path;
|
QString file_path;
|
||||||
const int folderCount = item_model->rowCount();
|
const int folderCount = item_model->rowCount();
|
||||||
|
@ -206,7 +211,9 @@ void GameList::OnTextChanged(const QString& new_text) {
|
||||||
// If the searchfield is empty every item is visible
|
// If the searchfield is empty every item is visible
|
||||||
// Otherwise the filter gets applied
|
// Otherwise the filter gets applied
|
||||||
if (edit_filter_text.isEmpty()) {
|
if (edit_filter_text.isEmpty()) {
|
||||||
for (int i = 0; i < folder_count; ++i) {
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
|
||||||
|
UISettings::values.favorited_ids.size() == 0);
|
||||||
|
for (int i = 1; i < folder_count; ++i) {
|
||||||
folder = item_model->item(i, 0);
|
folder = item_model->item(i, 0);
|
||||||
const QModelIndex folder_index = folder->index();
|
const QModelIndex folder_index = folder->index();
|
||||||
const int children_count = folder->rowCount();
|
const int children_count = folder->rowCount();
|
||||||
|
@ -217,8 +224,9 @@ void GameList::OnTextChanged(const QString& new_text) {
|
||||||
}
|
}
|
||||||
search_field->setFilterResult(children_total, children_total);
|
search_field->setFilterResult(children_total, children_total);
|
||||||
} else {
|
} else {
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
|
||||||
int result_count = 0;
|
int result_count = 0;
|
||||||
for (int i = 0; i < folder_count; ++i) {
|
for (int i = 1; i < folder_count; ++i) {
|
||||||
folder = item_model->item(i, 0);
|
folder = item_model->item(i, 0);
|
||||||
const QModelIndex folder_index = folder->index();
|
const QModelIndex folder_index = folder->index();
|
||||||
const int children_count = folder->rowCount();
|
const int children_count = folder->rowCount();
|
||||||
|
@ -281,6 +289,13 @@ void GameList::OnUpdateThemedIcons() {
|
||||||
child->setData(QIcon::fromTheme(QStringLiteral("plus")).pixmap(icon_size),
|
child->setData(QIcon::fromTheme(QStringLiteral("plus")).pixmap(icon_size),
|
||||||
Qt::DecorationRole);
|
Qt::DecorationRole);
|
||||||
break;
|
break;
|
||||||
|
case GameListItemType::Favorites:
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(QStringLiteral("star"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -422,6 +437,15 @@ void GameList::DonePopulating(const QStringList& watch_list) {
|
||||||
|
|
||||||
item_model->invisibleRootItem()->appendRow(new GameListAddDir());
|
item_model->invisibleRootItem()->appendRow(new GameListAddDir());
|
||||||
|
|
||||||
|
// Add favorites row
|
||||||
|
item_model->invisibleRootItem()->insertRow(0, new GameListFavorites());
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
|
||||||
|
UISettings::values.favorited_ids.size() == 0);
|
||||||
|
tree_view->expand(item_model->invisibleRootItem()->child(0)->index());
|
||||||
|
for (const auto id : UISettings::values.favorited_ids) {
|
||||||
|
AddFavorite(id);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear out the old directories to watch for changes and add the new ones
|
// Clear out the old directories to watch for changes and add the new ones
|
||||||
auto watch_dirs = watcher->directories();
|
auto watch_dirs = watcher->directories();
|
||||||
if (!watch_dirs.isEmpty()) {
|
if (!watch_dirs.isEmpty()) {
|
||||||
|
@ -440,7 +464,7 @@ void GameList::DonePopulating(const QStringList& watch_list) {
|
||||||
tree_view->setEnabled(true);
|
tree_view->setEnabled(true);
|
||||||
const int folderCount = tree_view->model()->rowCount();
|
const int folderCount = tree_view->model()->rowCount();
|
||||||
int children_total = 0;
|
int children_total = 0;
|
||||||
for (int i = 0; i < folderCount; ++i) {
|
for (int i = 1; i < folderCount; ++i) {
|
||||||
children_total += item_model->item(i, 0)->rowCount();
|
children_total += item_model->item(i, 0)->rowCount();
|
||||||
}
|
}
|
||||||
search_field->setFilterResult(children_total, children_total);
|
search_field->setFilterResult(children_total, children_total);
|
||||||
|
@ -477,6 +501,9 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
|
||||||
case GameListItemType::SystemDir:
|
case GameListItemType::SystemDir:
|
||||||
AddPermDirPopup(context_menu, selected);
|
AddPermDirPopup(context_menu, selected);
|
||||||
break;
|
break;
|
||||||
|
case GameListItemType::Favorites:
|
||||||
|
AddFavoritesPopup(context_menu);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -533,6 +560,8 @@ void ForEachOpenGLCacheFile(u64 program_id, auto func) {
|
||||||
|
|
||||||
void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QString& name,
|
void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QString& name,
|
||||||
u64 program_id, u64 extdata_id, Service::FS::MediaType media_type) {
|
u64 program_id, u64 extdata_id, Service::FS::MediaType media_type) {
|
||||||
|
QAction* favorite = context_menu.addAction(tr("Favorite"));
|
||||||
|
context_menu.addSeparator();
|
||||||
QMenu* open_menu = context_menu.addMenu(tr("Open"));
|
QMenu* open_menu = context_menu.addMenu(tr("Open"));
|
||||||
QAction* open_application_location = open_menu->addAction(tr("Application Location"));
|
QAction* open_application_location = open_menu->addAction(tr("Application Location"));
|
||||||
open_menu->addSeparator();
|
open_menu->addSeparator();
|
||||||
|
@ -577,6 +606,10 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QStr
|
||||||
program_id, [&opengl_cache_exists](QFile& file) { opengl_cache_exists |= file.exists(); });
|
program_id, [&opengl_cache_exists](QFile& file) { opengl_cache_exists |= file.exists(); });
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
favorite->setVisible(program_id != 0);
|
||||||
|
favorite->setCheckable(true);
|
||||||
|
favorite->setChecked(UISettings::values.favorited_ids.contains(program_id));
|
||||||
|
|
||||||
std::string sdmc_dir = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir);
|
std::string sdmc_dir = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir);
|
||||||
open_save_location->setEnabled(
|
open_save_location->setEnabled(
|
||||||
is_application && FileUtil::Exists(FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor(
|
is_application && FileUtil::Exists(FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor(
|
||||||
|
@ -624,6 +657,7 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QStr
|
||||||
auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
|
auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
|
||||||
navigate_to_gamedb_entry->setVisible(it != compatibility_list.end());
|
navigate_to_gamedb_entry->setVisible(it != compatibility_list.end());
|
||||||
|
|
||||||
|
connect(favorite, &QAction::triggered, [this, program_id]() { ToggleFavorite(program_id); });
|
||||||
connect(open_save_location, &QAction::triggered, this, [this, program_id] {
|
connect(open_save_location, &QAction::triggered, this, [this, program_id] {
|
||||||
emit OpenFolderRequested(program_id, GameListOpenTarget::SAVE_DATA);
|
emit OpenFolderRequested(program_id, GameListOpenTarget::SAVE_DATA);
|
||||||
});
|
});
|
||||||
|
@ -774,7 +808,7 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
|
||||||
|
|
||||||
const int row = selected.row();
|
const int row = selected.row();
|
||||||
|
|
||||||
move_up->setEnabled(row > 0);
|
move_up->setEnabled(row > 1);
|
||||||
move_down->setEnabled(row < item_model->rowCount() - 2);
|
move_down->setEnabled(row < item_model->rowCount() - 2);
|
||||||
|
|
||||||
connect(move_up, &QAction::triggered, this, [this, selected, row, game_dir_index] {
|
connect(move_up, &QAction::triggered, this, [this, selected, row, game_dir_index] {
|
||||||
|
@ -812,6 +846,18 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameList::AddFavoritesPopup(QMenu& context_menu) {
|
||||||
|
QAction* clear = context_menu.addAction(tr("Clear"));
|
||||||
|
|
||||||
|
connect(clear, &QAction::triggered, [this] {
|
||||||
|
for (const auto id : UISettings::values.favorited_ids) {
|
||||||
|
RemoveFavorite(id);
|
||||||
|
}
|
||||||
|
UISettings::values.favorited_ids.clear();
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void GameList::LoadCompatibilityList() {
|
void GameList::LoadCompatibilityList() {
|
||||||
QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
|
QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
|
||||||
|
|
||||||
|
@ -944,6 +990,58 @@ void GameList::RefreshGameDirectory() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameList::ToggleFavorite(u64 program_id) {
|
||||||
|
if (!UISettings::values.favorited_ids.contains(program_id)) {
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
|
||||||
|
!search_field->IsEmpty());
|
||||||
|
UISettings::values.favorited_ids.append(program_id);
|
||||||
|
AddFavorite(program_id);
|
||||||
|
item_model->sort(tree_view->header()->sortIndicatorSection(),
|
||||||
|
tree_view->header()->sortIndicatorOrder());
|
||||||
|
} else {
|
||||||
|
UISettings::values.favorited_ids.removeOne(program_id);
|
||||||
|
RemoveFavorite(program_id);
|
||||||
|
if (UISettings::values.favorited_ids.size() == 0) {
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::AddFavorite(u64 program_id) {
|
||||||
|
auto* favorites_row = item_model->item(0);
|
||||||
|
|
||||||
|
for (int i = 1; i < item_model->rowCount() - 1; i++) {
|
||||||
|
const auto* folder = item_model->item(i);
|
||||||
|
for (int j = 0; j < folder->rowCount(); j++) {
|
||||||
|
if (folder->child(j)->data(GameListItemPath::ProgramIdRole).toULongLong() ==
|
||||||
|
program_id) {
|
||||||
|
QList<QStandardItem*> list;
|
||||||
|
for (int k = 0; k < COLUMN_COUNT; k++) {
|
||||||
|
list.append(folder->child(j, k)->clone());
|
||||||
|
}
|
||||||
|
list[0]->setData(folder->child(j)->data(GameListItem::SortRole),
|
||||||
|
GameListItem::SortRole);
|
||||||
|
list[0]->setText(folder->child(j)->data(Qt::DisplayRole).toString());
|
||||||
|
|
||||||
|
favorites_row->appendRow(list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::RemoveFavorite(u64 program_id) {
|
||||||
|
auto* favorites_row = item_model->item(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < favorites_row->rowCount(); i++) {
|
||||||
|
const auto* game = favorites_row->child(i);
|
||||||
|
if (game->data(GameListItemPath::ProgramIdRole).toULongLong() == program_id) {
|
||||||
|
favorites_row->removeRow(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString GameList::FindGameByProgramID(u64 program_id, int role) {
|
QString GameList::FindGameByProgramID(u64 program_id, int role) {
|
||||||
return FindGameByProgramID(item_model->invisibleRootItem(), program_id, role);
|
return FindGameByProgramID(item_model->invisibleRootItem(), program_id, role);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,10 @@ public:
|
||||||
|
|
||||||
void RefreshGameDirectory();
|
void RefreshGameDirectory();
|
||||||
|
|
||||||
|
void ToggleFavorite(u64 program_id);
|
||||||
|
void AddFavorite(u64 program_id);
|
||||||
|
void RemoveFavorite(u64 program_id);
|
||||||
|
|
||||||
static const QStringList supported_file_extensions;
|
static const QStringList supported_file_extensions;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -113,6 +117,7 @@ private:
|
||||||
u64 extdata_id, Service::FS::MediaType media_type);
|
u64 extdata_id, Service::FS::MediaType media_type);
|
||||||
void AddCustomDirPopup(QMenu& context_menu, QModelIndex selected);
|
void AddCustomDirPopup(QMenu& context_menu, QModelIndex selected);
|
||||||
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
|
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
|
||||||
|
void AddFavoritesPopup(QMenu& context_menu);
|
||||||
void UpdateColumnVisibility();
|
void UpdateColumnVisibility();
|
||||||
|
|
||||||
QString FindGameByProgramID(QStandardItem* current_item, u64 program_id, int role);
|
QString FindGameByProgramID(QStandardItem* current_item, u64 program_id, int role);
|
||||||
|
|
|
@ -34,7 +34,8 @@ enum class GameListItemType {
|
||||||
CustomDir = QStandardItem::UserType + 2,
|
CustomDir = QStandardItem::UserType + 2,
|
||||||
InstalledDir = QStandardItem::UserType + 3,
|
InstalledDir = QStandardItem::UserType + 3,
|
||||||
SystemDir = QStandardItem::UserType + 4,
|
SystemDir = QStandardItem::UserType + 4,
|
||||||
AddDir = QStandardItem::UserType + 5
|
AddDir = QStandardItem::UserType + 5,
|
||||||
|
Favorites = QStandardItem::UserType + 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(GameListItemType);
|
Q_DECLARE_METATYPE(GameListItemType);
|
||||||
|
@ -430,6 +431,28 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GameListFavorites : public GameListItem {
|
||||||
|
public:
|
||||||
|
explicit GameListFavorites() {
|
||||||
|
setData(type(), TypeRole);
|
||||||
|
|
||||||
|
const int icon_size = IconSizes.at(UISettings::values.game_list_icon_size.GetValue());
|
||||||
|
setData(QIcon::fromTheme(QStringLiteral("star"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
setData(QObject::tr("Favorites"), Qt::DisplayRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
int type() const override {
|
||||||
|
return static_cast<int>(GameListItemType::Favorites);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const QStandardItem& other) const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class GameList;
|
class GameList;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
|
@ -444,6 +467,7 @@ public:
|
||||||
explicit GameListSearchField(GameList* parent = nullptr);
|
explicit GameListSearchField(GameList* parent = nullptr);
|
||||||
|
|
||||||
void setFilterResult(int visible, int total);
|
void setFilterResult(int visible, int total);
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
void setFocus();
|
void setFocus();
|
||||||
|
|
|
@ -116,6 +116,8 @@ struct Values {
|
||||||
bool game_dir_deprecated_deepscan;
|
bool game_dir_deprecated_deepscan;
|
||||||
QVector<UISettings::GameDir> game_dirs;
|
QVector<UISettings::GameDir> game_dirs;
|
||||||
QStringList recent_files;
|
QStringList recent_files;
|
||||||
|
QVector<u64> favorited_ids;
|
||||||
|
|
||||||
QString language;
|
QString language;
|
||||||
|
|
||||||
QString theme;
|
QString theme;
|
||||||
|
|
Loading…
Reference in a new issue