diff src/gui/pages/anime_list.cpp @ 15:cde8f67a7c7d

*: update, megacommit :)
author Paper <mrpapersonic@gmail.com>
date Tue, 19 Sep 2023 22:36:08 -0400
parents fc1bf97c528b
children d05b1be2f3a6
line wrap: on
line diff
--- a/src/gui/pages/anime_list.cpp	Tue Sep 19 16:33:07 2023 -0400
+++ b/src/gui/pages/anime_list.cpp	Tue Sep 19 22:36:08 2023 -0400
@@ -16,15 +16,14 @@
 #include "gui/dialog/information.h"
 #include "gui/translate/anime.h"
 #include "services/anilist.h"
+#include <QDebug>
 #include <QHBoxLayout>
 #include <QHeaderView>
 #include <QMenu>
 #include <QProgressBar>
-#include <QDebug>
 #include <QShortcut>
 #include <QStylePainter>
 #include <QStyledItemDelegate>
-#include <QAbstractItemModelTester>
 #include <cmath>
 
 AnimeListWidgetDelegate::AnimeListWidgetDelegate(QObject* parent) : QStyledItemDelegate(parent) {
@@ -36,29 +35,29 @@
 }
 
 void AnimeListWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
-									const QModelIndex& index) const {
+                                    const QModelIndex& index) const {
 	switch (index.column()) {
-/*
+#if 0
 		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());
+			    static_cast<int>(index.siblingAtColumn(AnimeListWidgetModel::AL_EPISODES).data(Qt::UserRole).toReal());
 
 			int text_width = 59;
 			QRectF text_rect(option.rect.x() + text_width, option.rect.y(), text_width, option.decorationSize.height());
 			painter->save();
 			painter->drawText(text_rect, "/", QTextOption(Qt::AlignCenter | Qt::AlignVCenter));
-			// drawText(const QRectF &rectangle, const QString &text, const QTextOption &option = QTextOption())
-			painter->drawText(QRectF(text_rect.x(), text_rect.y(), text_width / 2 - 2, text_rect.height()),
-							  QString::number(progress), QTextOption(Qt::AlignRight | Qt::AlignVCenter));
-			painter->drawText(
-				QRectF(text_rect.x() + text_width / 2 + 2, text_rect.y(), text_width / 2 - 2, text_rect.height()),
-				QString::number(episodes), QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
-			painter->restore();
-			QStyledItemDelegate::paint(painter, option, index);
-			break;
+			// drawText(const QRectF &rectangle, const QString &text, const QTextOption &option =
+			   QTextOption()) painter->drawText(QRectF(text_rect.x(), text_rect.y(), text_width / 2 - 2,
+			   text_rect.height()), QString::number(progress), QTextOption(Qt::AlignRight | Qt::AlignVCenter));
+			   painter->drawText(
+			       QRectF(text_rect.x() + text_width / 2 + 2, text_rect.y(), text_width / 2 - 2, text_rect.height()),
+			       QString::number(episodes), QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
+			   painter->restore();
+			   QStyledItemDelegate::paint(painter, option, index);
+			   break;
 		}
-*/
+#endif
 		default: QStyledItemDelegate::paint(painter, option, index); break;
 	}
 }
@@ -99,33 +98,33 @@
 QVariant AnimeListWidgetModel::headerData(const int section, const Qt::Orientation orientation, const int role) const {
 	if (role == Qt::DisplayRole) {
 		switch (section) {
-			case AL_TITLE: 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: return tr("Score");
-			case AL_SEASON: return tr("Season");
-			case AL_STARTED: return tr("Date started");
-			case AL_COMPLETED: return tr("Date completed");
-			case AL_NOTES: return tr("Notes");
-			case AL_AVG_SCORE: return tr("Average score");
-			case AL_UPDATED: return tr("Last updated");
-			default: return {};
+			   case AL_TITLE: 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: return tr("Score");
+			   case AL_SEASON: return tr("Season");
+			   case AL_STARTED: return tr("Date started");
+			   case AL_COMPLETED: return tr("Date completed");
+			   case AL_NOTES: return tr("Notes");
+			   case AL_AVG_SCORE: return tr("Average score");
+			   case AL_UPDATED: return tr("Last updated");
+			   default: return {};
 		}
 	} else if (role == Qt::TextAlignmentRole) {
 		switch (section) {
-			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: return QAbstractListModel::headerData(section, orientation, role);
+			   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: return QAbstractListModel::headerData(section, orientation, role);
 		}
 	}
 	return QAbstractListModel::headerData(section, orientation, role);
@@ -136,56 +135,56 @@
 		return QVariant();
 	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()].GetUserProgress()) + "/" + QString::number(list[index.row()].GetEpisodes());
-				case AL_EPISODES: return list[index.row()].GetEpisodes();
-				case AL_SCORE: return list[index.row()].GetUserScore();
-				case AL_TYPE: return QString::fromStdString(Translate::TranslateSeriesFormat(list[index.row()].GetFormat()));
-				case AL_SEASON:
-					return QString::fromStdString(Translate::TranslateSeriesSeason(list[index.row()].GetSeason())) + " " +
-						   QString::number(list[index.row()].GetAirDate().GetYear());
-				case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%";
-				case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate();
-				case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate();
-				case AL_UPDATED: {
-					if (list[index.row()].GetUserTimeUpdated() == 0)
-						return QString("-");
-					Time::Duration duration(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated());
-					return QString::fromUtf8(duration.AsRelativeString().c_str());
-				}
-				case AL_NOTES: return QString::fromUtf8(list[index.row()].GetUserNotes().c_str());
-				default: return "";
-			}
-			break;
+			   switch (index.column()) {
+				   case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str());
+				   case AL_PROGRESS:
+					   return QString::number(list[index.row()].GetUserProgress()) + "/" +
+					          QString::number(list[index.row()].GetEpisodes());
+				   case AL_EPISODES: return list[index.row()].GetEpisodes();
+				   case AL_SCORE: return list[index.row()].GetUserScore();
+				   case AL_TYPE: return QString::fromStdString(Translate::ToString(list[index.row()].GetFormat()));
+				   case AL_SEASON:
+					   return QString::fromStdString(Translate::ToString(list[index.row()].GetSeason())) + " " +
+					          QString::number(list[index.row()].GetAirDate().GetYear());
+				   case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%";
+				   case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate();
+				   case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate();
+				   case AL_UPDATED: {
+					   if (list[index.row()].GetUserTimeUpdated() == 0)
+						   return QString("-");
+					   Time::Duration duration(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated());
+					   return QString::fromUtf8(duration.AsRelativeString().c_str());
+				   }
+				   case AL_NOTES: return QString::fromUtf8(list[index.row()].GetUserNotes().c_str());
+				   default: return "";
+			   }
+			   break;
 		case Qt::UserRole:
-			switch (index.column()) {
-				case AL_ID: return list[index.row()].GetId();
-				case AL_PROGRESS: return list[index.row()].GetUserProgress();
-				case AL_TYPE: return static_cast<int>(list[index.row()].GetFormat());
-				case AL_SEASON: return list[index.row()].GetAirDate().GetAsQDate();
-				case AL_AVG_SCORE: return list[index.row()].GetAudienceScore();
-				case AL_UPDATED: return list[index.row()].GetUserTimeUpdated();
-				default: return data(index, Qt::DisplayRole);
-			}
-			break;
+			   switch (index.column()) {
+				   case AL_PROGRESS: return list[index.row()].GetUserProgress();
+				   case AL_TYPE: return static_cast<int>(list[index.row()].GetFormat());
+				   case AL_SEASON: return list[index.row()].GetAirDate().GetAsQDate();
+				   case AL_AVG_SCORE: return list[index.row()].GetAudienceScore();
+				   case AL_UPDATED: return list[index.row()].GetUserTimeUpdated();
+				   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;
+			   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();
 }
@@ -195,7 +194,7 @@
 	int i = 0;
 	for (const auto& a : Anime::db.items) {
 		if (a.second.IsInUserList() && a.first == id && a.second.GetUserStatus() == status) {
-			emit dataChanged(index(i), index(i));
+			   emit dataChanged(index(i), index(i));
 		}
 		i++;
 	}
@@ -207,15 +206,28 @@
 
 void AnimeListWidgetModel::RefreshList() {
 	bool has_children = !!rowCount(index(0));
-	if (has_children) beginResetModel();
+	if (has_children)
+		beginResetModel();
+	else {
+		int count = 0;
+		for (const auto& a : Anime::db.items)
+			   if (a.second.IsInUserList() && a.second.GetUserStatus() == status)
+				   count++;
+		beginInsertRows(index(0), 0, count - 1);
+	}
+
 	list.clear();
 
 	for (const auto& a : Anime::db.items) {
 		if (a.second.IsInUserList() && a.second.GetUserStatus() == status) {
-			list.push_back(a.second);
+			   list.push_back(a.second);
 		}
 	}
-	if (has_children) endResetModel();
+
+	if (has_children)
+		endResetModel();
+	else
+		endInsertRows();
 }
 
 int AnimeListWidget::VisibleColumnsCount() const {
@@ -223,7 +235,7 @@
 
 	for (int i = 0, end = tree_view->header()->count(); i < end; i++) {
 		if (!tree_view->isColumnHidden(i))
-			count++;
+			   count++;
 	}
 
 	return count;
@@ -242,7 +254,6 @@
 	tree_view->setColumnHidden(AnimeListWidgetModel::AL_COMPLETED, true);
 	tree_view->setColumnHidden(AnimeListWidgetModel::AL_UPDATED, true);
 	tree_view->setColumnHidden(AnimeListWidgetModel::AL_NOTES, true);
-	tree_view->setColumnHidden(AnimeListWidgetModel::AL_ID, true);
 }
 
 void AnimeListWidget::DisplayColumnHeaderMenu() {
@@ -252,10 +263,10 @@
 	menu->setToolTipsVisible(true);
 
 	for (int i = 0; i < AnimeListWidgetModel::NB_COLUMNS; i++) {
-		if (i == AnimeListWidgetModel::AL_TITLE || i == AnimeListWidgetModel::AL_ID)
-			continue;
+		if (i == AnimeListWidgetModel::AL_TITLE)
+			   continue;
 		const auto column_name =
-			sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
+		    sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
 		QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) {
 			if (!checked && (VisibleColumnsCount() <= 1))
 				return;
@@ -288,26 +299,28 @@
 	menu->setTitle(tr("Column visibility"));
 	menu->setToolTipsVisible(true);
 
-	const QItemSelection selection = sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
+	const QItemSelection selection =
+	    sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
 	if (!selection.indexes().first().isValid()) {
 		return;
 	}
 
 	QAction* action = menu->addAction("Information", [this, selection] {
 		const QModelIndex index = ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())
-									  ->index(selection.indexes().first().row());
+		                              ->index(selection.indexes().first().row());
 		Anime::Anime* anime =
-			((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index);
+		    ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index);
 		if (!anime) {
 			return;
 		}
 
 		InformationDialog* dialog = new InformationDialog(
-			*anime,
-			[this, anime] {
-				((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->UpdateAnime(anime->GetId());
-			},
-			this);
+		    *anime,
+		    [this, anime] {
+			    ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())
+			        ->UpdateAnime(anime->GetId());
+		    },
+		    this);
 
 		dialog->show();
 		dialog->raise();
@@ -319,22 +332,22 @@
 void AnimeListWidget::ItemDoubleClicked() {
 	/* throw out any other garbage */
 	const QItemSelection selection =
-		sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
+	    sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
 	if (!selection.indexes().first().isValid()) {
 		return;
 	}
 
 	const QModelIndex index = ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())
-								  ->index(selection.indexes().first().row());
+	                              ->index(selection.indexes().first().row());
 	Anime::Anime* anime =
-		((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index);
+	    ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index);
 
 	InformationDialog* dialog = new InformationDialog(
-		*anime,
-		[this, anime] {
-			((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->UpdateAnime(anime->GetId());
-		},
-		this);
+	    *anime,
+	    [this, anime] {
+		    ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->UpdateAnime(anime->GetId());
+	    },
+	    this);
 
 	dialog->show();
 	dialog->raise();
@@ -424,14 +437,14 @@
 	tree_view->setFrameShape(QFrame::NoFrame);
 
 	for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) {
-		tab_bar->addTab(QString::fromStdString(Translate::TranslateListStatus(Anime::ListStatuses[i])) + " (" + QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
+		tab_bar->addTab(QString::fromStdString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
+		                QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
 		sort_models[i] = new AnimeListWidgetSortFilter(tree_view);
-		AnimeListWidgetModel* model = new AnimeListWidgetModel(this, Anime::ListStatuses[i]);
-		new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Fatal, this);
-		sort_models[i]->setSourceModel(model);
+		sort_models[i]->setSourceModel(new AnimeListWidgetModel(this, Anime::ListStatuses[i]));
 		sort_models[i]->setSortRole(Qt::UserRole);
 		sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive);
 	}
+	tree_view->setModel(sort_models[0]);
 
 	QHBoxLayout* layout = new QHBoxLayout;
 	layout->addWidget(tree_view);
@@ -443,16 +456,15 @@
 	connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayListMenu);
 
 	/* Enter & return keys */
-	connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated,
-			this, &AnimeListWidget::ItemDoubleClicked);
+	connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this,
+	        &AnimeListWidget::ItemDoubleClicked);
 
-	connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated,
-			this, &AnimeListWidget::ItemDoubleClicked);
+	connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this,
+	        &AnimeListWidget::ItemDoubleClicked);
 
 	tree_view->header()->setStretchLastSection(false);
 	tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu);
-	connect(tree_view->header(), &QWidget::customContextMenuRequested, this,
-			&AnimeListWidget::DisplayColumnHeaderMenu);
+	connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayColumnHeaderMenu);
 
 	connect(tab_bar, &QTabBar::currentChanged, this, [this](int index) {
 		if (sort_models[index])
@@ -464,11 +476,24 @@
 }
 
 void AnimeListWidget::RefreshList() {
-	for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) {
+	for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++)
 		((AnimeListWidgetModel*)sort_models[i]->sourceModel())->RefreshList();
-	}
 }
 
+void AnimeListWidget::RefreshTabs() {
+	for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++)
+		tab_bar->setTabText(i, QString::fromStdString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
+		                           QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
+}
+
+void AnimeListWidget::Refresh() {
+	RefreshList();
+	RefreshTabs();
+}
+
+/* This function, really, really should not be called.
+   Ever. Why would you ever need to clear the anime list?
+   Also, this sucks. */
 void AnimeListWidget::Reset() {
 	while (tab_bar->count())
 		tab_bar->removeTab(0);