changeset 254:d14f8e0e40c3

[UNFINISHED] *: update anime button
author Paper <paper@paper.us.eu.org>
date Wed, 07 Feb 2024 07:57:37 -0500
parents b3549da699a6
children fe702c8f161f
files Makefile.am dep/animia/Makefile.am include/gui/pages/seasons.h include/gui/widgets/anime_button.h include/gui/widgets/poster.h src/core/anime_db.cc src/gui/pages/seasons.cc src/gui/pages/statistics.cc src/gui/widgets/anime_button.cc src/gui/widgets/poster.cc
diffstat 10 files changed, 170 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Tue Feb 06 16:56:32 2024 -0500
+++ b/Makefile.am	Wed Feb 07 07:57:37 2024 -0500
@@ -243,7 +243,7 @@
 minori_LDFLAGS = $(QT_LDFLAGS) $(ldflags_osx) $(ldflags_win)
 
 minori_DEPENDENCIES = dep/pugixml/libpugixml.la dep/animia/libanimia.la dep/anitomy/libanitomy.la
-minori_LDADD = $(libs_glib) $(LIBCURL) $(QT_LIBS) $(libs_osx) $(libs_win) $(minori_DEPENDENCIES)
+minori_LDADD = $(minori_DEPENDENCIES) $(libs_glib) $(LIBCURL) $(QT_LIBS) $(libs_osx) $(libs_win)
 
 # Build only one qrc, otherwise we get a ton of
 # weird linking errors
--- a/dep/animia/Makefile.am	Tue Feb 06 16:56:32 2024 -0500
+++ b/dep/animia/Makefile.am	Wed Feb 07 07:57:37 2024 -0500
@@ -30,6 +30,7 @@
 
 if BUILD_WIN
 files_win = src/fd/win32.cc src/win/win32.cc src/util/win32.cc
+libs_win = -lole32 -luuid
 endif
 
 if BUILD_OSX
@@ -90,6 +91,6 @@
 libanimia_la_CXXFLAGS = -std=c++17 $(cflags_osx) $(cflags_x11) $(cflags_wayland)
 libanimia_la_LDFLAGS = -version-info 0:0:0 $(ldflags_osx)
 
-libanimia_la_LIBADD = $(libs_wayland) $(libs_x11) $(libs_osx) $(libs_libutil) $(libs_libkvm)
+libanimia_la_LIBADD = $(libs_win) $(libs_wayland) $(libs_x11) $(libs_osx) $(libs_libutil) $(libs_libkvm)
 
 ACLOCAL_AMFLAGS = -I m4
--- a/include/gui/pages/seasons.h	Tue Feb 06 16:56:32 2024 -0500
+++ b/include/gui/pages/seasons.h	Wed Feb 07 07:57:37 2024 -0500
@@ -3,11 +3,17 @@
 
 #include <QWidget>
 
+class QListWidget;
+class QResizeEvent;
+
 class SeasonsPage final : public QWidget {
 		Q_OBJECT
 
 	public:
 		SeasonsPage(QWidget* parent = nullptr);
+
+	protected:
+		QListWidget* buttons = nullptr;
 };
 
 #endif // __gui__pages__seasons_h
--- a/include/gui/widgets/anime_button.h	Tue Feb 06 16:56:32 2024 -0500
+++ b/include/gui/widgets/anime_button.h	Wed Feb 07 07:57:37 2024 -0500
@@ -4,12 +4,12 @@
 #include <QFrame>
 
 class QWidget;
+class QLabel;
 
 class Poster;
 class ElidedLabel;
 
 namespace TextWidgets {
-class Line;
 class LabelledParagraph;
 }
 
@@ -25,7 +25,7 @@
 
 protected:
 	Poster* _poster = nullptr;
-	TextWidgets::Line* _title = nullptr;
+	QLabel* _title = nullptr;
 	TextWidgets::LabelledParagraph* _info = nullptr;
 	ElidedLabel* _synopsis = nullptr;
 };
--- a/include/gui/widgets/poster.h	Tue Feb 06 16:56:32 2024 -0500
+++ b/include/gui/widgets/poster.h	Wed Feb 07 07:57:37 2024 -0500
@@ -10,21 +10,24 @@
 }
 
 class Poster final : public QFrame {
-		Q_OBJECT
+	Q_OBJECT
 
-	public:
-		Poster(QWidget* parent = nullptr);
-		Poster(const Anime::Anime& anime, QWidget* parent = nullptr);
-		void SetAnime(const Anime::Anime& anime);
+public:
+	Poster(QWidget* parent = nullptr);
+	Poster(const Anime::Anime& anime, QWidget* parent = nullptr);
+	void SetAnime(const Anime::Anime& anime);
+	void SetClickable(bool clickable);
 
-	protected:
-		void resizeEvent(QResizeEvent*) override;
-		void ImageDownloadFinished(const QByteArray& arr);
-		void RenderToLabel();
+protected:
+	void resizeEvent(QResizeEvent*) override;
+	void ImageDownloadFinished(const QByteArray& arr);
+	void RenderToLabel();
 
-	private:
-		QImage img;
-		ClickableLabel* label;
+private:
+	QImage img;
+	QString service_url;
+	ClickableLabel* label;
+	bool clickable = true;
 };
 
 #endif // __gui__widgets__poster_h
\ No newline at end of file
--- a/src/core/anime_db.cc	Tue Feb 06 16:56:32 2024 -0500
+++ b/src/core/anime_db.cc	Wed Feb 07 07:57:37 2024 -0500
@@ -123,47 +123,23 @@
 }
 
 /* 
- * This fairly basic algorithm is only in effect because
- * there are some special cases, e.g. Another and Re:ZERO, where 
- * we get the wrong match, so we have to create Advanced Techniques
- * to solve this
- *
- * This algorithm:
- *   1. searches each anime item for a match to the preferred title
- *      AND all synonyms and marks those matches with
- *        `synonym.length() - (synonym.find(needle) + needle.length());`
- *      which should never be less than zero and will be zero if, and only if
- *      the titles match exactly.
- *   2. returns the id of the match that is the lowest, which will most
- *      definitely match anything that exactly matches the title of the
- *      filename
+ * TODO: separate this from the anime DB,
+ * provide *some* sort of normalization
 */
 int Database::GetAnimeFromTitle(const std::string& title) {
 	if (title.empty())
 		return 0;
 
-	std::unordered_map<int, size_t> map;
-
-	static const auto process_title = [&map](const Anime& anime, const std::string& title, const std::string& needle) -> bool {
-		const std::string title_l = Strings::ToLower(title), needle_l = Strings::ToLower(needle);
-		size_t ret = title_l.find(needle_l);
-		if (ret == std::string::npos)
-			return false;
-
-		map[anime.GetId()] = title.length() - (ret + needle.length());
-		return true;
-	};
-
 	for (const auto& [id, anime] : items) {
-		if (process_title(anime, anime.GetUserPreferredTitle(), title))
-			continue;
+		if (anime.GetUserPreferredTitle() == title)
+			return id;
 
 		for (const auto& synonym : anime.GetTitleSynonyms())
-			if (process_title(anime, synonym, title))
-				continue;
+			if (synonym == title)
+				return id;
 	}
 
-	return get_lowest_in_map(map);
+	return 0;
 }
 
 static bool GetListDataAsJSON(const Anime& anime, nlohmann::json& json) {
--- a/src/gui/pages/seasons.cc	Tue Feb 06 16:56:32 2024 -0500
+++ b/src/gui/pages/seasons.cc	Wed Feb 07 07:57:37 2024 -0500
@@ -5,32 +5,95 @@
 #include "gui/layouts/flow_layout.h"
 
 #include <QVBoxLayout>
+#include <QToolBar>
+#include <QFrame>
+#include <QListWidget>
+#include <QListWidgetItem>
 
 SeasonsPage::SeasonsPage(QWidget* parent) : QWidget(parent) {
-	FlowLayout* ly = new FlowLayout(this);
+	QVBoxLayout* full_layout = new QVBoxLayout(this);
+
 	{
-		AnimeButton* button = new AnimeButton(this);
-		button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
-		ly->addWidget(button);
+		/* Toolbar */
+		QToolBar* toolbar = new QToolBar(this);
+		toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+		toolbar->setIconSize(QSize(16, 16));
+		toolbar->setMovable(false);
+
+		{
+			/* this needs to be stored somewhere to replicate Taiga's
+			   "timer" feature */
+			toolbar->addAction("Aids");
+		}
+
+		toolbar->addSeparator();
+
+		{
+			toolbar->addAction(QIcon(":/icons/16x16/navigation-270-button.png"), tr("Download &marked torrents"));
+		}
+
+		{
+			toolbar->addAction(QIcon(":/icons/16x16/cross-button.png"), tr("&Discard all"));
+		}
+
+		toolbar->addSeparator();
+
+		{
+			toolbar->addAction(QIcon(":/icons/16x16/gear.png"), tr("&Settings"));
+		}
+
+		full_layout->addWidget(toolbar);
 	}
-	{
-		AnimeButton* button = new AnimeButton(this);
-		button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
-		ly->addWidget(button);
-	}
+
 	{
-		AnimeButton* button = new AnimeButton(this);
-		button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
-		ly->addWidget(button);
+		QFrame* line = new QFrame(this);
+		line->setFrameShape(QFrame::HLine);
+		line->setFrameShadow(QFrame::Sunken);
+		line->setLineWidth(1);
+		full_layout->addWidget(line);
 	}
+
 	{
-		AnimeButton* button = new AnimeButton(this);
-		button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
-		ly->addWidget(button);
-	}
-	{
-		AnimeButton* button = new AnimeButton(this);
-		button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
-		ly->addWidget(button);
+		buttons = new QListWidget(this);
+		buttons->setFlow(QListView::LeftToRight);
+		buttons->setWrapping(true);
+		buttons->setContentsMargins(4, 4, 4, 4);
+		buttons->setSpacing(2);
+		buttons->setResizeMode(QListView::Adjust);
+
+		{
+			QListWidgetItem* item = new QListWidgetItem;
+			AnimeButton* button = new AnimeButton(this);
+			button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
+			item->setSizeHint(button->sizeHint());
+			buttons->addItem(item);
+			buttons->setItemWidget(item, button);
+		}
+		{
+			QListWidgetItem* item = new QListWidgetItem;
+			AnimeButton* button = new AnimeButton(this);
+			button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
+			item->setSizeHint(button->sizeHint());
+			buttons->addItem(item);
+			buttons->setItemWidget(item, button);
+		}
+		{
+			QListWidgetItem* item = new QListWidgetItem;
+			AnimeButton* button = new AnimeButton(this);
+			button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
+			item->setSizeHint(button->sizeHint());
+			buttons->addItem(item);
+			buttons->setItemWidget(item, button);
+		}
+		{
+			QListWidgetItem* item = new QListWidgetItem;
+			AnimeButton* button = new AnimeButton(this);
+			button->SetAnime(Anime::db.items[Anime::db.GetAnimeFromTitle("Another")]);
+			item->setSizeHint(button->sizeHint());
+			buttons->addItem(item);
+			buttons->setItemWidget(item, button);
+		}
+
+		full_layout->addWidget(buttons);
 	}
 }
--- a/src/gui/pages/statistics.cc	Tue Feb 06 16:56:32 2024 -0500
+++ b/src/gui/pages/statistics.cc	Wed Feb 07 07:57:37 2024 -0500
@@ -52,8 +52,6 @@
 			score_parent_layout->setSpacing(0);
 			score_parent_layout->setContentsMargins(12, 0, 0, 0);
 
-			score_graph_parent->setContentsMargins(3, 0, 0, 0);
-
 			score_dist_layout->addWidget(score_graph_parent);
 		}
 
--- a/src/gui/widgets/anime_button.cc	Tue Feb 06 16:56:32 2024 -0500
+++ b/src/gui/widgets/anime_button.cc	Wed Feb 07 07:57:37 2024 -0500
@@ -33,7 +33,8 @@
 
 	_poster = new Poster(this);
 	_poster->setFixedSize(120, 170);
-	ly->addWidget(_poster);
+	_poster->SetClickable(false);
+	ly->addWidget(_poster, 0, Qt::AlignTop);
 
 	{
 		QWidget* misc_section = new QWidget(this);
@@ -42,18 +43,41 @@
 		QVBoxLayout* misc_layout = new QVBoxLayout(misc_section);
 		misc_layout->setContentsMargins(0, 0, 0, 0);
 
-		_title = new TextWidgets::Line("", misc_section);
+		_title = new QLabel("", misc_section);
+		_title->setAutoFillBackground(true);
+		_title->setContentsMargins(4, 4, 4, 4);
+		_title->setStyleSheet("background-color: rgba(0, 245, 25, 25);");
+		{
+			QFont fnt(_title->font());
+			fnt.setWeight(QFont::Bold);
+			_title->setFont(fnt);
+		}
 		misc_layout->addWidget(_title);
 
 		/* need to make a separate "labelled paragraph" for this */
-		_info = new TextWidgets::LabelledParagraph(tr("Aired:\nEpisodes:\nProducers:\nScore:\nPopularity:"), "\n\n\n\n", misc_section);
+		_info = new TextWidgets::LabelledParagraph(tr("Aired:\nEpisodes:\nGenres:\nProducers:\nScore:\nPopularity:"), "\n\n\n\n", misc_section);
+		{
+			QFont fnt(_info->GetLabels()->font());
+			fnt.setWeight(QFont::Bold);
+			_info->GetLabels()->setFont(fnt);
+		}
+		_info->setContentsMargins(4, 0, 4, 0);
 		_info->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
 		misc_layout->addWidget(_info);
 
-		_synopsis = new ElidedLabel("", misc_section);
-		misc_layout->addWidget(_synopsis);
+		QWidget* dummy = new QWidget(misc_section);
+		dummy->setContentsMargins(4, 0, 4, 0);
+		QVBoxLayout* dummy_layout = new QVBoxLayout(dummy);
+		dummy_layout->setSpacing(0);
+		// dummy_layout->setContentsMargins(0, 0, 0, 0);
+		dummy_layout->setContentsMargins(0, 0, 0, 0);
 
-		ly->addWidget(misc_section);
+		_synopsis = new ElidedLabel("", dummy);
+		_synopsis->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
+		dummy_layout->addWidget(_synopsis);
+		misc_layout->addWidget(dummy);
+
+		ly->addWidget(misc_section, 0, Qt::AlignTop);
 	}
 }
 
@@ -63,13 +87,14 @@
 
 void AnimeButton::SetAnime(const Anime::Anime& anime) {
 	_poster->SetAnime(anime);
-	_title->SetText(Strings::ToQString(anime.GetUserPreferredTitle()));
+	_title->setText(Strings::ToQString(anime.GetUserPreferredTitle()));
 
 	{
 		const QLocale& locale = session.config.locale.GetLocale();
 		_info->GetParagraph()->SetText(
 			locale.toString(anime.GetAirDate().GetAsQDate(), "dd MMM yyyy") + "\n" +
 			QString::number(anime.GetEpisodes()) + "\n" +
+			Strings::ToQString(Strings::Implode(anime.GetGenres(), ", ")) + "\n" +
 			"...\n" +
 			QString::number(anime.GetAudienceScore()) + "%\n" +
 			"..."
--- a/src/gui/widgets/poster.cc	Tue Feb 06 16:56:32 2024 -0500
+++ b/src/gui/widgets/poster.cc	Wed Feb 07 07:57:37 2024 -0500
@@ -4,6 +4,7 @@
 #include "core/session.h"
 #include "core/strings.h"
 #include "gui/widgets/clickable_label.h"
+
 #include <QByteArray>
 #include <QDebug>
 #include <QDesktopServices>
@@ -14,7 +15,6 @@
 #include <QPixmap>
 #include <QThread>
 #include <QUrl>
-#include <curl/curl.h>
 
 Poster::Poster(QWidget* parent) : QFrame(parent) {
 	QHBoxLayout* layout = new QHBoxLayout(this);
@@ -44,9 +44,27 @@
 		thread->start();
 	}
 
-	label->disconnect();
-	connect(label, &ClickableLabel::clicked, this,
-	        [anime] { QDesktopServices::openUrl(Strings::ToQString(anime.GetServiceUrl())); });
+	service_url = Strings::ToQString(anime.GetServiceUrl());
+
+	if (clickable) {
+		label->disconnect();
+		connect(label, &ClickableLabel::clicked, this,
+				[this] { QDesktopServices::openUrl(service_url); });
+	}
+}
+
+void Poster::SetClickable(bool enabled) {
+	clickable = enabled;
+
+	if (clickable && !service_url.isEmpty()) {
+		setCursor(Qt::PointingHandCursor);
+		label->disconnect();
+		connect(label, &ClickableLabel::clicked, this,
+				[this] { QDesktopServices::openUrl(service_url); });
+	} else {
+		setCursor(Qt::ArrowCursor);
+		label->disconnect();
+	}
 }
 
 void Poster::ImageDownloadFinished(const QByteArray& arr) {