Mercurial > minori
diff src/anime.cpp @ 6:1d82f6e04d7d
Update: add first parts to the settings dialog
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 16 Aug 2023 00:49:17 -0400 |
parents | 190ded9438c0 |
children | 07a9095eaeed |
line wrap: on
line diff
--- a/src/anime.cpp Sat Aug 12 13:10:34 2023 -0400 +++ b/src/anime.cpp Wed Aug 16 00:49:17 2023 -0400 @@ -10,6 +10,7 @@ #include "time_utils.h" #include "information.h" #include "ui_utils.h" +#include <iostream> std::map<enum AnimeWatchingStatus, std::string> AnimeWatchingToStringMap = { {CURRENT, "Watching"}, @@ -74,6 +75,12 @@ duration = a.duration; } +std::string Anime::GetUserPreferredTitle() { + if (title.english.empty()) + return title.romaji; + return title.english; +} + void AnimeList::Add(Anime& anime) { if (anime_id_to_anime.contains(anime.id)) return; @@ -156,6 +163,58 @@ /* ------------------------------------------------------------------------- */ +AnimeListWidgetDelegate::AnimeListWidgetDelegate(QObject* parent) + : QStyledItemDelegate (parent) { +} + +QWidget *AnimeListWidgetDelegate::createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const +{ + // LOL + return nullptr; +} + +void AnimeListWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + switch (index.column()) { + case AnimeListWidgetModel::AL_PROGRESS: { + const int progress = static_cast<int>(index.data(Qt::UserRole).toReal()); + const int episodes = static_cast<int>(index.siblingAtColumn(AnimeListWidgetModel::AL_EPISODES).data(Qt::UserRole).toReal()); + + QStyleOptionViewItem customOption (option); + customOption.state.setFlag(QStyle::State_Enabled, true); + + progress_bar.paint(painter, customOption, index.data().toString(), progress, episodes); + break; + } + default: + QStyledItemDelegate::paint(painter, option, index); + break; + } +} + +AnimeListWidgetSortFilter::AnimeListWidgetSortFilter(QObject *parent) + : QSortFilterProxyModel(parent) { +} + +bool AnimeListWidgetSortFilter::lessThan(const QModelIndex &l, + const QModelIndex &r) const { + QVariant left = sourceModel()->data(l, sortRole()); + QVariant right = sourceModel()->data(r, sortRole()); + + switch (left.userType()) { + case QMetaType::Int: + case QMetaType::UInt: + case QMetaType::LongLong: + case QMetaType::ULongLong: + return left.toInt() < right.toInt(); + case QMetaType::QDate: + return left.toDate() < right.toDate(); + case QMetaType::QString: + default: + return left.toString() < right.toString(); + } +} + /* Thank you qBittorrent for having a great example of a widget model. */ AnimeListWidgetModel::AnimeListWidgetModel (QWidget* parent, AnimeList* alist) @@ -181,6 +240,8 @@ return tr("Anime title"); case AL_PROGRESS: return tr("Progress"); + case AL_EPISODES: + return tr("Episodes"); case AL_TYPE: return tr("Type"); case AL_SCORE: @@ -206,6 +267,7 @@ case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); case AL_PROGRESS: + case AL_EPISODES: case AL_TYPE: case AL_SCORE: case AL_AVG_SCORE: @@ -229,53 +291,75 @@ QVariant AnimeListWidgetModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); - if (role == Qt::DisplayRole) { - switch (index.column()) { - case AL_TITLE: - return QString::fromWCharArray(list[index.row()].title.english.c_str()); - case AL_PROGRESS: - return list[index.row()].progress; - case AL_SCORE: - return list[index.row()].score; - case AL_TYPE: - return QString::fromStdString(AnimeFormatToStringMap[list[index.row()].type]); - case AL_SEASON: - return QString::fromStdString(AnimeSeasonToStringMap[list[index.row()].season]) + " " + QString::number(list[index.row()].air_date.GetYear()); - case AL_AVG_SCORE: - return list[index.row()].audience_score; - case AL_STARTED: - return list[index.row()].started.GetAsQDate(); - case AL_COMPLETED: - return list[index.row()].completed.GetAsQDate(); - case AL_UPDATED: { - if (list[index.row()].updated == 0) - return QString("-"); - Time::Duration duration(Time::GetSystemTime() - list[index.row()].updated); - return QString::fromStdString(duration.AsRelativeString()); + switch (role) { + case Qt::DisplayRole: + switch (index.column()) { + case AL_TITLE: + return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); + case AL_PROGRESS: + return QString::number(list[index.row()].progress) + "/" + QString::number(list[index.row()].episodes); + case AL_EPISODES: + return list[index.row()].episodes; + case AL_SCORE: + return list[index.row()].score; + case AL_TYPE: + return QString::fromStdString(AnimeFormatToStringMap[list[index.row()].type]); + case AL_SEASON: + return QString::fromStdString(AnimeSeasonToStringMap[list[index.row()].season]) + " " + QString::number(list[index.row()].air_date.GetYear()); + case AL_AVG_SCORE: + return QString::number(list[index.row()].audience_score) + "%"; + case AL_STARTED: + return list[index.row()].started.GetAsQDate(); + case AL_COMPLETED: + return list[index.row()].completed.GetAsQDate(); + case AL_UPDATED: { + if (list[index.row()].updated == 0) + return QString("-"); + Time::Duration duration(Time::GetSystemTime() - list[index.row()].updated); + return QString::fromUtf8(duration.AsRelativeString().c_str()); + } + case AL_NOTES: + return QString::fromUtf8(list[index.row()].notes.c_str()); + default: + return ""; } - case AL_NOTES: - return QString::fromWCharArray(list[index.row()].notes.c_str()); - default: - return ""; - } - } else if (role == Qt::TextAlignmentRole) { - switch (index.column()) { - case AL_TITLE: - case AL_NOTES: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - case AL_PROGRESS: - case AL_TYPE: - case AL_SCORE: - case AL_AVG_SCORE: - return QVariant(Qt::AlignCenter | Qt::AlignVCenter); - case AL_SEASON: - case AL_STARTED: - case AL_COMPLETED: - case AL_UPDATED: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - break; - } + break; + case Qt::UserRole: + switch (index.column()) { + case AL_PROGRESS: + return list[index.row()].progress; + case AL_TYPE: + return list[index.row()].type; + case AL_SEASON: + return list[index.row()].air_date.GetAsQDate(); + case AL_AVG_SCORE: + return list[index.row()].audience_score; + case AL_UPDATED: + return list[index.row()].updated; + default: + return data(index, Qt::DisplayRole); + } + break; + case Qt::TextAlignmentRole: + switch (index.column()) { + case AL_TITLE: + case AL_NOTES: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + case AL_PROGRESS: + case AL_EPISODES: + case AL_TYPE: + case AL_SCORE: + case AL_AVG_SCORE: + return QVariant(Qt::AlignCenter | Qt::AlignVCenter); + case AL_SEASON: + case AL_STARTED: + case AL_COMPLETED: + case AL_UPDATED: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + default: + break; + } + break; } return QVariant(); } @@ -285,27 +369,6 @@ emit dataChanged(index(i), index(i)); } -/* Most of this stuff is const and/or should be edited in the Information dialog - -bool AnimeListWidgetModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (!index.isValid() || role != Qt::DisplayRole) - return false; - - Anime* const anime = &list[index.row()]; - - switch (index.column()) { - case AL_TITLE: - break; - case AL_CATEGORY: - break; - default: - return false; - } - - return true; -} -*/ - int AnimeListWidget::VisibleColumnsCount() const { int count = 0; @@ -325,6 +388,7 @@ setColumnHidden(AnimeListWidgetModel::AL_PROGRESS, false); setColumnHidden(AnimeListWidgetModel::AL_SCORE, false); setColumnHidden(AnimeListWidgetModel::AL_TITLE, false); + setColumnHidden(AnimeListWidgetModel::AL_EPISODES, true); setColumnHidden(AnimeListWidgetModel::AL_AVG_SCORE, true); setColumnHidden(AnimeListWidgetModel::AL_STARTED, true); setColumnHidden(AnimeListWidgetModel::AL_COMPLETED, true); @@ -370,29 +434,44 @@ } void AnimeListWidget::DisplayListMenu() { - /* throw out any other garbage */ - const QModelIndexList selected_items = selectionModel()->selectedRows(); - if (selected_items.size() != 1 || !selected_items.first().isValid()) { + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->setTitle(tr("Column visibility")); + menu->setToolTipsVisible(true); + + const QItemSelection selection = sort_model->mapSelectionToSource(selectionModel()->selection()); + if (!selection.indexes().first().isValid()) { return; } - const QModelIndex index = model->index(selected_items.first().row()); - Anime* anime = model->GetAnimeFromIndex(index); - if (!anime) { - return; - } + QAction* action = menu->addAction("Information", [this, selection]{ + const QModelIndex index = model->index(selection.indexes().first().row()); + Anime* anime = model->GetAnimeFromIndex(index); + if (!anime) { + return; + } + InformationDialog* dialog = new InformationDialog(*anime, model, this); + + dialog->show(); + dialog->raise(); + dialog->activateWindow(); + }); + menu->popup(QCursor::pos()); } void AnimeListWidget::ItemDoubleClicked() { /* throw out any other garbage */ - const QModelIndexList selected_items = selectionModel()->selectedRows(); - if (selected_items.size() != 1 || !selected_items.first().isValid()) { + const QItemSelection selection = sort_model->mapSelectionToSource(selectionModel()->selection()); + if (!selection.indexes().first().isValid()) { return; } - /* TODO: after we implement our sort model, we have to use mapToSource here... */ - const QModelIndex index = model->index(selected_items.first().row()); + const QModelIndex index = model->index(selection.indexes().first().row()); + const QString title = index.siblingAtColumn(AnimeListWidgetModel::AL_TITLE).data(Qt::UserRole).toString(); + QMessageBox box; + box.setText(QString::number(title.size())); + box.exec(); Anime* anime = model->GetAnimeFromIndex(index); if (!anime) { return; @@ -407,10 +486,14 @@ AnimeListWidget::AnimeListWidget(QWidget* parent, AnimeList* alist) : QTreeView(parent) { + setItemDelegate(new AnimeListWidgetDelegate(this)); model = new AnimeListWidgetModel(parent, alist); - setModel(model); + sort_model = new AnimeListWidgetSortFilter(this); + sort_model->setSourceModel(model); + sort_model->setSortRole(Qt::UserRole); + setModel(sort_model); setObjectName("listwidget"); - setStyleSheet("QTreeView#listwidget{border-top:0px;}"); + setStyleSheet("QTreeView#listwidget{border:0px;}"); setUniformRowHeights(true); setAllColumnsShowFocus(false); setSortingEnabled(true); @@ -438,9 +521,11 @@ AnimeListPage::AnimeListPage(QWidget* parent) : QTabWidget (parent) { setDocumentMode(false); + setObjectName("animepage"); + //setStyleSheet("QTabWidget#animepage{border-bottom:0px;border-left:0px;border-right:0px;}"); SyncAnimeList(); for (AnimeList& list : anime_lists) { - addTab(new AnimeListWidget(this, &list), QString::fromWCharArray(list.name.c_str())); + addTab(new AnimeListWidget(this, &list), QString::fromUtf8(list.name.c_str())); } } @@ -448,7 +533,6 @@ switch (session.config.service) { case ANILIST: { AniList anilist = AniList(); - anilist.Authorize(); session.config.anilist.user_id = anilist.GetUserId(session.config.anilist.username); FreeAnimeList(); anilist.UpdateAnimeList(&anime_lists, session.config.anilist.user_id); @@ -460,14 +544,10 @@ } void AnimeListPage::FreeAnimeList() { - if (anime_lists.size() > 0) { - /* FIXME: we may not need this, but to prevent memleaks - we should keep it until we're sure we don't */ - for (auto& list : anime_lists) { - list.Clear(); - } - anime_lists.clear(); + for (auto& list : anime_lists) { + list.Clear(); } + anime_lists.clear(); } int AnimeListPage::GetTotalAnimeAmount() {