mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #3463 from FearlessTobi/game-list-compat
citra-qt: Show Game Compatibility within Citra
This commit is contained in:
		
						commit
						a2ab91fa31
					
				
					 11 changed files with 153 additions and 11 deletions
				
			
		|  | @ -20,7 +20,7 @@ echo y | sh cmake-3.10.1-Linux-x86_64.sh --prefix=cmake | ||||||
| export PATH=/citra/cmake/cmake-3.10.1-Linux-x86_64/bin:$PATH | export PATH=/citra/cmake/cmake-3.10.1-Linux-x86_64/bin:$PATH | ||||||
| 
 | 
 | ||||||
| mkdir build && cd build | mkdir build && cd build | ||||||
| cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON | ||||||
| make -j4 | make -j4 | ||||||
| 
 | 
 | ||||||
| ctest -VV -C Release | ctest -VV -C Release | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ echo y | sh cmake-3.10.1-Linux-x86_64.sh --prefix=cmake | ||||||
| export PATH=/citra/cmake/cmake-3.10.1-Linux-x86_64/bin:$PATH | export PATH=/citra/cmake/cmake-3.10.1-Linux-x86_64/bin:$PATH | ||||||
| 
 | 
 | ||||||
| mkdir build && cd build | mkdir build && cd build | ||||||
| cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON | ||||||
| make -j4 | make -j4 | ||||||
| 
 | 
 | ||||||
| ctest -VV -C Release | ctest -VV -C Release | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ export Qt5_DIR=$(brew --prefix)/opt/qt5 | ||||||
| export PATH="/usr/local/opt/ccache/libexec:$PATH" | export PATH="/usr/local/opt/ccache/libexec:$PATH" | ||||||
| 
 | 
 | ||||||
| mkdir build && cd build | mkdir build && cd build | ||||||
| cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} | cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON | ||||||
| make -j4 | make -j4 | ||||||
| 
 | 
 | ||||||
| ctest -VV -C Release | ctest -VV -C Release | ||||||
|  |  | ||||||
|  | @ -40,6 +40,22 @@ function(check_submodules_present) | ||||||
| endfunction() | endfunction() | ||||||
| check_submodules_present() | check_submodules_present() | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | configure_file(${CMAKE_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc | ||||||
|  |                ${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc | ||||||
|  |                COPYONLY) | ||||||
|  | 
 | ||||||
|  | if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) | ||||||
|  |     message(STATUS "Downloading compatibility list for citra...") | ||||||
|  |     file(DOWNLOAD | ||||||
|  |         https://api.citra-emu.org/gamedb/titleid/ | ||||||
|  |         "${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (NOT EXISTS ${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) | ||||||
|  |     file(WRITE ${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.json "") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| # Detect current compilation architecture and create standard definitions | # Detect current compilation architecture and create standard definitions | ||||||
| # ======================================================================= | # ======================================================================= | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -43,9 +43,9 @@ before_build: | ||||||
|         $COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING} |         $COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING} | ||||||
|         if ($env:BUILD_TYPE -eq 'msvc') { |         if ($env:BUILD_TYPE -eq 'msvc') { | ||||||
|           # redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning |           # redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning | ||||||
|           cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} .. 2>&1 && exit 0' |           cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON .. 2>&1 && exit 0' | ||||||
|         } else { |         } else { | ||||||
|           C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} .. 2>&1" |           C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON .. 2>&1" | ||||||
|         } |         } | ||||||
|   - cd .. |   - cd .. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								dist/compatibility_list/compatibility_list.qrc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								dist/compatibility_list/compatibility_list.qrc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | <RCC> | ||||||
|  |   <qresource prefix="compatibility_list"> | ||||||
|  |       <file>compatibility_list.json</file> | ||||||
|  |   </qresource> | ||||||
|  | </RCC> | ||||||
|  | @ -85,6 +85,9 @@ set(UIS | ||||||
|     compatdb.ui |     compatdb.ui | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | file(GLOB COMPAT_LIST | ||||||
|  |             ${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc | ||||||
|  |             ${CMAKE_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) | ||||||
| file(GLOB_RECURSE ICONS ${CMAKE_SOURCE_DIR}/dist/icons/*) | file(GLOB_RECURSE ICONS ${CMAKE_SOURCE_DIR}/dist/icons/*) | ||||||
| file(GLOB_RECURSE THEMES ${CMAKE_SOURCE_DIR}/dist/qt_themes/*) | file(GLOB_RECURSE THEMES ${CMAKE_SOURCE_DIR}/dist/qt_themes/*) | ||||||
| 
 | 
 | ||||||
|  | @ -125,6 +128,7 @@ endif() | ||||||
| 
 | 
 | ||||||
| target_sources(citra-qt | target_sources(citra-qt | ||||||
|     PRIVATE |     PRIVATE | ||||||
|  |         ${COMPAT_LIST} | ||||||
|         ${ICONS} |         ${ICONS} | ||||||
|         ${THEMES} |         ${THEMES} | ||||||
|         ${UI_HDRS} |         ${UI_HDRS} | ||||||
|  |  | ||||||
|  | @ -2,11 +2,14 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <cinttypes> | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| #include <QFileInfo> | #include <QFileInfo> | ||||||
| #include <QFileSystemWatcher> | #include <QFileSystemWatcher> | ||||||
| #include <QHBoxLayout> | #include <QHBoxLayout> | ||||||
| #include <QHeaderView> | #include <QHeaderView> | ||||||
|  | #include <QJsonDocument> | ||||||
|  | #include <QJsonObject> | ||||||
| #include <QKeyEvent> | #include <QKeyEvent> | ||||||
| #include <QLabel> | #include <QLabel> | ||||||
| #include <QLineEdit> | #include <QLineEdit> | ||||||
|  | @ -227,6 +230,7 @@ GameList::GameList(GMainWindow* parent) : QWidget{parent} { | ||||||
| 
 | 
 | ||||||
|     item_model->insertColumns(0, COLUMN_COUNT); |     item_model->insertColumns(0, COLUMN_COUNT); | ||||||
|     item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); |     item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); | ||||||
|  |     item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, "Compatibility"); | ||||||
|     item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); |     item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); | ||||||
|     item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); |     item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); | ||||||
| 
 | 
 | ||||||
|  | @ -337,6 +341,39 @@ void GameList::PopupContextMenu(const QPoint& menu_location) { | ||||||
|     context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); |     context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void GameList::LoadCompatibilityList() { | ||||||
|  |     QFile compat_list{":compatibility_list/compatibility_list.json"}; | ||||||
|  | 
 | ||||||
|  |     if (!compat_list.open(QFile::ReadOnly | QFile::Text)) { | ||||||
|  |         NGLOG_ERROR(Frontend, "Unable to open game compatibility list"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (compat_list.size() == 0) { | ||||||
|  |         NGLOG_ERROR(Frontend, "Game compatibility list is empty"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const QByteArray content = compat_list.readAll(); | ||||||
|  |     if (content.isEmpty()) { | ||||||
|  |         NGLOG_ERROR(Frontend, "Unable to completely read game compatibility list"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const QString string_content = content; | ||||||
|  |     QJsonDocument json = QJsonDocument::fromJson(string_content.toUtf8()); | ||||||
|  |     QJsonObject list = json.object(); | ||||||
|  |     QStringList game_ids = list.keys(); | ||||||
|  |     for (QString id : game_ids) { | ||||||
|  |         QJsonObject game = list[id].toObject(); | ||||||
|  | 
 | ||||||
|  |         if (game.contains("compatibility") && game["compatibility"].isString()) { | ||||||
|  |             QString compatibility = game["compatibility"].toString(); | ||||||
|  |             compatibility_list.insert(std::make_pair(id.toUpper().toStdString(), compatibility)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { | void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { | ||||||
|     if (!FileUtil::Exists(dir_path.toStdString()) || |     if (!FileUtil::Exists(dir_path.toStdString()) || | ||||||
|         !FileUtil::IsDirectory(dir_path.toStdString())) { |         !FileUtil::IsDirectory(dir_path.toStdString())) { | ||||||
|  | @ -351,7 +388,7 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { | ||||||
| 
 | 
 | ||||||
|     emit ShouldCancelWorker(); |     emit ShouldCancelWorker(); | ||||||
| 
 | 
 | ||||||
|     GameListWorker* worker = new GameListWorker(dir_path, deep_scan); |     GameListWorker* worker = new GameListWorker(dir_path, deep_scan, compatibility_list); | ||||||
| 
 | 
 | ||||||
|     connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection); |     connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection); | ||||||
|     connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating, |     connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating, | ||||||
|  | @ -436,8 +473,21 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | ||||||
|                 return update_smdh; |                 return update_smdh; | ||||||
|             }(); |             }(); | ||||||
| 
 | 
 | ||||||
|  |             auto it = std::find_if(compatibility_list.begin(), compatibility_list.end(), | ||||||
|  |                                    [program_id](const std::pair<std::string, QString>& element) { | ||||||
|  |                                        std::string pid = | ||||||
|  |                                            Common::StringFromFormat("%016" PRIX64, program_id); | ||||||
|  |                                        return element.first == pid; | ||||||
|  |                                    }); | ||||||
|  | 
 | ||||||
|  |             // The game list uses this as compatibility number for untested games
 | ||||||
|  |             QString compatibility("99"); | ||||||
|  |             if (it != compatibility_list.end()) | ||||||
|  |                 compatibility = it->second; | ||||||
|  | 
 | ||||||
|             emit EntryReady({ |             emit EntryReady({ | ||||||
|                 new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id), |                 new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id), | ||||||
|  |                 new GameListItemCompat(compatibility), | ||||||
|                 new GameListItem( |                 new GameListItem( | ||||||
|                     QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), |                     QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), | ||||||
|                 new GameListItemSize(FileUtil::GetSize(physical_name)), |                 new GameListItemSize(FileUtil::GetSize(physical_name)), | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <unordered_map> | ||||||
| #include <QString> | #include <QString> | ||||||
| #include <QWidget> | #include <QWidget> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | @ -29,6 +30,7 @@ class GameList : public QWidget { | ||||||
| public: | public: | ||||||
|     enum { |     enum { | ||||||
|         COLUMN_NAME, |         COLUMN_NAME, | ||||||
|  |         COLUMN_COMPATIBILITY, | ||||||
|         COLUMN_FILE_TYPE, |         COLUMN_FILE_TYPE, | ||||||
|         COLUMN_SIZE, |         COLUMN_SIZE, | ||||||
|         COLUMN_COUNT, // Number of columns
 |         COLUMN_COUNT, // Number of columns
 | ||||||
|  | @ -68,6 +70,7 @@ public: | ||||||
|     void setFilterFocus(); |     void setFilterFocus(); | ||||||
|     void setFilterVisible(bool visibility); |     void setFilterVisible(bool visibility); | ||||||
| 
 | 
 | ||||||
|  |     void LoadCompatibilityList(); | ||||||
|     void PopulateAsync(const QString& dir_path, bool deep_scan); |     void PopulateAsync(const QString& dir_path, bool deep_scan); | ||||||
| 
 | 
 | ||||||
|     void SaveInterfaceLayout(); |     void SaveInterfaceLayout(); | ||||||
|  | @ -100,6 +103,7 @@ private: | ||||||
|     QStandardItemModel* item_model = nullptr; |     QStandardItemModel* item_model = nullptr; | ||||||
|     GameListWorker* current_worker = nullptr; |     GameListWorker* current_worker = nullptr; | ||||||
|     QFileSystemWatcher* watcher = nullptr; |     QFileSystemWatcher* watcher = nullptr; | ||||||
|  |     std::unordered_map<std::string, QString> compatibility_list; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Q_DECLARE_METATYPE(GameListOpenTarget); | Q_DECLARE_METATYPE(GameListOpenTarget); | ||||||
|  |  | ||||||
|  | @ -5,11 +5,16 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <atomic> | #include <atomic> | ||||||
|  | #include <map> | ||||||
|  | #include <unordered_map> | ||||||
| #include <QImage> | #include <QImage> | ||||||
|  | #include <QObject> | ||||||
|  | #include <QPainter> | ||||||
| #include <QRunnable> | #include <QRunnable> | ||||||
| #include <QStandardItem> | #include <QStandardItem> | ||||||
| #include <QString> | #include <QString> | ||||||
| #include "citra_qt/util/util.h" | #include "citra_qt/util/util.h" | ||||||
|  | #include "common/logging/log.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/loader/smdh.h" | #include "core/loader/smdh.h" | ||||||
| 
 | 
 | ||||||
|  | @ -39,6 +44,23 @@ static QPixmap GetDefaultIcon(bool large) { | ||||||
|     return icon; |     return icon; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Creates a circle pixmap from a specified color | ||||||
|  |  * @param color The color the pixmap shall have | ||||||
|  |  * @return QPixmap circle pixmap | ||||||
|  |  */ | ||||||
|  | static QPixmap CreateCirclePixmapFromColor(const QColor& color) { | ||||||
|  |     QPixmap circle_pixmap(16, 16); | ||||||
|  |     circle_pixmap.fill(Qt::transparent); | ||||||
|  | 
 | ||||||
|  |     QPainter painter(&circle_pixmap); | ||||||
|  |     painter.setPen(color); | ||||||
|  |     painter.setBrush(color); | ||||||
|  |     painter.drawEllipse(0, 0, 15, 15); | ||||||
|  | 
 | ||||||
|  |     return circle_pixmap; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Gets the short game title from SMDH data. |  * Gets the short game title from SMDH data. | ||||||
|  * @param smdh SMDH data |  * @param smdh SMDH data | ||||||
|  | @ -50,8 +72,25 @@ static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, | ||||||
|     return QString::fromUtf16(smdh.GetShortTitle(language).data()); |     return QString::fromUtf16(smdh.GetShortTitle(language).data()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class GameListItem : public QStandardItem { | struct CompatStatus { | ||||||
|  |     QString color; | ||||||
|  |     QString text; | ||||||
|  |     QString tooltip; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
|  | // When this is put in a class, MSVS builds crash when closing Citra
 | ||||||
|  | // clang-format off
 | ||||||
|  | const static inline std::map<QString, CompatStatus> status_data = { | ||||||
|  | { "0", { "#5c93ed", GameList::tr("Perfect"),    GameList::tr("Game functions flawless with no audio or graphical glitches, all tested functionality works as intended without\nany workarounds needed.") } }, | ||||||
|  | { "1", { "#47d35c", GameList::tr("Great"),      GameList::tr("Game functions with minor graphical or audio glitches and is playable from start to finish. May require some\nworkarounds.") } }, | ||||||
|  | { "2", { "#94b242", GameList::tr("Okay"),       GameList::tr("Game functions with major graphical or audio glitches, but game is playable from start to finish with\nworkarounds.") } }, | ||||||
|  | { "3", { "#f2d624", GameList::tr("Bad"),        GameList::tr("Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches\neven with workarounds.") } }, | ||||||
|  | { "4", { "#FF0000", GameList::tr("Intro/Menu"), GameList::tr("Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start\nScreen.") } }, | ||||||
|  | { "5", { "#828282", GameList::tr("Won't Boot"), GameList::tr("The game crashes when attempting to startup.") } }, | ||||||
|  | { "99",{ "#000000", GameList::tr("Not Tested"), GameList::tr("The game has not yet been tested.") } }, }; | ||||||
|  | // clang-format on
 | ||||||
|  | 
 | ||||||
|  | class GameListItem : public QStandardItem { | ||||||
| public: | public: | ||||||
|     GameListItem() : QStandardItem() {} |     GameListItem() : QStandardItem() {} | ||||||
|     GameListItem(const QString& string) : QStandardItem(string) {} |     GameListItem(const QString& string) : QStandardItem(string) {} | ||||||
|  | @ -65,7 +104,6 @@ public: | ||||||
|  * If this class receives valid SMDH data, it will also display game icons and titles. |  * If this class receives valid SMDH data, it will also display game icons and titles. | ||||||
|  */ |  */ | ||||||
| class GameListItemPath : public GameListItem { | class GameListItemPath : public GameListItem { | ||||||
| 
 |  | ||||||
| public: | public: | ||||||
|     static const int FullPathRole = Qt::UserRole + 1; |     static const int FullPathRole = Qt::UserRole + 1; | ||||||
|     static const int TitleRole = Qt::UserRole + 2; |     static const int TitleRole = Qt::UserRole + 2; | ||||||
|  | @ -107,13 +145,34 @@ public: | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | class GameListItemCompat : public GameListItem { | ||||||
|  | public: | ||||||
|  |     static const int CompatNumberRole = Qt::UserRole + 1; | ||||||
|  |     GameListItemCompat() = default; | ||||||
|  |     explicit GameListItemCompat(const QString compatiblity) { | ||||||
|  |         auto iterator = status_data.find(compatiblity); | ||||||
|  |         if (iterator == status_data.end()) { | ||||||
|  |             NGLOG_WARNING(Frontend, "Invalid compatibility number {}", compatiblity.toStdString()); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         CompatStatus status = iterator->second; | ||||||
|  |         setData(compatiblity, CompatNumberRole); | ||||||
|  |         setText(status.text); | ||||||
|  |         setToolTip(status.tooltip); | ||||||
|  |         setData(CreateCirclePixmapFromColor(status.color), Qt::DecorationRole); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool operator<(const QStandardItem& other) const override { | ||||||
|  |         return data(CompatNumberRole) < other.data(CompatNumberRole); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A specialization of GameListItem for size values. |  * A specialization of GameListItem for size values. | ||||||
|  * This class ensures that for every numerical size value it holds (in bytes), a correct |  * This class ensures that for every numerical size value it holds (in bytes), a correct | ||||||
|  * human-readable string representation will be displayed to the user. |  * human-readable string representation will be displayed to the user. | ||||||
|  */ |  */ | ||||||
| class GameListItemSize : public GameListItem { | class GameListItemSize : public GameListItem { | ||||||
| 
 |  | ||||||
| public: | public: | ||||||
|     static const int SizeRole = Qt::UserRole + 1; |     static const int SizeRole = Qt::UserRole + 1; | ||||||
| 
 | 
 | ||||||
|  | @ -152,8 +211,10 @@ class GameListWorker : public QObject, public QRunnable { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     GameListWorker(QString dir_path, bool deep_scan) |     GameListWorker(QString dir_path, bool deep_scan, | ||||||
|         : QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan) {} |                    const std::unordered_map<std::string, QString>& compatibility_list) | ||||||
|  |         : QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan), | ||||||
|  |           compatibility_list(compatibility_list) {} | ||||||
| 
 | 
 | ||||||
| public slots: | public slots: | ||||||
|     /// Starts the processing of directory tree information.
 |     /// Starts the processing of directory tree information.
 | ||||||
|  | @ -179,6 +240,7 @@ private: | ||||||
|     QStringList watch_list; |     QStringList watch_list; | ||||||
|     QString dir_path; |     QString dir_path; | ||||||
|     bool deep_scan; |     bool deep_scan; | ||||||
|  |     const std::unordered_map<std::string, QString>& compatibility_list; | ||||||
|     std::atomic_bool stop_processing; |     std::atomic_bool stop_processing; | ||||||
| 
 | 
 | ||||||
|     void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0); |     void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0); | ||||||
|  |  | ||||||
|  | @ -131,6 +131,7 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { | ||||||
| 
 | 
 | ||||||
|     show(); |     show(); | ||||||
| 
 | 
 | ||||||
|  |     game_list->LoadCompatibilityList(); | ||||||
|     game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); |     game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); | ||||||
| 
 | 
 | ||||||
|     // Show one-time "callout" messages to the user
 |     // Show one-time "callout" messages to the user
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue