mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-25 11:56:18 +00:00
Favorites in the game list (#2649) (#3071)
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / linux-qt-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / linux-qt-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
* Favorites in the game list (#2649) Changed how favorites are saved to match PR #2984. Adjusted the favorite icon size. Fixed bug where favorites were inconsistent when changing to list mode. Instantly sort list when adding or removing a favorite. Co-authored-by: David Antunes <david.f.antunes@tecnico.ulisboa.pt> * fix formatting * Favorites in the game list (#2649) Fixed issue where background change was inconsistent while adding favorites, unselect row when adding favorites, cleaned code, changed right click menu options to match the game's favorite status. * fixed right click bug * keep row selection when adding favorites * fixed sorting on game grid after using search bar * change the way favorites are saved to match #3119
This commit is contained in:
parent
669b19c2f3
commit
4bfa8c9fc7
10 changed files with 203 additions and 31 deletions
|
@ -7,8 +7,8 @@ path = [
|
||||||
"CMakeSettings.json",
|
"CMakeSettings.json",
|
||||||
".github/FUNDING.yml",
|
".github/FUNDING.yml",
|
||||||
".github/shadps4.png",
|
".github/shadps4.png",
|
||||||
".github/workflows/scripts/update_translation.sh",
|
".github/workflows/scripts/update_translation.sh",
|
||||||
".github/workflows/update_translation.yml",
|
".github/workflows/update_translation.yml",
|
||||||
".gitmodules",
|
".gitmodules",
|
||||||
"dist/MacOSBundleInfo.plist.in",
|
"dist/MacOSBundleInfo.plist.in",
|
||||||
"dist/net.shadps4.shadPS4.desktop",
|
"dist/net.shadps4.shadPS4.desktop",
|
||||||
|
@ -29,6 +29,7 @@ path = [
|
||||||
"src/images/discord.png",
|
"src/images/discord.png",
|
||||||
"src/images/dump_icon.png",
|
"src/images/dump_icon.png",
|
||||||
"src/images/exit_icon.png",
|
"src/images/exit_icon.png",
|
||||||
|
"src/images/favorite_icon.png",
|
||||||
"src/images/file_icon.png",
|
"src/images/file_icon.png",
|
||||||
"src/images/trophy_icon.png",
|
"src/images/trophy_icon.png",
|
||||||
"src/images/flag_china.png",
|
"src/images/flag_china.png",
|
||||||
|
@ -71,7 +72,7 @@ path = [
|
||||||
"src/images/youtube.svg",
|
"src/images/youtube.svg",
|
||||||
"src/shadps4.qrc",
|
"src/shadps4.qrc",
|
||||||
"src/shadps4.rc",
|
"src/shadps4.rc",
|
||||||
"src/qt_gui/translations/update_translation.sh",
|
"src/qt_gui/translations/update_translation.sh",
|
||||||
]
|
]
|
||||||
precedence = "aggregate"
|
precedence = "aggregate"
|
||||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||||
|
|
BIN
src/images/favorite_icon.png
Normal file
BIN
src/images/favorite_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -36,6 +36,7 @@ GameGridFrame::GameGridFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
|
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
|
||||||
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info,
|
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info,
|
||||||
m_gui_settings, this, false);
|
m_gui_settings, this, false);
|
||||||
|
PopulateGameGrid(m_game_info->m_games, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +90,13 @@ void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool from
|
||||||
this->crtColumn = -1;
|
this->crtColumn = -1;
|
||||||
QVector<GameInfo> m_games_;
|
QVector<GameInfo> m_games_;
|
||||||
this->clearContents();
|
this->clearContents();
|
||||||
if (fromSearch)
|
if (fromSearch) {
|
||||||
|
SortByFavorite(&m_games_search);
|
||||||
m_games_ = m_games_search;
|
m_games_ = m_games_search;
|
||||||
else
|
} else {
|
||||||
|
SortByFavorite(&(m_game_info->m_games));
|
||||||
m_games_ = m_game_info->m_games;
|
m_games_ = m_game_info->m_games;
|
||||||
|
}
|
||||||
m_games_shared = std::make_shared<QVector<GameInfo>>(m_games_);
|
m_games_shared = std::make_shared<QVector<GameInfo>>(m_games_);
|
||||||
icon_size =
|
icon_size =
|
||||||
m_gui_settings->GetValue(gui::gg_icon_size).toInt(); // update icon size for resize event.
|
m_gui_settings->GetValue(gui::gg_icon_size).toInt(); // update icon size for resize event.
|
||||||
|
@ -111,14 +115,21 @@ void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool from
|
||||||
for (int i = 0; i < m_games_.size(); i++) {
|
for (int i = 0; i < m_games_.size(); i++) {
|
||||||
QWidget* widget = new QWidget();
|
QWidget* widget = new QWidget();
|
||||||
QVBoxLayout* layout = new QVBoxLayout();
|
QVBoxLayout* layout = new QVBoxLayout();
|
||||||
QLabel* image_label = new QLabel();
|
|
||||||
|
QWidget* image_container = new QWidget();
|
||||||
|
image_container->setFixedSize(icon_size, icon_size);
|
||||||
|
|
||||||
|
QLabel* image_label = new QLabel(image_container);
|
||||||
QImage icon = m_games_[gameCounter].icon.scaled(
|
QImage icon = m_games_[gameCounter].icon.scaled(
|
||||||
QSize(icon_size, icon_size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
QSize(icon_size, icon_size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
image_label->setFixedSize(icon.width(), icon.height());
|
image_label->setFixedSize(icon.width(), icon.height());
|
||||||
image_label->setPixmap(QPixmap::fromImage(icon));
|
image_label->setPixmap(QPixmap::fromImage(icon));
|
||||||
|
image_label->move(0, 0);
|
||||||
|
SetFavoriteIcon(image_container, m_games_, gameCounter);
|
||||||
|
|
||||||
QLabel* name_label = new QLabel(QString::fromStdString(m_games_[gameCounter].serial));
|
QLabel* name_label = new QLabel(QString::fromStdString(m_games_[gameCounter].serial));
|
||||||
name_label->setAlignment(Qt::AlignHCenter);
|
name_label->setAlignment(Qt::AlignHCenter);
|
||||||
layout->addWidget(image_label);
|
layout->addWidget(image_container);
|
||||||
layout->addWidget(name_label);
|
layout->addWidget(name_label);
|
||||||
|
|
||||||
// Resizing of font-size.
|
// Resizing of font-size.
|
||||||
|
@ -226,3 +237,43 @@ void GameGridFrame::resizeEvent(QResizeEvent* event) {
|
||||||
bool GameGridFrame::IsValidCellSelected() {
|
bool GameGridFrame::IsValidCellSelected() {
|
||||||
return validCellSelected;
|
return validCellSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameGridFrame::SetFavoriteIcon(QWidget* parentWidget, QVector<GameInfo> m_games_,
|
||||||
|
int gameCounter) {
|
||||||
|
QString serialStr = QString::fromStdString(m_games_[gameCounter].serial);
|
||||||
|
QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::favorites_list));
|
||||||
|
bool isFavorite = list.contains(serialStr);
|
||||||
|
|
||||||
|
QLabel* label = new QLabel(parentWidget);
|
||||||
|
label->setPixmap(QPixmap(":images/favorite_icon.png")
|
||||||
|
.scaled(icon_size / 3.8, icon_size / 3.8, Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation));
|
||||||
|
label->move(icon_size - icon_size / 4, 2);
|
||||||
|
label->raise();
|
||||||
|
label->setVisible(isFavorite);
|
||||||
|
label->setObjectName("favoriteIcon");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameGridFrame::SortByFavorite(QVector<GameInfo>* game_list) {
|
||||||
|
std::sort(game_list->begin(), game_list->end(), [this](const GameInfo& a, const GameInfo& b) {
|
||||||
|
return this->CompareWithFavorite(a, b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameGridFrame::CompareWithFavorite(GameInfo a, GameInfo b) {
|
||||||
|
std::string serial_a = a.serial;
|
||||||
|
std::string serial_b = b.serial;
|
||||||
|
QString serialStr_a = QString::fromStdString(a.serial);
|
||||||
|
QString serialStr_b = QString::fromStdString(b.serial);
|
||||||
|
QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::favorites_list));
|
||||||
|
bool isFavorite_a = list.contains(serialStr_a);
|
||||||
|
bool isFavorite_b = list.contains(serialStr_b);
|
||||||
|
if (isFavorite_a != isFavorite_b) {
|
||||||
|
return isFavorite_a;
|
||||||
|
} else {
|
||||||
|
std::string name_a = a.name, name_b = b.name;
|
||||||
|
std::transform(name_a.begin(), name_a.end(), name_a.begin(), ::tolower);
|
||||||
|
std::transform(name_b.begin(), name_b.end(), name_b.begin(), ::tolower);
|
||||||
|
return name_a < name_b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ private:
|
||||||
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
|
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
|
||||||
std::filesystem::path m_current_game_path; // Track current game path to detect changes
|
std::filesystem::path m_current_game_path; // Track current game path to detect changes
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
void SetFavoriteIcon(QWidget* parentWidget, QVector<GameInfo> m_games_, int gameCounter);
|
||||||
|
bool CompareWithFavorite(GameInfo a, GameInfo b);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GameGridFrame(std::shared_ptr<gui_settings> gui_settings,
|
explicit GameGridFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
|
@ -47,6 +49,7 @@ public:
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
void PopulateGameGrid(QVector<GameInfo> m_games, bool fromSearch);
|
void PopulateGameGrid(QVector<GameInfo> m_games, bool fromSearch);
|
||||||
bool IsValidCellSelected();
|
bool IsValidCellSelected();
|
||||||
|
void SortByFavorite(QVector<GameInfo>* game_list);
|
||||||
|
|
||||||
bool cellClicked = false;
|
bool cellClicked = false;
|
||||||
int icon_size;
|
int icon_size;
|
||||||
|
|
|
@ -16,6 +16,7 @@ GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
: QTableWidget(parent), m_gui_settings(std::move(gui_settings)), m_game_info(game_info_get),
|
: QTableWidget(parent), m_gui_settings(std::move(gui_settings)), m_game_info(game_info_get),
|
||||||
m_compat_info(compat_info_get) {
|
m_compat_info(compat_info_get) {
|
||||||
icon_size = m_gui_settings->GetValue(gui::gl_icon_size).toInt();
|
icon_size = m_gui_settings->GetValue(gui::gl_icon_size).toInt();
|
||||||
|
last_favorite = "";
|
||||||
this->setShowGrid(false);
|
this->setShowGrid(false);
|
||||||
this->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
this->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
this->setSelectionBehavior(QAbstractItemView::SelectRows);
|
this->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
@ -30,9 +31,8 @@ GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
this->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
this->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
this->horizontalHeader()->setHighlightSections(false);
|
this->horizontalHeader()->setHighlightSections(false);
|
||||||
this->horizontalHeader()->setSortIndicatorShown(true);
|
this->horizontalHeader()->setSortIndicatorShown(true);
|
||||||
this->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
this->setColumnCount(10);
|
this->setColumnCount(11);
|
||||||
this->setColumnWidth(1, 300); // Name
|
this->setColumnWidth(1, 300); // Name
|
||||||
this->setColumnWidth(2, 140); // Compatibility
|
this->setColumnWidth(2, 140); // Compatibility
|
||||||
this->setColumnWidth(3, 120); // Serial
|
this->setColumnWidth(3, 120); // Serial
|
||||||
|
@ -41,14 +41,18 @@ GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
this->setColumnWidth(6, 90); // Size
|
this->setColumnWidth(6, 90); // Size
|
||||||
this->setColumnWidth(7, 90); // Version
|
this->setColumnWidth(7, 90); // Version
|
||||||
this->setColumnWidth(8, 120); // Play Time
|
this->setColumnWidth(8, 120); // Play Time
|
||||||
|
this->setColumnWidth(10, 90); // Favorite
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
headers << tr("Icon") << tr("Name") << tr("Compatibility") << tr("Serial") << tr("Region")
|
headers << tr("Icon") << tr("Name") << tr("Compatibility") << tr("Serial") << tr("Region")
|
||||||
<< tr("Firmware") << tr("Size") << tr("Version") << tr("Play Time") << tr("Path");
|
<< tr("Firmware") << tr("Size") << tr("Version") << tr("Play Time") << tr("Path")
|
||||||
|
<< tr("Favorite");
|
||||||
this->setHorizontalHeaderLabels(headers);
|
this->setHorizontalHeaderLabels(headers);
|
||||||
this->horizontalHeader()->setSortIndicatorShown(true);
|
this->horizontalHeader()->setSortIndicatorShown(true);
|
||||||
this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||||
this->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed);
|
this->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed);
|
||||||
this->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Fixed);
|
this->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Fixed);
|
||||||
|
this->horizontalHeader()->setSectionResizeMode(9, QHeaderView::Stretch);
|
||||||
|
this->horizontalHeader()->setSectionResizeMode(10, QHeaderView::Fixed);
|
||||||
PopulateGameList();
|
PopulateGameList();
|
||||||
|
|
||||||
connect(this, &QTableWidget::currentCellChanged, this, &GameListFrame::onCurrentCellChanged);
|
connect(this, &QTableWidget::currentCellChanged, this, &GameListFrame::onCurrentCellChanged);
|
||||||
|
@ -65,18 +69,24 @@ GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
SortNameDescending(columnIndex);
|
SortNameDescending(columnIndex);
|
||||||
this->horizontalHeader()->setSortIndicator(columnIndex, Qt::DescendingOrder);
|
this->horizontalHeader()->setSortIndicator(columnIndex, Qt::DescendingOrder);
|
||||||
ListSortedAsc = false;
|
ListSortedAsc = false;
|
||||||
|
sortColumn = columnIndex;
|
||||||
} else {
|
} else {
|
||||||
SortNameAscending(columnIndex);
|
SortNameAscending(columnIndex);
|
||||||
this->horizontalHeader()->setSortIndicator(columnIndex, Qt::AscendingOrder);
|
this->horizontalHeader()->setSortIndicator(columnIndex, Qt::AscendingOrder);
|
||||||
ListSortedAsc = true;
|
ListSortedAsc = true;
|
||||||
|
sortColumn = columnIndex;
|
||||||
}
|
}
|
||||||
this->clearContents();
|
this->clearContents();
|
||||||
PopulateGameList(false);
|
PopulateGameList(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
|
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
|
||||||
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info,
|
int changedFavorite = m_gui_context_menus.RequestGameMenu(
|
||||||
m_gui_settings, this, true);
|
pos, m_game_info->m_games, m_compat_info, m_gui_settings, this, true);
|
||||||
|
if (changedFavorite) {
|
||||||
|
last_favorite = m_game_info->m_games[this->currentRow()].serial;
|
||||||
|
PopulateGameList(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &QTableWidget::cellClicked, this, [=, this](int row, int column) {
|
connect(this, &QTableWidget::cellClicked, this, [=, this](int row, int column) {
|
||||||
|
@ -84,6 +94,19 @@ GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
|
||||||
auto url_issues = "https://github.com/shadps4-emu/shadps4-game-compatibility/issues/";
|
auto url_issues = "https://github.com/shadps4-emu/shadps4-game-compatibility/issues/";
|
||||||
QDesktopServices::openUrl(
|
QDesktopServices::openUrl(
|
||||||
QUrl(url_issues + m_game_info->m_games[row].compatibility.issue_number));
|
QUrl(url_issues + m_game_info->m_games[row].compatibility.issue_number));
|
||||||
|
} else if (column == 10) {
|
||||||
|
last_favorite = m_game_info->m_games[row].serial;
|
||||||
|
QString serialStr = QString::fromStdString(last_favorite);
|
||||||
|
QList<QString> list =
|
||||||
|
gui_settings::Var2List(m_gui_settings->GetValue(gui::favorites_list));
|
||||||
|
bool isFavorite = list.contains(serialStr);
|
||||||
|
if (isFavorite) {
|
||||||
|
list.removeOne(serialStr);
|
||||||
|
} else {
|
||||||
|
list.append(serialStr);
|
||||||
|
}
|
||||||
|
m_gui_settings->SetValue(gui::favorites_list, gui_settings::List2Var(list));
|
||||||
|
PopulateGameList(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -118,10 +141,7 @@ void GameListFrame::PopulateGameList(bool isInitialPopulation) {
|
||||||
this->setRowCount(m_game_info->m_games.size());
|
this->setRowCount(m_game_info->m_games.size());
|
||||||
ResizeIcons(icon_size);
|
ResizeIcons(icon_size);
|
||||||
|
|
||||||
if (isInitialPopulation) {
|
ApplyLastSorting(isInitialPopulation);
|
||||||
SortNameAscending(1); // Column 1 = Name
|
|
||||||
ResizeIcons(icon_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < m_game_info->m_games.size(); i++) {
|
for (int i = 0; i < m_game_info->m_games.size(); i++) {
|
||||||
SetTableItem(i, 1, QString::fromStdString(m_game_info->m_games[i].name));
|
SetTableItem(i, 1, QString::fromStdString(m_game_info->m_games[i].name));
|
||||||
|
@ -130,6 +150,11 @@ void GameListFrame::PopulateGameList(bool isInitialPopulation) {
|
||||||
SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].fw));
|
SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].fw));
|
||||||
SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].size));
|
SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].size));
|
||||||
SetTableItem(i, 7, QString::fromStdString(m_game_info->m_games[i].version));
|
SetTableItem(i, 7, QString::fromStdString(m_game_info->m_games[i].version));
|
||||||
|
SetFavoriteIcon(i, 10);
|
||||||
|
|
||||||
|
if (m_game_info->m_games[i].serial == last_favorite && !isInitialPopulation) {
|
||||||
|
this->setCurrentCell(i, 10);
|
||||||
|
}
|
||||||
|
|
||||||
m_game_info->m_games[i].compatibility =
|
m_game_info->m_games[i].compatibility =
|
||||||
m_compat_info->GetCompatibilityInfo(m_game_info->m_games[i].serial);
|
m_compat_info->GetCompatibilityInfo(m_game_info->m_games[i].serial);
|
||||||
|
@ -227,20 +252,50 @@ void GameListFrame::resizeEvent(QResizeEvent* event) {
|
||||||
RefreshListBackgroundImage();
|
RefreshListBackgroundImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameListFrame::CompareWithFavorite(GameInfo a, GameInfo b, int columnIndex, bool ascending) {
|
||||||
|
std::string serial_a = a.serial;
|
||||||
|
std::string serial_b = b.serial;
|
||||||
|
QString serialStr_a = QString::fromStdString(a.serial);
|
||||||
|
QString serialStr_b = QString::fromStdString(b.serial);
|
||||||
|
QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::favorites_list));
|
||||||
|
bool isFavorite_a = list.contains(serialStr_a);
|
||||||
|
bool isFavorite_b = list.contains(serialStr_b);
|
||||||
|
if (isFavorite_a != isFavorite_b) {
|
||||||
|
return isFavorite_a;
|
||||||
|
} else if (ascending) {
|
||||||
|
return CompareStringsAscending(a, b, columnIndex);
|
||||||
|
} else {
|
||||||
|
return CompareStringsDescending(a, b, columnIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GameListFrame::SortNameAscending(int columnIndex) {
|
void GameListFrame::SortNameAscending(int columnIndex) {
|
||||||
std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(),
|
std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(),
|
||||||
[columnIndex](const GameInfo& a, const GameInfo& b) {
|
[this, columnIndex](const GameInfo& a, const GameInfo& b) {
|
||||||
return CompareStringsAscending(a, b, columnIndex);
|
return this->CompareWithFavorite(a, b, columnIndex, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameListFrame::SortNameDescending(int columnIndex) {
|
void GameListFrame::SortNameDescending(int columnIndex) {
|
||||||
std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(),
|
std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(),
|
||||||
[columnIndex](const GameInfo& a, const GameInfo& b) {
|
[this, columnIndex](const GameInfo& a, const GameInfo& b) {
|
||||||
return CompareStringsDescending(a, b, columnIndex);
|
return this->CompareWithFavorite(a, b, columnIndex, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameListFrame::ApplyLastSorting(bool isInitialPopulation) {
|
||||||
|
if (isInitialPopulation) {
|
||||||
|
SortNameAscending(1); // Column 1 = Name
|
||||||
|
ResizeIcons(icon_size);
|
||||||
|
} else if (ListSortedAsc) {
|
||||||
|
SortNameAscending(sortColumn);
|
||||||
|
ResizeIcons(icon_size);
|
||||||
|
} else {
|
||||||
|
SortNameDescending(sortColumn);
|
||||||
|
ResizeIcons(icon_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GameListFrame::ResizeIcons(int iconSize) {
|
void GameListFrame::ResizeIcons(int iconSize) {
|
||||||
for (int index = 0; auto& game : m_game_info->m_games) {
|
for (int index = 0; auto& game : m_game_info->m_games) {
|
||||||
QImage scaledPixmap = game.icon.scaled(QSize(iconSize, iconSize), Qt::KeepAspectRatio,
|
QImage scaledPixmap = game.icon.scaled(QSize(iconSize, iconSize), Qt::KeepAspectRatio,
|
||||||
|
@ -391,6 +446,35 @@ void GameListFrame::SetRegionFlag(int row, int column, QString itemStr) {
|
||||||
this->setCellWidget(row, column, widget);
|
this->setCellWidget(row, column, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameListFrame::SetFavoriteIcon(int row, int column) {
|
||||||
|
|
||||||
|
QString serialStr = QString::fromStdString(m_game_info->m_games[row].serial);
|
||||||
|
QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::favorites_list));
|
||||||
|
bool isFavorite = list.contains(serialStr);
|
||||||
|
|
||||||
|
QTableWidgetItem* item = new QTableWidgetItem();
|
||||||
|
QImage scaledPixmap = QImage(":images/favorite_icon.png");
|
||||||
|
|
||||||
|
scaledPixmap = scaledPixmap.scaledToHeight(this->columnWidth(column) / 2.5);
|
||||||
|
scaledPixmap = scaledPixmap.scaledToWidth(this->columnWidth(column) / 2.5);
|
||||||
|
QWidget* widget = new QWidget(this);
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(widget);
|
||||||
|
QLabel* label = new QLabel(widget);
|
||||||
|
label->setPixmap(QPixmap::fromImage(scaledPixmap));
|
||||||
|
label->setObjectName("favoriteIcon");
|
||||||
|
label->setVisible(isFavorite);
|
||||||
|
|
||||||
|
layout->setAlignment(Qt::AlignCenter);
|
||||||
|
layout->addWidget(label);
|
||||||
|
widget->setLayout(layout);
|
||||||
|
this->setItem(row, column, item);
|
||||||
|
this->setCellWidget(row, column, widget);
|
||||||
|
|
||||||
|
if (column > 0) {
|
||||||
|
this->horizontalHeader()->setSectionResizeMode(column - 1, QHeaderView::Stretch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString GameListFrame::GetPlayTime(const std::string& serial) {
|
QString GameListFrame::GetPlayTime(const std::string& serial) {
|
||||||
QString playTime;
|
QString playTime;
|
||||||
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||||
|
|
|
@ -42,11 +42,13 @@ public Q_SLOTS:
|
||||||
private:
|
private:
|
||||||
void SetTableItem(int row, int column, QString itemStr);
|
void SetTableItem(int row, int column, QString itemStr);
|
||||||
void SetRegionFlag(int row, int column, QString itemStr);
|
void SetRegionFlag(int row, int column, QString itemStr);
|
||||||
|
void SetFavoriteIcon(int row, int column);
|
||||||
void SetCompatibilityItem(int row, int column, CompatibilityEntry entry);
|
void SetCompatibilityItem(int row, int column, CompatibilityEntry entry);
|
||||||
QString GetPlayTime(const std::string& serial);
|
QString GetPlayTime(const std::string& serial);
|
||||||
QList<QAction*> m_columnActs;
|
QList<QAction*> m_columnActs;
|
||||||
GameInfoClass* game_inf_get = nullptr;
|
GameInfoClass* game_inf_get = nullptr;
|
||||||
bool ListSortedAsc = true;
|
bool ListSortedAsc = true;
|
||||||
|
int sortColumn = 1;
|
||||||
QTableWidgetItem* m_current_item = nullptr;
|
QTableWidgetItem* m_current_item = nullptr;
|
||||||
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
|
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
|
||||||
std::filesystem::path m_current_game_path; // Track current game path to detect changes
|
std::filesystem::path m_current_game_path; // Track current game path to detect changes
|
||||||
|
@ -55,6 +57,7 @@ private:
|
||||||
public:
|
public:
|
||||||
void PopulateGameList(bool isInitialPopulation = true);
|
void PopulateGameList(bool isInitialPopulation = true);
|
||||||
void ResizeIcons(int iconSize);
|
void ResizeIcons(int iconSize);
|
||||||
|
void ApplyLastSorting(bool isInitialPopulation);
|
||||||
QTableWidgetItem* GetCurrentItem();
|
QTableWidgetItem* GetCurrentItem();
|
||||||
QImage backgroundImage;
|
QImage backgroundImage;
|
||||||
GameListUtils m_game_list_utils;
|
GameListUtils m_game_list_utils;
|
||||||
|
@ -63,6 +66,7 @@ public:
|
||||||
std::shared_ptr<CompatibilityInfoClass> m_compat_info;
|
std::shared_ptr<CompatibilityInfoClass> m_compat_info;
|
||||||
|
|
||||||
int icon_size;
|
int icon_size;
|
||||||
|
std::string last_favorite;
|
||||||
|
|
||||||
static float parseAsFloat(const std::string& str, const int& offset) {
|
static float parseAsFloat(const std::string& str, const int& offset) {
|
||||||
return std::stof(str.substr(0, str.size() - offset));
|
return std::stof(str.substr(0, str.size() - offset));
|
||||||
|
@ -130,4 +134,6 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CompareWithFavorite(GameInfo a, GameInfo b, int columnIndex, bool ascending);
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "compatibility_info.h"
|
#include "compatibility_info.h"
|
||||||
#include "game_info.h"
|
#include "game_info.h"
|
||||||
|
#include "gui_settings.h"
|
||||||
#include "trophy_viewer.h"
|
#include "trophy_viewer.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -30,13 +31,13 @@
|
||||||
class GuiContextMenus : public QObject {
|
class GuiContextMenus : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
void RequestGameMenu(const QPoint& pos, QVector<GameInfo>& m_games,
|
int RequestGameMenu(const QPoint& pos, QVector<GameInfo>& m_games,
|
||||||
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
|
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
|
||||||
std::shared_ptr<gui_settings> settings, QTableWidget* widget,
|
std::shared_ptr<gui_settings> settings, QTableWidget* widget, bool isList) {
|
||||||
bool isList) {
|
|
||||||
QPoint global_pos = widget->viewport()->mapToGlobal(pos);
|
QPoint global_pos = widget->viewport()->mapToGlobal(pos);
|
||||||
std::shared_ptr<gui_settings> m_gui_settings = std::move(settings);
|
std::shared_ptr<gui_settings> m_gui_settings = std::move(settings);
|
||||||
int itemID = 0;
|
int itemID = 0;
|
||||||
|
int changedFavorite = 0;
|
||||||
if (isList) {
|
if (isList) {
|
||||||
itemID = widget->currentRow();
|
itemID = widget->currentRow();
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,7 +46,7 @@ public:
|
||||||
|
|
||||||
// Do not show the menu if no item is selected
|
// Do not show the menu if no item is selected
|
||||||
if (itemID < 0 || itemID >= m_games.size()) {
|
if (itemID < 0 || itemID >= m_games.size()) {
|
||||||
return;
|
return changedFavorite;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup menu.
|
// Setup menu.
|
||||||
|
@ -65,11 +66,22 @@ public:
|
||||||
|
|
||||||
menu.addMenu(openFolderMenu);
|
menu.addMenu(openFolderMenu);
|
||||||
|
|
||||||
|
QString serialStr = QString::fromStdString(m_games[itemID].serial);
|
||||||
|
QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::favorites_list));
|
||||||
|
bool isFavorite = list.contains(serialStr);
|
||||||
|
QAction* toggleFavorite;
|
||||||
|
|
||||||
|
if (isFavorite) {
|
||||||
|
toggleFavorite = new QAction(tr("Remove from Favorites"), widget);
|
||||||
|
} else {
|
||||||
|
toggleFavorite = new QAction(tr("Add to Favorites"), widget);
|
||||||
|
}
|
||||||
QAction createShortcut(tr("Create Shortcut"), widget);
|
QAction createShortcut(tr("Create Shortcut"), widget);
|
||||||
QAction openCheats(tr("Cheats / Patches"), widget);
|
QAction openCheats(tr("Cheats / Patches"), widget);
|
||||||
QAction openSfoViewer(tr("SFO Viewer"), widget);
|
QAction openSfoViewer(tr("SFO Viewer"), widget);
|
||||||
QAction openTrophyViewer(tr("Trophy Viewer"), widget);
|
QAction openTrophyViewer(tr("Trophy Viewer"), widget);
|
||||||
|
|
||||||
|
menu.addAction(toggleFavorite);
|
||||||
menu.addAction(&createShortcut);
|
menu.addAction(&createShortcut);
|
||||||
menu.addAction(&openCheats);
|
menu.addAction(&openCheats);
|
||||||
menu.addAction(&openSfoViewer);
|
menu.addAction(&openSfoViewer);
|
||||||
|
@ -130,7 +142,7 @@ public:
|
||||||
// Show menu.
|
// Show menu.
|
||||||
auto selected = menu.exec(global_pos);
|
auto selected = menu.exec(global_pos);
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
return;
|
return changedFavorite;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected == openGameFolder) {
|
if (selected == openGameFolder) {
|
||||||
|
@ -303,6 +315,16 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selected == toggleFavorite) {
|
||||||
|
if (isFavorite) {
|
||||||
|
list.removeOne(serialStr);
|
||||||
|
} else {
|
||||||
|
list.append(serialStr);
|
||||||
|
}
|
||||||
|
m_gui_settings->SetValue(gui::favorites_list, gui_settings::List2Var(list));
|
||||||
|
changedFavorite = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (selected == &openCheats) {
|
if (selected == &openCheats) {
|
||||||
QString gameName = QString::fromStdString(m_games[itemID].name);
|
QString gameName = QString::fromStdString(m_games[itemID].name);
|
||||||
QString gameSerial = QString::fromStdString(m_games[itemID].serial);
|
QString gameSerial = QString::fromStdString(m_games[itemID].serial);
|
||||||
|
@ -588,6 +610,7 @@ public:
|
||||||
QUrl(url_issues + m_games[itemID].compatibility.issue_number));
|
QUrl(url_issues + m_games[itemID].compatibility.issue_number));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return changedFavorite;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) {
|
int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ const QString general_settings = "general_settings";
|
||||||
const QString main_window = "main_window";
|
const QString main_window = "main_window";
|
||||||
const QString game_list = "game_list";
|
const QString game_list = "game_list";
|
||||||
const QString game_grid = "game_grid";
|
const QString game_grid = "game_grid";
|
||||||
|
const QString favorites = "favorites";
|
||||||
|
|
||||||
// general
|
// general
|
||||||
const gui_value gen_checkForUpdates = gui_value(general_settings, "checkForUpdates", false);
|
const gui_value gen_checkForUpdates = gui_value(general_settings, "checkForUpdates", false);
|
||||||
|
@ -41,6 +42,10 @@ const gui_value gl_backgroundMusicVolume = gui_value(game_list, "backgroundMusic
|
||||||
const gui_value gg_icon_size = gui_value(game_grid, "icon_size", 69);
|
const gui_value gg_icon_size = gui_value(game_grid, "icon_size", 69);
|
||||||
const gui_value gg_slider_pos = gui_value(game_grid, "slider_pos", 0);
|
const gui_value gg_slider_pos = gui_value(game_grid, "slider_pos", 0);
|
||||||
|
|
||||||
|
// favorites list
|
||||||
|
const gui_value favorites_list =
|
||||||
|
gui_value(favorites, "favoritesList", QVariant::fromValue(QList<QString>()));
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|
||||||
class gui_settings : public settings {
|
class gui_settings : public settings {
|
||||||
|
|
|
@ -561,10 +561,8 @@ void MainWindow::CreateConnects() {
|
||||||
m_game_grid_frame->hide();
|
m_game_grid_frame->hide();
|
||||||
m_elf_viewer->hide();
|
m_elf_viewer->hide();
|
||||||
m_game_list_frame->show();
|
m_game_list_frame->show();
|
||||||
if (m_game_list_frame->item(0, 0) == nullptr) {
|
m_game_list_frame->clearContents();
|
||||||
m_game_list_frame->clearContents();
|
m_game_list_frame->PopulateGameList();
|
||||||
m_game_list_frame->PopulateGameList();
|
|
||||||
}
|
|
||||||
isTableList = true;
|
isTableList = true;
|
||||||
m_gui_settings->SetValue(gui::gl_mode, 0);
|
m_gui_settings->SetValue(gui::gl_mode, 0);
|
||||||
int slider_pos = m_gui_settings->GetValue(gui::gl_slider_pos).toInt();
|
int slider_pos = m_gui_settings->GetValue(gui::gl_slider_pos).toInt();
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
<file>images/KBM.png</file>
|
<file>images/KBM.png</file>
|
||||||
<file>images/fullscreen_icon.png</file>
|
<file>images/fullscreen_icon.png</file>
|
||||||
<file>images/refreshlist_icon.png</file>
|
<file>images/refreshlist_icon.png</file>
|
||||||
|
<file>images/favorite_icon.png</file>
|
||||||
<file>images/trophy_icon.png</file>
|
<file>images/trophy_icon.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue