Mercurial > minori
changeset 260:dd211ff68b36
pages/seasons: add initial functionality
the menu doesn't work yet, but it's a good start
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 03 Apr 2024 19:48:38 -0400 |
parents | 0362f3c4534c |
children | 3ec7804abf17 |
files | Makefile.am include/core/anime.h include/core/anime_season_db.h include/core/strings.h include/gui/pages/seasons.h src/core/anime_db.cc src/core/anime_season_db.cc src/core/strings.cc src/gui/pages/seasons.cc src/gui/pages/torrents.cc src/services/anilist.cc |
diffstat | 11 files changed, 152 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.am Mon Apr 01 18:11:15 2024 -0400 +++ b/Makefile.am Wed Apr 03 19:48:38 2024 -0400 @@ -154,6 +154,7 @@ noinst_HEADERS = \ include/core/anime_db.h \ include/core/anime.h \ + include/core/anime_season_db.h \ include/core/config.h \ include/core/date.h \ include/core/filesystem.h \ @@ -180,6 +181,7 @@ minori_SOURCES = \ src/core/anime_db.cc \ src/core/anime.cc \ + src/core/anime_season_db.cc \ src/core/config.cc \ src/core/date.cc \ src/core/filesystem.cc \
--- a/include/core/anime.h Mon Apr 01 18:11:15 2024 -0400 +++ b/include/core/anime.h Wed Apr 03 19:48:38 2024 -0400 @@ -50,6 +50,11 @@ FALL }; +constexpr std::array<SeriesSeason, 4> SeriesSeasons{ + SeriesSeason::WINTER, SeriesSeason::SPRING, + SeriesSeason::SUMMER, SeriesSeason::FALL +}; + enum class TitleLanguage { ROMAJI, NATIVE,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/core/anime_season_db.h Wed Apr 03 19:48:38 2024 -0400 @@ -0,0 +1,13 @@ +#ifndef MINORI_CORE_ANIME_SEASON_DB_H_ +#define MINORI_CORE_ANIME_SEASON_DB_H_ + +#include "core/anime.h" +#include "core/date.h" + +namespace Anime::Season { + +std::vector<int> GetAllAnimeForSeason(SeriesSeason season, Date::Year year); + +} + +#endif // MINORI_CORE_ANIME_SEASON_DB_H_
--- a/include/core/strings.h Mon Apr 01 18:11:15 2024 -0400 +++ b/include/core/strings.h Wed Apr 03 19:48:38 2024 -0400 @@ -21,13 +21,13 @@ std::vector<std::string> Split(const std::string& text, const std::string& delimiter); /* Substring removal functions */ -std::string ReplaceAll(std::string string, const std::string& find, const std::string& replace); -std::string SanitizeLineEndings(const std::string& string); -std::string RemoveHtmlTags(std::string string); -std::string ParseHtmlEntities(std::string string); +void ReplaceAll(std::string& string, std::string_view find, std::string_view replace); +void SanitizeLineEndings(std::string& string); +void RemoveHtmlTags(std::string& string); +void ParseHtmlEntities(std::string& string); /* stupid HTML bullshit */ -std::string TextifySynopsis(const std::string& string); +void TextifySynopsis(std::string& string); std::string ToUpper(const std::string& string); std::string ToLower(const std::string& string);
--- a/include/gui/pages/seasons.h Mon Apr 01 18:11:15 2024 -0400 +++ b/include/gui/pages/seasons.h Wed Apr 03 19:48:38 2024 -0400 @@ -3,6 +3,9 @@ #include <QWidget> +#include "core/anime.h" +#include "core/date.h" + class QListWidget; class QResizeEvent; @@ -11,6 +14,7 @@ public: SeasonsPage(QWidget* parent = nullptr); + void SetSeason(Anime::SeriesSeason season, Date::Year year); protected: QListWidget* buttons = nullptr;
--- a/src/core/anime_db.cc Mon Apr 01 18:11:15 2024 -0400 +++ b/src/core/anime_db.cc Wed Apr 03 19:48:38 2024 -0400 @@ -131,12 +131,14 @@ return 0; for (const auto& [id, anime] : items) { - if (anime.GetUserPreferredTitle() == title) - return id; + std::vector<std::string> synonyms(anime.GetTitleSynonyms()); + synonyms.push_back(anime.GetUserPreferredTitle()); - for (const auto& synonym : anime.GetTitleSynonyms()) - if (synonym == title) + for (const auto& synonym : synonyms) { + if (synonym == title) { return id; + } + } } return 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/anime_season_db.cc Wed Apr 03 19:48:38 2024 -0400 @@ -0,0 +1,20 @@ +#include "core/anime_season_db.h" +#include "core/anime.h" +#include "core/anime_db.h" +#include "core/date.h" + +namespace Anime::Season { + +std::vector<int> GetAllAnimeForSeason(SeriesSeason season, Date::Year year) { + std::vector<int> ret; + + for (const auto& [id, anime] : db.items) { + std::optional<Date::Year> anime_year = anime.GetAirDate().GetYear(); + if (anime.GetSeason() == season && anime_year && anime_year.value() == year) + ret.push_back(id); + } + + return ret; +} + +}
--- a/src/core/strings.cc Mon Apr 01 18:11:15 2024 -0400 +++ b/src/core/strings.cc Wed Apr 03 19:48:38 2024 -0400 @@ -70,26 +70,38 @@ /* This function is really only used for cleaning up the synopsis of * horrible HTML debris from AniList :) */ -std::string ReplaceAll(std::string string, const std::string& find, const std::string& replace) { +void ReplaceAll(std::string& string, std::string_view find, std::string_view replace) { size_t pos = 0; while ((pos = string.find(find, pos)) != std::string::npos) { string.replace(pos, find.length(), replace); pos += replace.length(); } - return string; } -std::string SanitizeLineEndings(const std::string& string) { +void SanitizeLineEndings(std::string& string) { /* LOL */ - return ReplaceAll(ReplaceAll(ReplaceAll(ReplaceAll(ReplaceAll(string, "\r\n", "\n"), "</p>", "\n"), "<br>", "\n"), - "<br />", "\n"), - "\n\n\n", "\n\n"); + ReplaceAll(string, "\r\n", "\n"); + ReplaceAll(string, "</p>", "\n"); + ReplaceAll(string, "<br>", "\n"); + ReplaceAll(string, "<br />", "\n"); + ReplaceAll(string, "\n\n\n", "\n\n"); +} + +void ConvertRomanNumerals(std::string& string) { + static const std::vector<std::pair<std::string_view, std::string_view>> vec = { + {"2", "II"}, {"3", "III"}, {"4", "IV"}, {"5", "V"}, {"6", "VI"}, + {"7", "VII"}, {"8", "VIII"}, {"9", "IX"}, {"11", "XI"}, {"12", "XII"}, + {"13", "XIII"} + }; + + for (const auto& item : vec) + ReplaceAll(string, item.second, item.first); } /* removes dumb HTML tags because anilist is aids and * gives us HTML for synopses :/ */ -std::string RemoveHtmlTags(std::string string) { +void RemoveHtmlTags(std::string& string) { while (string.find("<") != std::string::npos) { auto startpos = string.find("<"); auto endpos = string.find(">") + 1; @@ -97,17 +109,16 @@ if (endpos != std::string::npos) string.erase(startpos, endpos - startpos); } - return string; } /* e.g. "<" for "<" */ -std::string ParseHtmlEntities(std::string string) { +void ParseHtmlEntities(std::string& string) { + /* The only one of these I can understand using are the first + * three. why do the rest of these exist? + * + * probably mojibake. + */ const std::unordered_map<std::string, std::string> map = { - /* The only one of these I can understand using are the first - * three. why do the rest of these exist? - * - * probably mojibake. - */ {"<", "<" }, {"&rt;", ">" }, {" ", "\xA0"}, @@ -124,13 +135,14 @@ }; for (const auto& item : map) - string = ReplaceAll(string, item.first, item.second); - return string; + ReplaceAll(string, item.first, item.second); } /* removes stupid HTML stuff */ -std::string TextifySynopsis(const std::string& string) { - return ParseHtmlEntities(RemoveHtmlTags(SanitizeLineEndings(string))); +void TextifySynopsis(std::string& string) { + SanitizeLineEndings(string); + RemoveHtmlTags(string); + ParseHtmlEntities(string); } /* let Qt handle the heavy lifting of locale shit
--- a/src/gui/pages/seasons.cc Mon Apr 01 18:11:15 2024 -0400 +++ b/src/gui/pages/seasons.cc Wed Apr 03 19:48:38 2024 -0400 @@ -1,8 +1,12 @@ #include "gui/pages/seasons.h" #include "core/anime_db.h" +#include "core/anime_season_db.h" +#include "core/strings.h" #include "gui/widgets/anime_button.h" +#include "gui/translate/anime.h" +#include <QDate> #include <QFrame> #include <QListWidget> #include <QListWidgetItem> @@ -11,6 +15,23 @@ #include <QToolButton> #include <QVBoxLayout> +static constexpr Date::Year GetClosestDecade(Date::Year year) { + return year - (year % 10); +} + +void SeasonsPage::SetSeason(Anime::SeriesSeason season, Date::Year year) { + buttons->clear(); + + for (const auto& id : Anime::Season::GetAllAnimeForSeason(season, year)) { + QListWidgetItem* item = new QListWidgetItem; + AnimeButton* button = new AnimeButton(this); + button->SetAnime(Anime::db.items[id]); + item->setSizeHint(button->sizeHint()); + buttons->addItem(item); + buttons->setItemWidget(item, button); + } +} + SeasonsPage::SeasonsPage(QWidget* parent) : QWidget(parent) { QVBoxLayout* full_layout = new QVBoxLayout(this); @@ -22,22 +43,44 @@ toolbar->setMovable(false); { - { - QAction* action = new QAction(toolbar); - action->setIcon(QIcon(":/icons/16x16/calendar-previous.png")); - action->setToolTip(tr("Previous season")); - toolbar->addAction(action); - } + /* hard-coded this value */ + static constexpr Date::Year last_year = 1960; + + auto create_year_menu = [](QWidget* parent, QMenu* parent_menu, Date::Year year){ + const QString year_s = QString::number(year); + + QMenu* menu = new QMenu(year_s, parent); + for (const auto& season : Anime::SeriesSeasons) + menu->addAction(Strings::ToQString(Translate::ToLocalString(season)) + " " + year_s); + parent_menu->addMenu(menu); + }; + + auto create_decade_menu = [create_year_menu](QWidget* parent, QMenu* parent_menu, Date::Year decade) { + QMenu* menu = new QMenu(QString::number(decade) + "s", parent); + for (int i = 9; i >= 0; i--) + create_year_menu(parent, menu, decade + i); + parent_menu->addMenu(menu); + }; - { - QAction* action = new QAction(toolbar); - action->setIcon(QIcon(":/icons/16x16/calendar-next.png")); - action->setToolTip(tr("Next season")); - toolbar->addAction(action); - } + /* we'll be extinct by the time this code breaks, so I guess it's fine :) */ + const Date::Year year = static_cast<Date::Year>(QDate::currentDate().year()); + const Date::Year year_before_collapse = GetClosestDecade(year) - 10; + QToolButton* season_button = new QToolButton(toolbar); + QMenu* full_season_menu = new QMenu(season_button); + + for (Date::Year c = year; c >= year_before_collapse; c--) + create_year_menu(season_button, full_season_menu, c); - toolbar->addAction(QIcon(":/icons/16x16/calendar.png"), - "Fall 2024"); // this must be named the name of the season + full_season_menu->addSeparator(); + + for (Date::Year c = year_before_collapse - 10; c >= last_year; c -= 10) + create_decade_menu(season_button, full_season_menu, c); + + season_button->setMenu(full_season_menu); + season_button->setText("Summer 2011"); + season_button->setPopupMode(QToolButton::InstantPopup); + + toolbar->addWidget(season_button); } toolbar->addSeparator(); @@ -123,39 +166,9 @@ 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); } + + /* Do NOT move this up in this function, buttons HAS to be initialized */ + SetSeason(Anime::SeriesSeason::SUMMER, 2011); }
--- a/src/gui/pages/torrents.cc Mon Apr 01 18:11:15 2024 -0400 +++ b/src/gui/pages/torrents.cc Wed Apr 03 19:48:38 2024 -0400 @@ -157,7 +157,9 @@ torrent.SetResolution(Strings::ToUtf8String(elements.get(anitomy::kElementVideoResolution))); } - ParseFeedDescription(Strings::TextifySynopsis(item.child_value("description")), torrent); + std::string description = item.child_value("description"); + Strings::TextifySynopsis(description); + ParseFeedDescription(description, torrent); torrent.SetLink(item.child_value("link")); torrent.SetGuid(item.child_value("guid"));
--- a/src/services/anilist.cc Mon Apr 01 18:11:15 2024 -0400 +++ b/src/services/anilist.cc Wed Apr 03 19:48:38 2024 -0400 @@ -138,7 +138,10 @@ anime.SetAudienceScore(JSON::GetNumber(json, "/averageScore"_json_pointer, 0)); anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, ""))); anime.SetDuration(JSON::GetNumber(json, "/duration"_json_pointer, 0)); - anime.SetSynopsis(Strings::TextifySynopsis(JSON::GetString<std::string>(json, "/description"_json_pointer, ""))); + + std::string synopsis = JSON::GetString<std::string>(json, "/description"_json_pointer, ""); + Strings::TextifySynopsis(synopsis); + anime.SetSynopsis(synopsis); anime.SetGenres(JSON::GetArray<std::vector<std::string>>(json, "/genres"_json_pointer, {})); anime.SetTitleSynonyms(JSON::GetArray<std::vector<std::string>>(json, "/synonyms"_json_pointer, {}));