diff src/gui/pages/anime_list.cc @ 273:f31305b9f60a

*: various code safety changes this also makes the code build on Qt 5.7. I can't test it though because I don't have it working... FAIL!
author Paper <paper@paper.us.eu.org>
date Thu, 18 Apr 2024 16:53:17 -0400
parents 862d0d8619f6
children f6a756c19bfb
line wrap: on
line diff
--- a/src/gui/pages/anime_list.cc	Thu Apr 18 16:51:35 2024 -0400
+++ b/src/gui/pages/anime_list.cc	Thu Apr 18 16:53:17 2024 -0400
@@ -27,11 +27,32 @@
 #include <QShortcut>
 #include <QStylePainter>
 #include <QStyledItemDelegate>
-#include <QThread>
+#include <QThreadPool>
+#include <QRunnable>
 #include <QTreeView>
 
 #include <set>
 
+AnimeListPageUpdateEntryThread::AnimeListPageUpdateEntryThread(AnimeListPage* parent) : QThread(parent) {
+	page_ = parent;
+}
+
+void AnimeListPageUpdateEntryThread::AddToQueue(int id) {
+	if (isRunning())
+		return; /* don't let us fuck ourselves */
+
+	queue_.push(id);
+}
+
+/* processes the queue... */
+void AnimeListPageUpdateEntryThread::run() {
+	while (!queue_.empty() && !isInterruptionRequested()) {
+		Services::UpdateAnimeEntry(queue_.front());
+		queue_.pop();
+	}
+	page_->Refresh();
+}
+
 AnimeListPageSortFilter::AnimeListPageSortFilter(QObject* parent) : QSortFilterProxyModel(parent) {
 }
 
@@ -111,7 +132,7 @@
 				case AL_TITLE: return Strings::ToQString(list[index.row()].GetUserPreferredTitle());
 				case AL_PROGRESS:
 					return QString::number(list[index.row()].GetUserProgress()) + "/" +
-					       QString::number(list[index.row()].GetEpisodes());
+						   QString::number(list[index.row()].GetEpisodes());
 				case AL_EPISODES: return list[index.row()].GetEpisodes();
 				case AL_SCORE: return Strings::ToQString(list[index.row()].GetUserPresentableScore());
 				case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat()));
@@ -120,7 +141,7 @@
 					if (!year)
 						return "Unknown Unknown";
 					return Strings::ToQString(Translate::ToLocalString(list[index.row()].GetSeason()) + " " +
-					                          Strings::ToUtf8String(year.value()));
+											  Strings::ToUtf8String(year.value()));
 				}
 				case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%";
 				case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate();
@@ -219,12 +240,14 @@
 }
 
 void AnimeListPage::UpdateAnime(int id) {
-	QThread* thread = QThread::create([this, id] { Services::UpdateAnimeEntry(id); });
+	/* this ought to just add to the thread's buffer. */
+	if (update_entry_thread_.isRunning()) {
+		update_entry_thread_.requestInterruption();
+		update_entry_thread_.wait();
+	}
 
-	connect(thread, &QThread::finished, this, &AnimeListPage::Refresh);
-	connect(thread, &QThread::finished, thread, &QThread::deleteLater);
-
-	thread->start();
+	update_entry_thread_.AddToQueue(id);
+	update_entry_thread_.start();
 }
 
 void AnimeListPage::RemoveAnime(int id) {
@@ -243,7 +266,7 @@
 		if (i == AnimeListPageModel::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))
@@ -277,9 +300,9 @@
 	menu->setToolTipsVisible(true);
 
 	AnimeListPageModel* source_model =
-	    reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel());
+		reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel());
 	const QItemSelection selection =
-	    sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
+		sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
 
 	std::set<Anime::Anime*> animes;
 	for (const auto& index : selection.indexes()) {
@@ -293,7 +316,7 @@
 	menu->addAction(tr("Information"), [this, animes] {
 		for (auto& anime : animes) {
 			InformationDialog* dialog = new InformationDialog(
-			    *anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this);
+				*anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this);
 
 			dialog->show();
 			dialog->raise();
@@ -304,7 +327,7 @@
 	menu->addAction(tr("Edit"), [this, animes] {
 		for (auto& anime : animes) {
 			InformationDialog* dialog = new InformationDialog(
-			    *anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, this);
+				*anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, this);
 
 			dialog->show();
 			dialog->raise();
@@ -322,19 +345,19 @@
 void AnimeListPage::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;
 	}
 
 	AnimeListPageModel* source_model =
-	    reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel());
+		reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel());
 
 	const QModelIndex index = source_model->index(selection.indexes().first().row());
 	Anime::Anime* anime = source_model->GetAnimeFromIndex(index);
 
 	InformationDialog* dialog = new InformationDialog(
-	    *anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this);
+		*anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this);
 
 	dialog->show();
 	dialog->raise();
@@ -349,7 +372,7 @@
 void AnimeListPage::RefreshTabs() {
 	for (unsigned int i = 0; i < sort_models.size(); i++)
 		tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
-		                           QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
+								   QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
 }
 
 void AnimeListPage::Refresh() {
@@ -424,7 +447,7 @@
 
 /* --------- QTabWidget replication end ---------- */
 
-AnimeListPage::AnimeListPage(QWidget* parent) : QWidget(parent) {
+AnimeListPage::AnimeListPage(QWidget* parent) : QWidget(parent), update_entry_thread_(this) {
 	/* Tab bar */
 	tab_bar = new QTabBar(this);
 	tab_bar->setExpanding(false);
@@ -445,7 +468,7 @@
 
 	for (unsigned int i = 0; i < sort_models.size(); i++) {
 		tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
-		                QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
+						QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
 		sort_models[i] = new AnimeListPageSortFilter(tree_view);
 		sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i]));
 		sort_models[i]->setSortRole(Qt::UserRole);
@@ -476,10 +499,10 @@
 
 	/* Enter & return keys */
 	connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this,
-	        &AnimeListPage::ItemDoubleClicked);
+			&AnimeListPage::ItemDoubleClicked);
 
 	connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this,
-	        &AnimeListPage::ItemDoubleClicked);
+			&AnimeListPage::ItemDoubleClicked);
 
 	tree_view->header()->setStretchLastSection(false);
 	tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu);