Qt/GameList: Implement tag system

This commit is contained in:
spycrab 2018-10-01 09:10:40 +02:00
parent 4ebf3f3189
commit 6e873c6e06
7 changed files with 146 additions and 2 deletions

View File

@ -201,6 +201,7 @@ void SConfig::SaveGameListSettings(IniFile& ini)
gamelist->Set("ColumnID", m_showIDColumn);
gamelist->Set("ColumnRegion", m_showRegionColumn);
gamelist->Set("ColumnSize", m_showSizeColumn);
gamelist->Set("ColumnTags", m_showTagsColumn);
}
void SConfig::SaveCoreSettings(IniFile& ini)
@ -475,6 +476,7 @@ void SConfig::LoadGameListSettings(IniFile& ini)
gamelist->Get("ColumnID", &m_showIDColumn, false);
gamelist->Get("ColumnRegion", &m_showRegionColumn, true);
gamelist->Get("ColumnSize", &m_showSizeColumn, true);
gamelist->Get("ColumnTags", &m_showTagsColumn, false);
}
void SConfig::LoadCoreSettings(IniFile& ini)

View File

@ -270,6 +270,7 @@ struct SConfig
bool m_showIDColumn;
bool m_showRegionColumn;
bool m_showSizeColumn;
bool m_showTagsColumn;
std::string m_WirelessMac;
bool m_PauseMovie;

View File

@ -14,6 +14,7 @@
#include <QFileInfo>
#include <QFrame>
#include <QHeaderView>
#include <QInputDialog>
#include <QKeyEvent>
#include <QLabel>
#include <QListView>
@ -132,6 +133,7 @@ void GameList::MakeListView()
hor_header->setSectionResizeMode(GameListModel::COL_COUNTRY, QHeaderView::Fixed);
hor_header->setSectionResizeMode(GameListModel::COL_SIZE, QHeaderView::Fixed);
hor_header->setSectionResizeMode(GameListModel::COL_FILE_NAME, QHeaderView::Interactive);
hor_header->setSectionResizeMode(GameListModel::COL_TAGS, QHeaderView::Interactive);
// There's some odd platform-specific behavior with default minimum section size
hor_header->setMinimumSectionSize(38);
@ -174,6 +176,7 @@ void GameList::UpdateColumnVisibility()
m_list->setColumnHidden(GameListModel::COL_SIZE, !SConfig::GetInstance().m_showSizeColumn);
m_list->setColumnHidden(GameListModel::COL_FILE_NAME,
!SConfig::GetInstance().m_showFileNameColumn);
m_list->setColumnHidden(GameListModel::COL_TAGS, !SConfig::GetInstance().m_showTagsColumn);
}
void GameList::MakeEmptyView()
@ -336,6 +339,35 @@ void GameList::ShowContextMenu(const QPoint&)
menu->addAction(tr("Open &containing folder"), this, &GameList::OpenContainingFolder);
menu->addAction(tr("Delete File..."), this, &GameList::DeleteFile);
menu->addSeparator();
auto* model = Settings::Instance().GetGameListModel();
auto* tags_menu = menu->addMenu(tr("Tags"));
auto path = game->GetFilePath();
auto game_tags = model->GetGameTags(path);
for (const auto& tag : model->GetAllTags())
{
auto* tag_action = tags_menu->addAction(tag);
tag_action->setCheckable(true);
tag_action->setChecked(game_tags.contains(tag));
connect(tag_action, &QAction::toggled, this, [this, path, tag, model](bool checked) {
if (!checked)
model->RemoveGameTag(path, tag);
else
model->AddGameTag(path, tag);
});
}
menu->addAction(tr("New Tag..."), this, &GameList::NewTag);
menu->addAction(tr("Remove Tag..."), this, &GameList::DeleteTag);
menu->addSeparator();
QAction* netplay_host = new QAction(tr("Host with NetPlay"), menu);
connect(netplay_host, &QAction::triggered, [this, game] {
@ -742,7 +774,8 @@ void GameList::OnColumnVisibilityToggled(const QString& row, bool visible)
{tr("File Name"), GameListModel::COL_FILE_NAME},
{tr("Game ID"), GameListModel::COL_ID},
{tr("Region"), GameListModel::COL_COUNTRY},
{tr("File Size"), GameListModel::COL_SIZE}};
{tr("File Size"), GameListModel::COL_SIZE},
{tr("Tags"), GameListModel::COL_TAGS}};
m_list->setColumnHidden(rowname_to_col_index[row], !visible);
}
@ -859,6 +892,26 @@ void GameList::OnHeaderViewChanged()
block = false;
}
void GameList::NewTag()
{
auto tag = QInputDialog::getText(this, tr("New tag"), tr("Name for a new tag:"));
if (tag.isEmpty())
return;
Settings::Instance().GetGameListModel()->NewTag(tag);
}
void GameList::DeleteTag()
{
auto tag = QInputDialog::getText(this, tr("Remove tag"), tr("Name of the tag to remove:"));
if (tag.isEmpty())
return;
Settings::Instance().GetGameListModel()->DeleteTag(tag);
}
void GameList::SetSearchTerm(const QString& term)
{
m_model->SetSearchTerm(term);

View File

@ -60,6 +60,8 @@ private:
void ExportWiiSave();
void CompressISO(bool decompress);
void ChangeDisc();
void NewTag();
void DeleteTag();
void UpdateColumnVisibility();
void ZoomIn();

View File

@ -42,6 +42,11 @@ GameListModel::GameListModel(QObject* parent) : QAbstractTableModel(parent)
emit layoutAboutToBeChanged();
emit layoutChanged();
});
auto& settings = Settings::GetQSettings();
m_tag_list = settings.value(QStringLiteral("gamelist/tags")).toStringList();
m_game_tags = settings.value(QStringLiteral("gamelist/game_tags")).toMap();
}
QVariant GameListModel::data(const QModelIndex& index, int role) const
@ -117,6 +122,14 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const
if (role == Qt::InitialSortOrderRole)
return static_cast<quint64>(game.GetFileSize());
break;
case COL_TAGS:
if (role == Qt::DisplayRole || role == Qt::InitialSortOrderRole)
{
auto tags = GetGameTags(game.GetFilePath());
tags.sort();
return tags.join(QStringLiteral(", "));
}
}
return QVariant();
@ -143,6 +156,8 @@ QVariant GameListModel::headerData(int section, Qt::Orientation orientation, int
return tr("File Name");
case COL_SIZE:
return tr("Size");
case COL_TAGS:
return tr("Tags");
}
return QVariant();
}
@ -293,3 +308,57 @@ float GameListModel::GetScale() const
{
return m_scale;
}
const QStringList& GameListModel::GetAllTags() const
{
return m_tag_list;
}
const QStringList GameListModel::GetGameTags(const std::string& path) const
{
return m_game_tags[QString::fromStdString(path)].toStringList();
}
void GameListModel::AddGameTag(const std::string& path, const QString& name)
{
auto tags = GetGameTags(path);
if (tags.contains(name))
return;
tags << name;
m_game_tags[QString::fromStdString(path)] = tags;
Settings::GetQSettings().setValue(QStringLiteral("gamelist/game_tags"), m_game_tags);
}
void GameListModel::RemoveGameTag(const std::string& path, const QString& name)
{
auto tags = GetGameTags(path);
tags.removeAll(name);
m_game_tags[QString::fromStdString(path)] = tags;
Settings::GetQSettings().setValue(QStringLiteral("gamelist/game_tags"), m_game_tags);
}
void GameListModel::NewTag(const QString& name)
{
if (m_tag_list.contains(name))
return;
m_tag_list << name;
Settings::GetQSettings().setValue(QStringLiteral("gamelist/tags"), m_tag_list);
}
void GameListModel::DeleteTag(const QString& name)
{
m_tag_list.removeAll(name);
for (const auto& file : m_game_tags.keys())
RemoveGameTag(file.toStdString(), name);
Settings::GetQSettings().setValue(QStringLiteral("gamelist/tags"), m_tag_list);
}

View File

@ -8,7 +8,10 @@
#include <string>
#include <QAbstractTableModel>
#include <QMap>
#include <QString>
#include <QStringList>
#include <QVariant>
#include "Core/TitleDatabase.h"
@ -52,6 +55,7 @@ public:
COL_COUNTRY,
COL_SIZE,
COL_FILE_NAME,
COL_TAGS,
NUM_COLS
};
@ -62,10 +66,22 @@ public:
void SetScale(float scale);
float GetScale() const;
const QStringList& GetAllTags() const;
const QStringList GetGameTags(const std::string& path) const;
void AddGameTag(const std::string& path, const QString& name);
void RemoveGameTag(const std::string& path, const QString& name);
void NewTag(const QString& name);
void DeleteTag(const QString& name);
private:
// Index in m_games, or -1 if it isn't found
int FindGame(const std::string& path) const;
QStringList m_tag_list;
QMap<QString, QVariant> m_game_tags;
GameTracker m_tracker;
QList<std::shared_ptr<const UICommon::GameFile>> m_games;
Core::TitleDatabase m_title_database;

View File

@ -570,7 +570,8 @@ void MenuBar::AddListColumnsMenu(QMenu* view_menu)
{tr("File Name"), &SConfig::GetInstance().m_showFileNameColumn},
{tr("Game ID"), &SConfig::GetInstance().m_showIDColumn},
{tr("Region"), &SConfig::GetInstance().m_showRegionColumn},
{tr("File Size"), &SConfig::GetInstance().m_showSizeColumn}};
{tr("File Size"), &SConfig::GetInstance().m_showSizeColumn},
{tr("Tags"), &SConfig::GetInstance().m_showTagsColumn}};
QActionGroup* column_group = new QActionGroup(this);
QMenu* cols_menu = view_menu->addMenu(tr("List Columns"));