yuzu: Add support for multiple game directories

Ported from https://github.com/citra-emu/citra/pull/3617.
This commit is contained in:
fearlessTobi
2019-05-01 23:21:04 +02:00
committed by FearlessTobi
parent 7fc5af3622
commit 2d8eba5baf
12 changed files with 664 additions and 193 deletions

View File

@ -10,6 +10,7 @@
#include <utility>
#include <QCoreApplication>
#include <QFileInfo>
#include <QImage>
#include <QObject>
#include <QStandardItem>
@ -22,6 +23,16 @@
#include "yuzu/uisettings.h"
#include "yuzu/util/util.h"
enum class GameListItemType {
Game = QStandardItem::UserType + 1,
CustomDir = QStandardItem::UserType + 2,
InstalledDir = QStandardItem::UserType + 3,
SystemDir = QStandardItem::UserType + 4,
AddDir = QStandardItem::UserType + 5
};
Q_DECLARE_METATYPE(GameListItemType);
/**
* Gets the default icon (for games without valid title metadata)
* @param size The desired width and height of the default icon.
@ -36,8 +47,13 @@ static QPixmap GetDefaultIcon(u32 size) {
class GameListItem : public QStandardItem {
public:
// used to access type from item index
static const int TypeRole = Qt::UserRole + 1;
static const int SortRole = Qt::UserRole + 2;
GameListItem() = default;
explicit GameListItem(const QString& string) : QStandardItem(string) {}
GameListItem(const QString& string) : QStandardItem(string) {
setData(string, SortRole);
}
};
/**
@ -48,14 +64,15 @@ public:
*/
class GameListItemPath : public GameListItem {
public:
static const int FullPathRole = Qt::UserRole + 1;
static const int TitleRole = Qt::UserRole + 2;
static const int ProgramIdRole = Qt::UserRole + 3;
static const int FileTypeRole = Qt::UserRole + 4;
static const int TitleRole = SortRole;
static const int FullPathRole = SortRole + 1;
static const int ProgramIdRole = SortRole + 2;
static const int FileTypeRole = SortRole + 3;
GameListItemPath() = default;
GameListItemPath(const QString& game_path, const std::vector<u8>& picture_data,
const QString& game_name, const QString& game_type, u64 program_id) {
setData(type(), TypeRole);
setData(game_path, FullPathRole);
setData(game_name, TitleRole);
setData(qulonglong(program_id), ProgramIdRole);
@ -72,6 +89,10 @@ public:
setData(picture, Qt::DecorationRole);
}
int type() const override {
return static_cast<int>(GameListItemType::Game);
}
QVariant data(int role) const override {
if (role == Qt::DisplayRole) {
std::string filename;
@ -103,9 +124,11 @@ public:
class GameListItemCompat : public GameListItem {
Q_DECLARE_TR_FUNCTIONS(GameListItemCompat)
public:
static const int CompatNumberRole = Qt::UserRole + 1;
static const int CompatNumberRole = SortRole;
GameListItemCompat() = default;
explicit GameListItemCompat(const QString& compatibility) {
setData(type(), TypeRole);
struct CompatStatus {
QString color;
const char* text;
@ -135,6 +158,10 @@ public:
setData(CreateCirclePixmapFromColor(status.color), Qt::DecorationRole);
}
int type() const override {
return static_cast<int>(GameListItemType::Game);
}
bool operator<(const QStandardItem& other) const override {
return data(CompatNumberRole) < other.data(CompatNumberRole);
}
@ -146,12 +173,12 @@ public:
* human-readable string representation will be displayed to the user.
*/
class GameListItemSize : public GameListItem {
public:
static const int SizeRole = Qt::UserRole + 1;
static const int SizeRole = SortRole;
GameListItemSize() = default;
explicit GameListItemSize(const qulonglong size_bytes) {
setData(type(), TypeRole);
setData(size_bytes, SizeRole);
}
@ -167,6 +194,10 @@ public:
}
}
int type() const override {
return static_cast<int>(GameListItemType::Game);
}
/**
* This operator is, in practice, only used by the TreeView sorting systems.
* Override it so that it will correctly sort by numerical value instead of by string
@ -177,6 +208,67 @@ public:
}
};
class GameListDir : public GameListItem {
public:
static const int GameDirRole = Qt::UserRole + 2;
explicit GameListDir(UISettings::GameDir& directory,
GameListItemType dir_type = GameListItemType::CustomDir)
: dir_type{dir_type} {
setData(type(), TypeRole);
UISettings::GameDir* game_dir = &directory;
setData(QVariant::fromValue(game_dir), GameDirRole);
int icon_size = UISettings::values.icon_size;
switch (dir_type) {
case GameListItemType::InstalledDir:
setData(QIcon::fromTheme("sd_card").pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
setData("Installed Titles", Qt::DisplayRole);
break;
case GameListItemType::SystemDir:
setData(QIcon::fromTheme("chip").pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
setData("System Titles", Qt::DisplayRole);
break;
case GameListItemType::CustomDir:
QString icon_name = QFileInfo::exists(game_dir->path) ? "folder" : "bad_folder";
setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
setData(game_dir->path, Qt::DisplayRole);
break;
};
};
int type() const override {
return static_cast<int>(dir_type);
}
private:
GameListItemType dir_type;
};
class GameListAddDir : public GameListItem {
public:
explicit GameListAddDir() {
setData(type(), TypeRole);
int icon_size = UISettings::values.icon_size;
setData(QIcon::fromTheme("plus").pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
setData("Add New Game Directory", Qt::DisplayRole);
}
int type() const override {
return static_cast<int>(GameListItemType::AddDir);
}
};
class GameList;
class QHBoxLayout;
class QTreeView;
@ -195,6 +287,9 @@ public:
void clear();
void setFocus();
int visible;
int total;
private:
class KeyReleaseEater : public QObject {
public: