game_list_p.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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 "common/string_util.h"
  11. #include "yuzu/util/util.h"
  12. /**
  13. * Gets the default icon (for games without valid SMDH)
  14. * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
  15. * @return QPixmap default icon
  16. */
  17. static QPixmap GetDefaultIcon(bool large) {
  18. int size = large ? 48 : 24;
  19. QPixmap icon(size, size);
  20. icon.fill(Qt::transparent);
  21. return icon;
  22. }
  23. class GameListItem : public QStandardItem {
  24. public:
  25. GameListItem() : QStandardItem() {}
  26. GameListItem(const QString& string) : QStandardItem(string) {}
  27. virtual ~GameListItem() override {}
  28. };
  29. /**
  30. * A specialization of GameListItem for path values.
  31. * This class ensures that for every full path value it holds, a correct string representation
  32. * of just the filename (with no extension) will be displayed to the user.
  33. * If this class receives valid SMDH data, it will also display game icons and titles.
  34. */
  35. class GameListItemPath : public GameListItem {
  36. public:
  37. static const int FullPathRole = Qt::UserRole + 1;
  38. static const int TitleRole = Qt::UserRole + 2;
  39. static const int ProgramIdRole = Qt::UserRole + 3;
  40. GameListItemPath() : GameListItem() {}
  41. GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id)
  42. : GameListItem() {
  43. setData(game_path, FullPathRole);
  44. setData(qulonglong(program_id), ProgramIdRole);
  45. }
  46. QVariant data(int role) const override {
  47. if (role == Qt::DisplayRole) {
  48. std::string filename;
  49. Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename,
  50. nullptr);
  51. QString title = data(TitleRole).toString();
  52. return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title);
  53. } else {
  54. return GameListItem::data(role);
  55. }
  56. }
  57. };
  58. /**
  59. * A specialization of GameListItem for size values.
  60. * This class ensures that for every numerical size value it holds (in bytes), a correct
  61. * human-readable string representation will be displayed to the user.
  62. */
  63. class GameListItemSize : public GameListItem {
  64. public:
  65. static const int SizeRole = Qt::UserRole + 1;
  66. GameListItemSize() : GameListItem() {}
  67. GameListItemSize(const qulonglong size_bytes) : GameListItem() {
  68. setData(size_bytes, SizeRole);
  69. }
  70. void setData(const QVariant& value, int role) override {
  71. // By specializing setData for SizeRole, we can ensure that the numerical and string
  72. // representations of the data are always accurate and in the correct format.
  73. if (role == SizeRole) {
  74. qulonglong size_bytes = value.toULongLong();
  75. GameListItem::setData(ReadableByteSize(size_bytes), Qt::DisplayRole);
  76. GameListItem::setData(value, SizeRole);
  77. } else {
  78. GameListItem::setData(value, role);
  79. }
  80. }
  81. /**
  82. * This operator is, in practice, only used by the TreeView sorting systems.
  83. * Override it so that it will correctly sort by numerical value instead of by string
  84. * representation.
  85. */
  86. bool operator<(const QStandardItem& other) const override {
  87. return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong();
  88. }
  89. };
  90. /**
  91. * Asynchronous worker object for populating the game list.
  92. * Communicates with other threads through Qt's signal/slot system.
  93. */
  94. class GameListWorker : public QObject, public QRunnable {
  95. Q_OBJECT
  96. public:
  97. GameListWorker(QString dir_path, bool deep_scan)
  98. : QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan) {}
  99. public slots:
  100. /// Starts the processing of directory tree information.
  101. void run() override;
  102. /// Tells the worker that it should no longer continue processing. Thread-safe.
  103. void Cancel();
  104. signals:
  105. /**
  106. * The `EntryReady` signal is emitted once an entry has been prepared and is ready
  107. * to be added to the game list.
  108. * @param entry_items a list with `QStandardItem`s that make up the columns of the new entry.
  109. */
  110. void EntryReady(QList<QStandardItem*> entry_items);
  111. /**
  112. * After the worker has traversed the game directory looking for entries, this signal is emmited
  113. * with a list of folders that should be watched for changes as well.
  114. */
  115. void Finished(QStringList watch_list);
  116. private:
  117. QStringList watch_list;
  118. QString dir_path;
  119. bool deep_scan;
  120. std::atomic_bool stop_processing;
  121. void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0);
  122. };