mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	add icon & title to game list
This commit is contained in:
		
							parent
							
								
									73624b4721
								
							
						
					
					
						commit
						5d5dd66d92
					
				
					 9 changed files with 254 additions and 36 deletions
				
			
		|  | @ -34,8 +34,8 @@ GameList::GameList(QWidget* parent) | |||
|     tree_view->setUniformRowHeights(true); | ||||
| 
 | ||||
|     item_model->insertColumns(0, COLUMN_COUNT); | ||||
|     item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); | ||||
|     item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); | ||||
|     item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); | ||||
|     item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); | ||||
| 
 | ||||
|     connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, SLOT(ValidateEntry(const QModelIndex&))); | ||||
|  | @ -143,9 +143,15 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d | |||
|                 LOG_WARNING(Frontend, "Filetype and extension of file %s do not match.", physical_name.c_str()); | ||||
|             } | ||||
| 
 | ||||
|             std::vector<u8> smdh; | ||||
|             std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(FileUtil::IOFile(physical_name, "rb"), filetype, filename_filename, physical_name); | ||||
| 
 | ||||
|             if (loader) | ||||
|                 loader->ReadIcon(smdh); | ||||
| 
 | ||||
|             emit EntryReady({ | ||||
|                 new GameListItemPath(QString::fromStdString(physical_name), smdh), | ||||
|                 new GameListItem(QString::fromStdString(Loader::GetFileTypeString(filetype))), | ||||
|                 new GameListItemPath(QString::fromStdString(physical_name)), | ||||
|                 new GameListItemSize(FileUtil::GetSize(physical_name)), | ||||
|             }); | ||||
|         } | ||||
|  |  | |||
|  | @ -20,8 +20,8 @@ class GameList : public QWidget { | |||
| 
 | ||||
| public: | ||||
|     enum { | ||||
|         COLUMN_FILE_TYPE, | ||||
|         COLUMN_NAME, | ||||
|         COLUMN_FILE_TYPE, | ||||
|         COLUMN_SIZE, | ||||
|         COLUMN_COUNT, // Number of columns
 | ||||
|     }; | ||||
|  |  | |||
|  | @ -6,13 +6,85 @@ | |||
| 
 | ||||
| #include <atomic> | ||||
| 
 | ||||
| #include <QImage> | ||||
| #include <QRunnable> | ||||
| #include <QStandardItem> | ||||
| #include <QString> | ||||
| 
 | ||||
| #include "citra_qt/util/util.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/color.h" | ||||
| 
 | ||||
| #include "core/loader/loader.h" | ||||
| 
 | ||||
| #include "video_core/utils.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Tests if data is a valid SMDH by its length and magic number. | ||||
|  * @param smdh_data data buffer to test | ||||
|  * @return bool test result | ||||
|  */ | ||||
| static bool IsValidSMDH(const std::vector<u8>& smdh_data) { | ||||
|     if (smdh_data.size() < sizeof(Loader::SMDH)) | ||||
|         return false; | ||||
| 
 | ||||
|     u32 magic; | ||||
|     memcpy(&magic, smdh_data.data(), 4); | ||||
| 
 | ||||
|     return Loader::MakeMagic('S', 'M', 'D', 'H') == magic; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Gets game icon from SMDH | ||||
|  * @param sdmh SMDH data | ||||
|  * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) | ||||
|  * @return QPixmap game icon | ||||
|  */ | ||||
| static QPixmap GetIconFromSMDH(const Loader::SMDH& smdh, bool large) { | ||||
|     u32 size; | ||||
|     const u8* icon_data; | ||||
| 
 | ||||
|     if (large) { | ||||
|         size = 48; | ||||
|         icon_data = smdh.large_icon.data(); | ||||
|     } else { | ||||
|         size = 24; | ||||
|         icon_data = smdh.small_icon.data(); | ||||
|     } | ||||
| 
 | ||||
|     QImage icon(size, size, QImage::Format::Format_RGB888); | ||||
|     for (u32 x = 0; x < size; ++x) { | ||||
|         for (u32 y = 0; y < size; ++y) { | ||||
|             u32 coarse_y = y & ~7; | ||||
|             auto v = Color::DecodeRGB565( | ||||
|                 icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2); | ||||
|             icon.setPixel(x, y, qRgb(v.r(), v.g(), v.b())); | ||||
|         } | ||||
|     } | ||||
|     return QPixmap::fromImage(icon); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Gets the default icon (for games without valid SMDH) | ||||
|  * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) | ||||
|  * @return QPixmap default icon | ||||
|  */ | ||||
| static QPixmap GetDefaultIcon(bool large) { | ||||
|     int size = large ? 48 : 24; | ||||
|     QPixmap icon(size, size); | ||||
|     icon.fill(Qt::transparent); | ||||
|     return icon; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Gets the short game title fromn SMDH | ||||
|  * @param sdmh SMDH data | ||||
|  * @param language title language | ||||
|  * @return QString short title | ||||
|  */ | ||||
| static QString GetShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { | ||||
|     return QString::fromUtf16(smdh.titles[static_cast<int>(language)].short_title.data()); | ||||
| } | ||||
| 
 | ||||
| class GameListItem : public QStandardItem { | ||||
| 
 | ||||
|  | @ -27,29 +99,43 @@ public: | |||
|  * A specialization of GameListItem for path values. | ||||
|  * This class ensures that for every full path value it holds, a correct string representation | ||||
|  * of just the filename (with no extension) will be displayed to the user. | ||||
|  * If this class recieves valid SMDH data, it will also display game icons and titles. | ||||
|  */ | ||||
| class GameListItemPath : public GameListItem { | ||||
| 
 | ||||
| public: | ||||
|     static const int FullPathRole = Qt::UserRole + 1; | ||||
|     static const int TitleRole = Qt::UserRole + 2; | ||||
| 
 | ||||
|     GameListItemPath(): GameListItem() {} | ||||
|     GameListItemPath(const QString& game_path): GameListItem() | ||||
|     GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data): GameListItem() | ||||
|     { | ||||
|         setData(game_path, FullPathRole); | ||||
| 
 | ||||
|         if (!IsValidSMDH(smdh_data)) { | ||||
|             // SMDH is not valid, set a default icon
 | ||||
|             setData(GetDefaultIcon(true), Qt::DecorationRole); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         Loader::SMDH smdh; | ||||
|         memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); | ||||
| 
 | ||||
|         // Get icon from SMDH
 | ||||
|         setData(GetIconFromSMDH(smdh, true), Qt::DecorationRole); | ||||
| 
 | ||||
|         // Get title form SMDH
 | ||||
|         setData(GetShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); | ||||
|     } | ||||
| 
 | ||||
|     void setData(const QVariant& value, int role) override | ||||
|     { | ||||
|         // By specializing setData for FullPathRole, we can ensure that the two string
 | ||||
|         // representations of the data are always accurate and in the correct format.
 | ||||
|         if (role == FullPathRole) { | ||||
|     QVariant data(int role) const override { | ||||
|         if (role == Qt::DisplayRole) { | ||||
|             std::string filename; | ||||
|             Common::SplitPath(value.toString().toStdString(), nullptr, &filename, nullptr); | ||||
|             GameListItem::setData(QString::fromStdString(filename), Qt::DisplayRole); | ||||
|             GameListItem::setData(value, FullPathRole); | ||||
|             Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, nullptr); | ||||
|             QString title = data(TitleRole).toString(); | ||||
|             return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n    " + title); | ||||
|         } else { | ||||
|             GameListItem::setData(value, role); | ||||
|             return GameListItem::data(role); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue