game_list_p.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <atomic>
  6. #include <QImage>
  7. #include <QRunnable>
  8. #include <QStandardItem>
  9. #include <QString>
  10. #include "citra_qt/util/util.h"
  11. #include "common/string_util.h"
  12. #include "common/color.h"
  13. #include "core/loader/smdh.h"
  14. #include "video_core/utils.h"
  15. /**
  16. * Gets game icon from SMDH
  17. * @param sdmh SMDH data
  18. * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
  19. * @return QPixmap game icon
  20. */
  21. static QPixmap GetQPixmapFromSMDH(const Loader::SMDH& smdh, bool large) {
  22. std::vector<u16> icon_data = smdh.GetIcon(large);
  23. const uchar* data = reinterpret_cast<const uchar*>(icon_data.data());
  24. int size = large ? 48 : 24;
  25. QImage icon(data, size, size, QImage::Format::Format_RGB16);
  26. return QPixmap::fromImage(icon);
  27. }
  28. /**
  29. * Gets the default icon (for games without valid SMDH)
  30. * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
  31. * @return QPixmap default icon
  32. */
  33. static QPixmap GetDefaultIcon(bool large) {
  34. int size = large ? 48 : 24;
  35. QPixmap icon(size, size);
  36. icon.fill(Qt::transparent);
  37. return icon;
  38. }
  39. /**
  40. * Gets the short game title fromn SMDH
  41. * @param sdmh SMDH data
  42. * @param language title language
  43. * @return QString short title
  44. */
  45. static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) {
  46. return QString::fromUtf16(smdh.GetShortTitle(language).data());
  47. }
  48. class GameListItem : public QStandardItem {
  49. public:
  50. GameListItem(): QStandardItem() {}
  51. GameListItem(const QString& string): QStandardItem(string) {}
  52. virtual ~GameListItem() override {}
  53. };
  54. /**
  55. * A specialization of GameListItem for path values.
  56. * This class ensures that for every full path value it holds, a correct string representation
  57. * of just the filename (with no extension) will be displayed to the user.
  58. * If this class recieves valid SMDH data, it will also display game icons and titles.
  59. */
  60. class GameListItemPath : public GameListItem {
  61. public:
  62. static const int FullPathRole = Qt::UserRole + 1;
  63. static const int TitleRole = Qt::UserRole + 2;
  64. GameListItemPath(): GameListItem() {}
  65. GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data): GameListItem()
  66. {
  67. setData(game_path, FullPathRole);
  68. if (!Loader::IsValidSMDH(smdh_data)) {
  69. // SMDH is not valid, set a default icon
  70. setData(GetDefaultIcon(true), Qt::DecorationRole);
  71. return;
  72. }
  73. Loader::SMDH smdh;
  74. memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
  75. // Get icon from SMDH
  76. setData(GetQPixmapFromSMDH(smdh, true), Qt::DecorationRole);
  77. // Get title form SMDH
  78. setData(GetQStringShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole);
  79. }
  80. QVariant data(int role) const override {
  81. if (role == Qt::DisplayRole) {
  82. std::string filename;
  83. Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, nullptr);
  84. QString title = data(TitleRole).toString();
  85. return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title);
  86. } else {
  87. return GameListItem::data(role);
  88. }
  89. }
  90. };
  91. /**
  92. * A specialization of GameListItem for size values.
  93. * This class ensures that for every numerical size value it holds (in bytes), a correct
  94. * human-readable string representation will be displayed to the user.
  95. */
  96. class GameListItemSize : public GameListItem {
  97. public:
  98. static const int SizeRole = Qt::UserRole + 1;
  99. GameListItemSize(): GameListItem() {}
  100. GameListItemSize(const qulonglong size_bytes): GameListItem()
  101. {
  102. setData(size_bytes, SizeRole);
  103. }
  104. void setData(const QVariant& value, int role) override
  105. {
  106. // By specializing setData for SizeRole, we can ensure that the numerical and string
  107. // representations of the data are always accurate and in the correct format.
  108. if (role == SizeRole) {
  109. qulonglong size_bytes = value.toULongLong();
  110. GameListItem::setData(ReadableByteSize(size_bytes), Qt::DisplayRole);
  111. GameListItem::setData(value, SizeRole);
  112. } else {
  113. GameListItem::setData(value, role);
  114. }
  115. }
  116. /**
  117. * This operator is, in practice, only used by the TreeView sorting systems.
  118. * Override it so that it will correctly sort by numerical value instead of by string representation.
  119. */
  120. bool operator<(const QStandardItem& other) const override
  121. {
  122. return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong();
  123. }
  124. };
  125. /**
  126. * Asynchronous worker object for populating the game list.
  127. * Communicates with other threads through Qt's signal/slot system.
  128. */
  129. class GameListWorker : public QObject, public QRunnable {
  130. Q_OBJECT
  131. public:
  132. GameListWorker(QString dir_path, bool deep_scan):
  133. QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan) {}
  134. public slots:
  135. /// Starts the processing of directory tree information.
  136. void run() override;
  137. /// Tells the worker that it should no longer continue processing. Thread-safe.
  138. void Cancel();
  139. signals:
  140. /**
  141. * The `EntryReady` signal is emitted once an entry has been prepared and is ready
  142. * to be added to the game list.
  143. * @param entry_items a list with `QStandardItem`s that make up the columns of the new entry.
  144. */
  145. void EntryReady(QList<QStandardItem*> entry_items);
  146. void Finished();
  147. private:
  148. QString dir_path;
  149. bool deep_scan;
  150. std::atomic_bool stop_processing;
  151. void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0);
  152. };