changeset 279:657fda1b9cac

*: clean up enums
author Paper <paper@paper.us.eu.org>
date Fri, 19 Apr 2024 13:24:06 -0400
parents f6a756c19bfb
children 9b6e12c14a1e
files Makefile.am include/core/anime.h include/core/config.h include/gui/dialog/settings.h include/gui/theme.h include/gui/translate/anilist.h include/gui/translate/anime.h include/gui/translate/config.h src/core/anime.cc src/core/anime_db.cc src/gui/dialog/settings/application.cc src/gui/dialog/settings/services.cc src/gui/pages/search.cc src/gui/pages/seasons.cc src/gui/theme.cc src/gui/translate/anilist.cc src/gui/translate/anime.cc src/gui/translate/config.cc src/gui/window.cc src/services/anilist.cc src/services/services.cc src/track/media.cc
diffstat 22 files changed, 367 insertions(+), 348 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Thu Apr 18 17:24:42 2024 -0400
+++ b/Makefile.am	Fri Apr 19 13:24:06 2024 -0400
@@ -154,6 +154,7 @@
 noinst_HEADERS = \
 	include/core/anime_db.h		\
 	include/core/anime.h		\
+	include/core/anime_season.h	\
 	include/core/anime_season_db.h \
 	include/core/config.h		\
 	include/core/date.h		\
@@ -184,6 +185,7 @@
 minori_SOURCES = \
 	src/core/anime_db.cc		\
 	src/core/anime.cc		\
+	src/core/anime_season.cc	\
 	src/core/anime_season_db.cc \
 	src/core/config.cc		\
 	src/core/date.cc		\
--- a/include/core/anime.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/core/anime.h	Fri Apr 19 13:24:06 2024 -0400
@@ -10,81 +10,103 @@
 namespace Anime {
 
 enum class ListStatus {
-	NOT_IN_LIST,
-	CURRENT,
-	COMPLETED,
-	PAUSED,
-	DROPPED,
-	PLANNING
+	NotInList = 0,
+	Current,
+	Completed,
+	Paused,
+	Dropped,
+	Planning
+};
+
+constexpr std::array<ListStatus, 5> ListStatuses{
+	ListStatus::Current, ListStatus::Completed, ListStatus::Paused,
+    ListStatus::Dropped, ListStatus::Planning
 };
 
-constexpr std::array<ListStatus, 5> ListStatuses{ListStatus::CURRENT, ListStatus::COMPLETED, ListStatus::PAUSED,
-                                                 ListStatus::DROPPED, ListStatus::PLANNING};
+enum class SeriesStatus {
+	Unknown = 0,
+	Finished,
+	Releasing,
+	NotYetReleased,
+	Cancelled,
+	Hiatus
+};
 
-enum class SeriesStatus {
-	UNKNOWN,
-	FINISHED,
-	RELEASING,
-	NOT_YET_RELEASED,
-	CANCELLED,
-	HIATUS
+constexpr std::array<SeriesStatus, 6> SeriesStatuses{
+	SeriesStatus::Unknown,
+	SeriesStatus::Finished,
+	SeriesStatus::Releasing,
+	SeriesStatus::NotYetReleased,
+	SeriesStatus::Cancelled,
+	SeriesStatus::Hiatus
 };
 
 enum class SeriesFormat {
-	UNKNOWN,
-	TV,
-	TV_SHORT,
-	MOVIE,
-	SPECIAL,
-	OVA,
-	ONA,
-	MUSIC,
-	MANGA,
-	NOVEL,
-	ONE_SHOT
+	Unknown = 0,
+	Tv,
+	TvShort,
+	Movie,
+	Special,
+	Ova,
+	Ona,
+	Music
+};
+
+constexpr std::array<SeriesFormat, 8> SeriesFormats{
+	SeriesFormat::Unknown,
+	SeriesFormat::Tv,
+	SeriesFormat::TvShort,
+	SeriesFormat::Movie,
+	SeriesFormat::Special,
+	SeriesFormat::Ova,
+	SeriesFormat::Ona,
+	SeriesFormat::Music
 };
 
 enum class SeriesSeason {
-	UNKNOWN,
-	WINTER,
-	SPRING,
-	SUMMER,
-	FALL
+	Unknown = 0,
+	Winter,
+	Spring,
+	Summer,
+	Fall
 };
 
 constexpr std::array<SeriesSeason, 4> SeriesSeasons{
-	SeriesSeason::WINTER, SeriesSeason::SPRING,
-	SeriesSeason::SUMMER, SeriesSeason::FALL
+	SeriesSeason::Winter, SeriesSeason::Spring,
+	SeriesSeason::Summer, SeriesSeason::Fall
 };
 
 enum class TitleLanguage {
-	ROMAJI,
-	NATIVE,
-	ENGLISH
+	Romaji,
+	Native,
+	English
 };
 
-enum class Services {
-	NONE,
-	ANILIST,
-	NB_SERVICES
+constexpr std::array<TitleLanguage, 3> TitleLanguages{TitleLanguage::Romaji, TitleLanguage::Native, TitleLanguage::English};
+
+enum class Service {
+	None,
+	AniList
 };
 
+constexpr std::array<Service, 1> Services{Service::AniList};
+
 enum class ScoreFormat {
-	POINT_100,        // 0-100
-	POINT_10_DECIMAL, // 0.0-10.0
-	POINT_10,         // 0-10
-	POINT_5,          // 0-5, should be represented in stars
-	POINT_3           // 1-3, should be represented in smileys
+	Point100,       // 0-100
+	Point10Decimal, // 0.0-10.0
+	Point10,        // 0-10
+	Point5,         // 0-5, should be represented in stars
+	Point3          // 1-3, should be represented in smileys
 };
 
-constexpr std::array<ScoreFormat, 5> ScoreFormats{ScoreFormat::POINT_100, ScoreFormat::POINT_10_DECIMAL,
-                                                  ScoreFormat::POINT_10, ScoreFormat::POINT_5, ScoreFormat::POINT_3};
+constexpr std::array<ScoreFormat, 5> ScoreFormats{ScoreFormat::Point100, ScoreFormat::Point10Decimal,
+                                                  ScoreFormat::Point10, ScoreFormat::Point5, ScoreFormat::Point3};
 
 struct ListInformation {
 	int id = 0;
 	int progress = 0;
-	int score = 0; // note that this will ALWAYS be in POINT_100 format and must be converted
-	ListStatus status = ListStatus::NOT_IN_LIST;
+	int score = 0; // this will ALWAYS be in POINT_100 format internally
+	ListStatus status = ListStatus::NotInList;
 	Date started;
 	Date completed;
 	bool is_private = false;
@@ -103,12 +125,11 @@
 	} title;
 	std::vector<std::string> synonyms;
 	int episodes = 0;
-	SeriesStatus status = SeriesStatus::UNKNOWN;
+	SeriesStatus status = SeriesStatus::Unknown;
 	Date air_date;
 	std::vector<std::string> genres;
 	std::vector<std::string> producers;
-	SeriesFormat format = SeriesFormat::UNKNOWN;
-	SeriesSeason season = SeriesSeason::UNKNOWN;
+	SeriesFormat format = SeriesFormat::Unknown;
 	int audience_score = 0;
 	std::string synopsis;
 	int duration = 0;
@@ -172,7 +193,6 @@
 	void SetGenres(std::vector<std::string> const& genres);
 	void SetProducers(std::vector<std::string> const& producers);
 	void SetFormat(SeriesFormat format);
-	void SetSeason(SeriesSeason season);
 	void SetAudienceScore(int audience_score);
 	void SetSynopsis(std::string synopsis);
 	void SetDuration(int duration);
--- a/include/core/config.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/core/config.h	Fri Apr 19 13:24:06 2024 -0400
@@ -22,8 +22,8 @@
 	int Load();
 	int Save();
 
-	Anime::Services service;
-	Theme::Theme theme;
+	Anime::Service service;
+	Theme::ThemeManager theme;
 	Locale::Locale locale;
 
 	struct {
--- a/include/gui/dialog/settings.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/gui/dialog/settings.h	Fri Apr 19 13:24:06 2024 -0400
@@ -69,7 +69,7 @@
 	QWidget* CreateAnimeListWidget();
 	QWidget* CreateGeneralWidget();
 
-	Themes theme;
+	Theme::Theme theme;
 	QLocale locale;
 
 	decltype(session.config.anime_list.score_format) format;
--- a/include/gui/theme.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/gui/theme.h	Fri Apr 19 13:24:06 2024 -0400
@@ -1,30 +1,36 @@
 #ifndef MINORI_GUI_THEME_H_
 #define MINORI_GUI_THEME_H_
 
-#include <QStyle>
-
-enum class Themes {
-	OS,
-	LIGHT,
-	DARK
-};
+#include <array>
 
 namespace Theme {
 
-class Theme final {
+enum class Theme {
+	Default,
+	Light,
+	Dark
+};
+
+constexpr std::array<Theme, 3> Themes{
+	Theme::Default,
+	Theme::Light,
+	Theme::Dark
+};
+
+class ThemeManager final {
 public:
-	Theme(Themes theme = Themes::OS);
-	void SetTheme(Themes theme);
-	Themes GetTheme() const;
+	ThemeManager(Theme theme = Theme::Default);
+	void SetTheme(Theme theme);
+	Theme GetTheme() const;
 	bool IsInDarkTheme() const;
 	void RepaintCurrentTheme();
 
 private:
 	void SetToDarkTheme();
 	void SetToLightTheme();
-	void SetStyleSheet(Themes theme);
-	Themes GetCurrentOSTheme() const;
-	Themes theme;
+	void SetStyleSheet(Theme theme);
+	Theme GetCurrentOSTheme() const;
+	Theme theme;
 };
 
 } // namespace Theme
--- a/include/gui/translate/anilist.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/gui/translate/anilist.h	Fri Apr 19 13:24:06 2024 -0400
@@ -6,9 +6,9 @@
 namespace Translate {
 namespace AniList {
 
-Anime::SeriesStatus ToSeriesStatus(std::string status);
-Anime::SeriesSeason ToSeriesSeason(std::string season);
-Anime::SeriesFormat ToSeriesFormat(std::string format);
+Anime::SeriesStatus ToSeriesStatus(const std::string& status);
+Anime::SeriesSeason ToSeriesSeason(const std::string& season);
+Anime::SeriesFormat ToSeriesFormat(const std::string& format);
 
 } // namespace AniList
 } // namespace Translate
--- a/include/gui/translate/anime.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/gui/translate/anime.h	Fri Apr 19 13:24:06 2024 -0400
@@ -9,7 +9,7 @@
 std::string ToString(const Anime::SeriesFormat format);
 std::string ToString(const Anime::SeriesSeason season);
 std::string ToString(const Anime::SeriesStatus status);
-std::string ToString(const Anime::Services service);
+std::string ToString(const Anime::Service service);
 std::string ToString(const Anime::TitleLanguage language);
 std::string ToString(const Anime::ScoreFormat format);
 
@@ -17,7 +17,7 @@
 std::string ToLocalString(const Anime::SeriesFormat format);
 std::string ToLocalString(const Anime::SeriesSeason season);
 std::string ToLocalString(const Anime::SeriesStatus status);
-std::string ToLocalString(const Anime::Services service);
+std::string ToLocalString(const Anime::Service service);
 std::string ToLocalString(const Anime::TitleLanguage language);
 std::string ToLocalString(const Anime::ScoreFormat language);
 
@@ -25,7 +25,7 @@
 Anime::SeriesFormat ToSeriesFormat(const std::string& str);
 Anime::SeriesSeason ToSeriesSeason(const std::string& str);
 Anime::SeriesStatus ToSeriesStatus(const std::string& str);
-Anime::Services ToService(const std::string& str);
+Anime::Service ToService(const std::string& str);
 Anime::TitleLanguage ToLanguage(const std::string& str);
 Anime::ScoreFormat ToScoreFormat(const std::string& str);
 
--- a/include/gui/translate/config.h	Thu Apr 18 17:24:42 2024 -0400
+++ b/include/gui/translate/config.h	Fri Apr 19 13:24:06 2024 -0400
@@ -1,13 +1,14 @@
 #ifndef MINORI_GUI_TRANSLATE_CONFIG_H_
 #define MINORI_GUI_TRANSLATE_CONFIG_H_
 
-#include "core/config.h"
+#include "gui/theme.h"
 
 namespace Translate {
 
-Themes ToTheme(const std::string& theme);
-std::string ToString(const Themes& theme);
+Theme::Theme ToTheme(const std::string& theme);
+std::string ToString(const Theme::Theme& theme);
+std::string ToLocalString(const Theme::Theme& theme);
 
 } // namespace Translate
 
-#endif // MINORI_GUI_TRANSLATE_CONFIG_H_
\ No newline at end of file
+#endif // MINORI_GUI_TRANSLATE_CONFIG_H_
--- a/src/core/anime.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/core/anime.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -3,6 +3,7 @@
  * datatypes & variables
  */
 #include "core/anime.h"
+#include "core/anime_season.h"
 #include "core/date.h"
 #include "core/session.h"
 #include "core/strings.h"
@@ -46,15 +47,16 @@
 
 std::string Anime::GetUserPresentableScore() const {
 	assert(list_info_.has_value());
+
 	const int score = list_info_->score;
 	if (score == 0)
 		return "";
 
 	switch (session.config.anime_list.score_format) {
-		case ScoreFormat::POINT_10_DECIMAL:
+		case ScoreFormat::Point10Decimal:
 			return Strings::ToUtf8String(score / 10) + "." + Strings::ToUtf8String(score % 10);
-		case ScoreFormat::POINT_10: return Strings::ToUtf8String(score / 10);
-		case ScoreFormat::POINT_5: {
+		case ScoreFormat::Point10: return Strings::ToUtf8String(score / 10);
+		case ScoreFormat::Point5: {
 			std::string stars = "";
 
 			for (int i = 0; i < 100; i += 20)
@@ -62,7 +64,7 @@
 
 			return stars;
 		}
-		case ScoreFormat::POINT_3: {
+		case ScoreFormat::Point3: {
 			if (score >= 100)
 				return ":)";
 			else if (score >= 66)
@@ -73,7 +75,7 @@
 				return "";
 		}
 		default:
-		case ScoreFormat::POINT_100: return Strings::ToUtf8String(score);
+		case ScoreFormat::Point100: return Strings::ToUtf8String(score);
 	}
 }
 
@@ -222,7 +224,8 @@
 }
 
 SeriesSeason Anime::GetSeason() const {
-	return info_.season;
+	std::optional<Date::Month> month = info_.air_date.GetMonth();
+	return (month.has_value() ? GetSeasonForMonth(month.value()) : SeriesSeason::Unknown);
 }
 
 int Anime::GetAudienceScore() const {
@@ -243,7 +246,10 @@
 
 std::string Anime::GetServiceUrl() const {
 	/* todo: add support for other services... */
-	return "https://anilist.co/anime/" + Strings::ToUtf8String(GetId());
+	switch (session.config.service) {
+		case Service::AniList: return "https://anilist.co/anime/" + Strings::ToUtf8String(GetId());
+		default: return "";
+	}
 }
 
 void Anime::SetId(int id) {
@@ -294,10 +300,6 @@
 	info_.format = format;
 }
 
-void Anime::SetSeason(SeriesSeason season) {
-	info_.season = season;
-}
-
 void Anime::SetAudienceScore(int audience_score) {
 	info_.audience_score = audience_score;
 }
@@ -316,8 +318,8 @@
 
 std::string Anime::GetUserPreferredTitle() const {
 	switch (session.config.anime_list.language) {
-		case TitleLanguage::NATIVE: return (GetNativeTitle().empty()) ? GetRomajiTitle() : GetNativeTitle();
-		case TitleLanguage::ENGLISH: return (GetEnglishTitle().empty()) ? GetRomajiTitle() : GetEnglishTitle();
+		case TitleLanguage::Native: return (GetNativeTitle().empty()) ? GetRomajiTitle() : GetNativeTitle();
+		case TitleLanguage::Romaji: return (GetEnglishTitle().empty()) ? GetRomajiTitle() : GetEnglishTitle();
 		default: break;
 	}
 	return GetRomajiTitle();
--- a/src/core/anime_db.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/core/anime_db.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -27,7 +27,7 @@
 }
 
 size_t Database::GetListsAnimeAmount(ListStatus status) {
-	if (status == ListStatus::NOT_IN_LIST)
+	if (status == ListStatus::NotInList)
 		return 0;
 
 	size_t total = 0;
@@ -169,7 +169,7 @@
 		{"genres", anime.GetGenres()},
 		{"producers", anime.GetProducers()},
 		{"format", Translate::ToString(anime.GetFormat())},
-		{"season", Translate::ToString(anime.GetSeason())},
+		// {"season", Translate::ToString(anime.GetSeason())},
 		{"audience_score", anime.GetAudienceScore()},
 		{"synopsis", anime.GetSynopsis()},
 		{"duration", anime.GetDuration()},
@@ -247,7 +247,7 @@
 	anime.SetGenres(JSON::GetArray<std::vector<std::string>>(json, "/genres"_json_pointer, {}));
 	anime.SetProducers(JSON::GetArray<std::vector<std::string>>(json, "/producers"_json_pointer, {}));
 	anime.SetFormat(Translate::ToSeriesFormat(JSON::GetString<std::string>(json, "/format"_json_pointer, "")));
-	anime.SetSeason(Translate::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, "")));
+	// anime.SetSeason(Translate::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, "")));
 	anime.SetAudienceScore(JSON::GetNumber(json, "/audience_score"_json_pointer, 0));
 	anime.SetSynopsis(JSON::GetString<std::string>(json, "/synopsis"_json_pointer, ""));
 	anime.SetDuration(JSON::GetNumber(json, "/duration"_json_pointer, 0));
@@ -291,4 +291,4 @@
 
 Database db;
 
-} // namespace Anime
\ No newline at end of file
+} // namespace Anime
--- a/src/gui/dialog/settings/application.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/dialog/settings/application.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -4,6 +4,7 @@
 #include "gui/locale.h"
 #include "gui/theme.h"
 #include "gui/translate/anime.h"
+#include "gui/translate/config.h"
 
 #include <QCheckBox>
 #include <QComboBox>
@@ -14,8 +15,6 @@
 #include <QSizePolicy>
 #include <QVBoxLayout>
 
-#include <algorithm>
-
 QWidget* SettingsPageApplication::CreateAnimeListWidget() {
 	QWidget* result = new QWidget(this);
 	result->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
@@ -197,12 +196,13 @@
 			}
 
 			{
+				/* FIXME: don't hardcode these values */
 				QComboBox* theme_combo_box = new QComboBox(appearance_group_box);
-				theme_combo_box->addItem(tr("Default"));
-				theme_combo_box->addItem(tr("Light"));
-				theme_combo_box->addItem(tr("Dark"));
+				for (const auto& theme : Theme::Themes)
+					theme_combo_box->addItem(Strings::ToQString(Translate::ToLocalString(theme)));
+
 				connect(theme_combo_box, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
-				        [this](int index) { theme = static_cast<Themes>(index); });
+				        [this](int index) { theme = static_cast<Theme::Theme>(index); });
 				theme_combo_box->setCurrentIndex(static_cast<int>(theme));
 				appearance_layout->addWidget(theme_combo_box);
 			}
--- a/src/gui/dialog/settings/services.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/dialog/settings/services.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -2,6 +2,7 @@
 #include "core/session.h"
 #include "core/strings.h"
 #include "gui/dialog/settings.h"
+#include "gui/translate/anime.h"
 #include "services/anilist.h"
 #include <QComboBox>
 #include <QGroupBox>
@@ -30,9 +31,15 @@
 
 		{
 			QComboBox* sync_combo_box = new QComboBox(sync_group_box);
-			sync_combo_box->addItem(tr("AniList"));
+			for (const auto& service : Anime::Services)
+				sync_combo_box->addItem(Strings::ToQString(Translate::ToLocalString(service)), static_cast<int>(service));
+
 			connect(sync_combo_box, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
-			        [this](int index) { service = static_cast<Anime::Services>(index + 1); });
+			        [this, sync_combo_box](int index) {
+				service = static_cast<Anime::Service>(sync_combo_box->itemData(index).toInt());
+			});
+
+			/* this is evil */
 			sync_combo_box->setCurrentIndex(static_cast<int>(service) - 1);
 			sync_layout->addWidget(sync_combo_box);
 		}
--- a/src/gui/pages/search.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/pages/search.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -210,46 +210,16 @@
 	menu->addSeparator();
 	{
 		QMenu* submenu = menu->addMenu(tr("Add to list..."));
-		submenu->addAction(tr("Currently watching"), [animes] {
-			for (auto& anime : animes) {
-				if (!anime->IsInUserList())
-					anime->AddToUserList();
-				anime->SetUserStatus(Anime::ListStatus::CURRENT);
-				Services::UpdateAnimeEntry(anime->GetId());
-			}
-		});
-		submenu->addAction(tr("Completed"), [animes] {
-			for (auto& anime : animes) {
-				if (!anime->IsInUserList())
-					anime->AddToUserList();
-				anime->SetUserStatus(Anime::ListStatus::COMPLETED);
-				Services::UpdateAnimeEntry(anime->GetId());
-			}
-		});
-		submenu->addAction(tr("On hold"), [animes] {
-			for (auto& anime : animes) {
-				if (!anime->IsInUserList())
-					anime->AddToUserList();
-				anime->SetUserStatus(Anime::ListStatus::PAUSED);
-				Services::UpdateAnimeEntry(anime->GetId());
-			}
-		});
-		submenu->addAction(tr("Dropped"), [animes] {
-			for (auto& anime : animes) {
-				if (!anime->IsInUserList())
-					anime->AddToUserList();
-				anime->SetUserStatus(Anime::ListStatus::DROPPED);
-				Services::UpdateAnimeEntry(anime->GetId());
-			}
-		});
-		submenu->addAction(tr("Plan to watch"), [animes] {
-			for (auto& anime : animes) {
-				if (!anime->IsInUserList())
-					anime->AddToUserList();
-				anime->SetUserStatus(Anime::ListStatus::PLANNING);
-				Services::UpdateAnimeEntry(anime->GetId());
-			}
-		});
+		for (const auto& status : Anime::ListStatuses) {
+			submenu->addAction(Strings::ToQString(Translate::ToLocalString(status)), [animes, status] {
+				for (auto& anime : animes) {
+					if (!anime->IsInUserList())
+						anime->AddToUserList();
+					anime->SetUserStatus(status);
+					Services::UpdateAnimeEntry(anime->GetId());
+				}
+			});
+		}
 		submenu->setEnabled(add_to_list_enable);
 	}
 	menu->popup(QCursor::pos());
--- a/src/gui/pages/seasons.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/pages/seasons.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -178,5 +178,5 @@
 	}
 
 	/* Do NOT move this up in this function, buttons HAS to be initialized */
-	SetSeason(Anime::SeriesSeason::SUMMER, 2011);
+	SetSeason(Anime::SeriesSeason::Summer, 2011);
 }
--- a/src/gui/theme.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/theme.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -1,13 +1,15 @@
 #include "core/config.h"
 #include "core/session.h"
+#include "gui/theme.h"
 #include <QApplication>
 #include <QDebug>
 #include <QFile>
 #include <QStyleFactory>
 #include <QTextStream>
+#include <QStyle>
 #ifdef MACOSX
 #	include "sys/osx/dark_theme.h"
-#elif WIN32
+#elif defined(WIN32)
 #	include "sys/win32/dark_theme.h"
 #else
 #	ifdef GLIB
@@ -24,32 +26,34 @@
 
 namespace Theme {
 
-Theme::Theme(Themes theme) {
+ThemeManager::ThemeManager(Theme theme) {
 	this->theme = theme;
 }
 
-Themes Theme::GetTheme() const {
+Theme ThemeManager::GetTheme() const {
 	return theme;
 }
 
-bool Theme::IsInDarkTheme() const {
-	if (theme != Themes::OS)
-		return (theme == Themes::DARK);
+bool ThemeManager::IsInDarkTheme() const {
+	switch (theme) {
+		case Theme::Default:
 #ifdef MACOSX
-	if (osx::DarkThemeAvailable())
-		return osx::IsInDarkTheme();
+			if (osx::DarkThemeAvailable())
+				return osx::IsInDarkTheme();
 #elif defined(WIN32)
-	if (win32::DarkThemeAvailable())
-		return win32::IsInDarkTheme();
+			if (win32::DarkThemeAvailable())
+				return win32::IsInDarkTheme();
 #else
 #	ifdef GLIB
-	return glib::IsInDarkTheme();
+			return glib::IsInDarkTheme();
 #	endif
 #endif
-	return (theme == Themes::DARK);
+		default: break;
+	}
+	return (theme == Theme::Dark);
 }
 
-void Theme::SetToDarkTheme() {
+void ThemeManager::SetToDarkTheme() {
 	/* macOS >= 10.14 has its own global dark theme,
 	   use it :) */
 #ifdef MACOSX
@@ -60,10 +64,10 @@
 	if (win32::DarkThemeAvailable())
 		win32::SetTitleBarsToBlack(true);
 #endif
-		SetStyleSheet(Themes::DARK);
+		SetStyleSheet(Theme::Dark);
 }
 
-void Theme::SetToLightTheme() {
+void ThemeManager::SetToLightTheme() {
 #ifdef MACOSX
 	if (osx::DarkThemeAvailable())
 		osx::SetToLightTheme();
@@ -72,22 +76,17 @@
 	if (win32::DarkThemeAvailable())
 		win32::SetTitleBarsToBlack(false);
 #endif
-		SetStyleSheet(Themes::LIGHT);
+		SetStyleSheet(Theme::Light);
 }
 
-Themes Theme::GetCurrentOSTheme() const {
-	return IsInDarkTheme() ? Themes::DARK : Themes::LIGHT;
-
-	/* Currently OS detection only supports Windows and macOS.
-	   Please don't be shy if you're willing to port it to other OSes
-	   (or desktop environments, or window managers) */
-	return Themes::LIGHT;
+Theme ThemeManager::GetCurrentOSTheme() const {
+	return IsInDarkTheme() ? Theme::Dark : Theme::Light;
 }
 
 /* this function is private, and should stay that way */
-void Theme::SetStyleSheet(Themes theme) {
+void ThemeManager::SetStyleSheet(Theme theme) {
 	switch (theme) {
-		case Themes::DARK: {
+		case Theme::Dark: {
 			const QColor darkGray(53, 53, 53);
 			const QColor gray(128, 128, 128);
 			const QColor black(25, 25, 25);
@@ -127,8 +126,7 @@
 			break;
 		}
 		default:
-			/* this sucks, it relies on the standard palette which
-			 * may or may not be a dark style itself. */
+			/* this sucks. */
 			QPalette pal(QApplication::style()->standardPalette());
 #ifdef WIN32 /* fuck you Qt 6 */
 			pal.setColor(QPalette::Window, QColor(0xF0, 0xF0, 0xF0));
@@ -140,12 +138,12 @@
 	}
 }
 
-void Theme::SetTheme(Themes theme) {
+void ThemeManager::SetTheme(Theme theme) {
 	switch (theme) {
-		case Themes::LIGHT: SetToLightTheme(); break;
-		case Themes::DARK: SetToDarkTheme(); break;
-		case Themes::OS:
-			if (GetCurrentOSTheme() == Themes::LIGHT)
+		case Theme::Light: SetToLightTheme(); break;
+		case Theme::Dark: SetToDarkTheme(); break;
+		case Theme::Default:
+			if (GetCurrentOSTheme() == Theme::Light)
 				SetToLightTheme();
 			else
 				SetToDarkTheme();
@@ -154,8 +152,8 @@
 	this->theme = theme;
 }
 
-void Theme::RepaintCurrentTheme() {
-	Theme::SetTheme(theme);
+void ThemeManager::RepaintCurrentTheme() {
+	SetTheme(theme);
 }
 
 } // namespace Theme
--- a/src/gui/translate/anilist.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/translate/anilist.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -4,49 +4,46 @@
 namespace Translate {
 namespace AniList {
 
-Anime::SeriesStatus ToSeriesStatus(std::string status) {
+Anime::SeriesStatus ToSeriesStatus(const std::string& status) {
 	static const std::unordered_map<std::string, Anime::SeriesStatus> map = {
-	    {"FINISHED",         Anime::SeriesStatus::FINISHED        },
-	    {"RELEASING",        Anime::SeriesStatus::RELEASING       },
-	    {"NOT_YET_RELEASED", Anime::SeriesStatus::NOT_YET_RELEASED},
-	    {"CANCELLED",        Anime::SeriesStatus::CANCELLED       },
-	    {"HIATUS",           Anime::SeriesStatus::HIATUS          }
+	    {"FINISHED",         Anime::SeriesStatus::Finished        },
+	    {"RELEASING",        Anime::SeriesStatus::Releasing       },
+	    {"NOT_YET_RELEASED", Anime::SeriesStatus::NotYetReleased},
+	    {"CANCELLED",        Anime::SeriesStatus::Cancelled       },
+	    {"HIATUS",           Anime::SeriesStatus::Hiatus          }
     };
 
 	if (map.find(status) == map.end())
-		return Anime::SeriesStatus::UNKNOWN;
+		return Anime::SeriesStatus::Unknown;
 	return map.at(status);
 }
 
-Anime::SeriesSeason ToSeriesSeason(std::string season) {
+Anime::SeriesSeason ToSeriesSeason(const std::string& season) {
 	static const std::unordered_map<std::string, Anime::SeriesSeason> map = {
-	    {"WINTER", Anime::SeriesSeason::WINTER},
-	    {"SPRING", Anime::SeriesSeason::SPRING},
-	    {"SUMMER", Anime::SeriesSeason::SUMMER},
-	    {"FALL",   Anime::SeriesSeason::FALL  }
+	    {"WINTER", Anime::SeriesSeason::Winter},
+	    {"SPRING", Anime::SeriesSeason::Spring},
+	    {"SUMMER", Anime::SeriesSeason::Summer},
+	    {"FALL",   Anime::SeriesSeason::Fall  }
     };
 
 	if (map.find(season) == map.end())
-		return Anime::SeriesSeason::UNKNOWN;
+		return Anime::SeriesSeason::Unknown;
 	return map.at(season);
 }
 
-Anime::SeriesFormat ToSeriesFormat(std::string format) {
+Anime::SeriesFormat ToSeriesFormat(const std::string& format) {
 	static const std::unordered_map<std::string, enum Anime::SeriesFormat> map = {
-	    {"TV",       Anime::SeriesFormat::TV      },
-        {"TV_SHORT", Anime::SeriesFormat::TV_SHORT},
-	    {"MOVIE",    Anime::SeriesFormat::MOVIE   },
-        {"SPECIAL",  Anime::SeriesFormat::SPECIAL },
-	    {"OVA",      Anime::SeriesFormat::OVA     },
-        {"ONA",      Anime::SeriesFormat::ONA     },
-	    {"MUSIC",    Anime::SeriesFormat::MUSIC   },
-        {"MANGA",    Anime::SeriesFormat::MANGA   },
-	    {"NOVEL",    Anime::SeriesFormat::NOVEL   },
-        {"ONE_SHOT", Anime::SeriesFormat::ONE_SHOT}
+	    {"TV",       Anime::SeriesFormat::Tv      },
+        {"TV_SHORT", Anime::SeriesFormat::TvShort},
+	    {"MOVIE",    Anime::SeriesFormat::Movie   },
+        {"SPECIAL",  Anime::SeriesFormat::Special },
+	    {"OVA",      Anime::SeriesFormat::Ova     },
+        {"ONA",      Anime::SeriesFormat::Ona     },
+	    {"MUSIC",    Anime::SeriesFormat::Music   }
     };
 
 	if (map.find(format) == map.end())
-		return Anime::SeriesFormat::UNKNOWN;
+		return Anime::SeriesFormat::Unknown;
 	return map.at(format);
 }
 
--- a/src/gui/translate/anime.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/translate/anime.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -10,171 +10,177 @@
 
 std::string ToString(const Anime::ListStatus status) {
 	switch (status) {
-		case Anime::ListStatus::CURRENT: return "Currently watching";
-		case Anime::ListStatus::PLANNING: return "Plan to watch";
-		case Anime::ListStatus::COMPLETED: return "Completed";
-		case Anime::ListStatus::DROPPED: return "Dropped";
-		case Anime::ListStatus::PAUSED: return "On hold";
+		case Anime::ListStatus::Current: return "Currently watching";
+		case Anime::ListStatus::Planning: return "Plan to watch";
+		case Anime::ListStatus::Completed: return "Completed";
+		case Anime::ListStatus::Dropped: return "Dropped";
+		case Anime::ListStatus::Paused: return "On hold";
 		default:
-		case Anime::ListStatus::NOT_IN_LIST: return "Not in list";
+		case Anime::ListStatus::NotInList: return "Not in list";
 	}
 }
 
 std::string ToString(const Anime::SeriesFormat format) {
 	switch (format) {
-		case Anime::SeriesFormat::TV: return "TV";
-		case Anime::SeriesFormat::TV_SHORT: return "TV short";
-		case Anime::SeriesFormat::OVA: return "OVA";
-		case Anime::SeriesFormat::MOVIE: return "Movie";
-		case Anime::SeriesFormat::SPECIAL: return "Special";
-		case Anime::SeriesFormat::ONA: return "ONA";
-		case Anime::SeriesFormat::MUSIC: return "Music";
+		case Anime::SeriesFormat::Tv: return "TV";
+		case Anime::SeriesFormat::TvShort: return "TV short";
+		case Anime::SeriesFormat::Ova: return "OVA";
+		case Anime::SeriesFormat::Movie: return "Movie";
+		case Anime::SeriesFormat::Special: return "Special";
+		case Anime::SeriesFormat::Ona: return "ONA";
+		case Anime::SeriesFormat::Music: return "Music";
 		default:
-		case Anime::SeriesFormat::UNKNOWN: return "Unknown";
+		case Anime::SeriesFormat::Unknown: return "Unknown";
 	}
 }
 
 std::string ToString(const Anime::SeriesSeason season) {
 	switch (season) {
-		case Anime::SeriesSeason::WINTER: return "Winter";
-		case Anime::SeriesSeason::SUMMER: return "Summer";
-		case Anime::SeriesSeason::FALL: return "Fall";
-		case Anime::SeriesSeason::SPRING: return "Spring";
+		case Anime::SeriesSeason::Winter: return "Winter";
+		case Anime::SeriesSeason::Summer: return "Summer";
+		case Anime::SeriesSeason::Fall: return "Fall";
+		case Anime::SeriesSeason::Spring: return "Spring";
 		default:
-		case Anime::SeriesSeason::UNKNOWN: return "Unknown";
+		case Anime::SeriesSeason::Unknown: return "Unknown";
 	}
 }
 
 std::string ToString(const Anime::SeriesStatus status) {
 	switch (status) {
-		case Anime::SeriesStatus::RELEASING: return "Currently airing";
-		case Anime::SeriesStatus::FINISHED: return "Finished airing";
-		case Anime::SeriesStatus::NOT_YET_RELEASED: return "Not yet aired";
-		case Anime::SeriesStatus::CANCELLED: return "Cancelled";
-		case Anime::SeriesStatus::HIATUS: return "On hiatus";
+		case Anime::SeriesStatus::Releasing: return "Currently airing";
+		case Anime::SeriesStatus::Finished: return "Finished airing";
+		case Anime::SeriesStatus::NotYetReleased: return "Not yet aired";
+		case Anime::SeriesStatus::Cancelled: return "Cancelled";
+		case Anime::SeriesStatus::Hiatus: return "On hiatus";
 		default:
-		case Anime::SeriesStatus::UNKNOWN: return "Unknown";
+		case Anime::SeriesStatus::Unknown: return "Unknown";
 	}
 }
 
-std::string ToString(const Anime::Services service) {
+std::string ToString(const Anime::Service service) {
 	switch (service) {
-		case Anime::Services::ANILIST: return "AniList";
+		case Anime::Service::AniList: return "AniList";
 		default:
-		case Anime::Services::NONE: return "None";
+		case Anime::Service::None: return "None";
 	}
 }
 
 std::string ToString(const Anime::TitleLanguage language) {
 	switch (language) {
-		case Anime::TitleLanguage::NATIVE: return "Native";
-		case Anime::TitleLanguage::ENGLISH: return "English";
+		case Anime::TitleLanguage::Native: return "Native";
+		case Anime::TitleLanguage::English: return "English";
 		default:
-		case Anime::TitleLanguage::ROMAJI: return "Romaji";
+		case Anime::TitleLanguage::Romaji: return "Romaji";
 	}
 }
 
 std::string ToString(const Anime::ScoreFormat format) {
 	switch (format) {
-		case Anime::ScoreFormat::POINT_3: return "POINT_3";
-		case Anime::ScoreFormat::POINT_5: return "POINT_5";
-		case Anime::ScoreFormat::POINT_10: return "POINT_10";
-		case Anime::ScoreFormat::POINT_10_DECIMAL: return "POINT_10_DECIMAL";
+		case Anime::ScoreFormat::Point3: return "3-point";
+		case Anime::ScoreFormat::Point5: return "5-point";
+		case Anime::ScoreFormat::Point10: return "10-point";
+		case Anime::ScoreFormat::Point10Decimal: return "10-point Decimal";
 		default:
-		case Anime::ScoreFormat::POINT_100: return "POINT_100";
+		case Anime::ScoreFormat::Point100: return "100-point";
 	}
 }
 
 Anime::ListStatus ToListStatus(const std::string& str) {
 	static const std::unordered_map<std::string, Anime::ListStatus> map = {
-	    {"Currently watching", Anime::ListStatus::CURRENT  },
-	    {"Plan to watch",      Anime::ListStatus::PLANNING },
-	    {"Completed",          Anime::ListStatus::COMPLETED},
-	    {"Dropped",            Anime::ListStatus::DROPPED  },
-	    {"On hold",            Anime::ListStatus::PAUSED   }
+	    {"Currently watching", Anime::ListStatus::Current  },
+	    {"Plan to watch",      Anime::ListStatus::Planning },
+	    {"Completed",          Anime::ListStatus::Completed},
+	    {"Dropped",            Anime::ListStatus::Dropped  },
+	    {"On hold",            Anime::ListStatus::Paused   }
     };
 
 	if (map.find(str) == map.end())
-		return Anime::ListStatus::NOT_IN_LIST;
+		return Anime::ListStatus::NotInList;
 	return map.at(str);
 }
 
 Anime::SeriesStatus ToSeriesStatus(const std::string& str) {
 	static const std::unordered_map<std::string, Anime::SeriesStatus> map = {
-	    {"Currently airing", Anime::SeriesStatus::RELEASING       },
-	    {"Finished airing",  Anime::SeriesStatus::FINISHED        },
-	    {"Not yet aired",    Anime::SeriesStatus::NOT_YET_RELEASED},
-	    {"Cancelled",        Anime::SeriesStatus::CANCELLED       },
-	    {"On hiatus",        Anime::SeriesStatus::HIATUS          }
+	    {"Currently airing", Anime::SeriesStatus::Releasing       },
+	    {"Finished airing",  Anime::SeriesStatus::Finished        },
+	    {"Not yet aired",    Anime::SeriesStatus::NotYetReleased},
+	    {"Cancelled",        Anime::SeriesStatus::Cancelled       },
+	    {"On hiatus",        Anime::SeriesStatus::Hiatus          }
     };
 
 	if (map.find(str) == map.end())
-		return Anime::SeriesStatus::UNKNOWN;
+		return Anime::SeriesStatus::Unknown;
 	return map.at(str);
 }
 
 Anime::SeriesSeason ToSeriesSeason(const std::string& str) {
 	static const std::unordered_map<std::string, Anime::SeriesSeason> map = {
-	    {"Winter", Anime::SeriesSeason::WINTER},
-	    {"Summer", Anime::SeriesSeason::SUMMER},
-	    {"Fall",   Anime::SeriesSeason::FALL  },
-	    {"Spring", Anime::SeriesSeason::SPRING}
+	    {"Winter", Anime::SeriesSeason::Winter},
+	    {"Summer", Anime::SeriesSeason::Summer},
+	    {"Fall",   Anime::SeriesSeason::Fall  },
+	    {"Spring", Anime::SeriesSeason::Spring}
     };
 
 	if (map.find(str) == map.end())
-		return Anime::SeriesSeason::UNKNOWN;
+		return Anime::SeriesSeason::Unknown;
 	return map.at(str);
 }
 
 Anime::SeriesFormat ToSeriesFormat(const std::string& str) {
 	static const std::unordered_map<std::string, Anime::SeriesFormat> map = {
-	    {"TV",       Anime::SeriesFormat::TV      },
-        {"TV short", Anime::SeriesFormat::TV_SHORT},
-	    {"OVA",      Anime::SeriesFormat::OVA     },
-        {"Movie",    Anime::SeriesFormat::MOVIE   },
-	    {"Special",  Anime::SeriesFormat::SPECIAL },
-        {"ONA",      Anime::SeriesFormat::ONA     },
-	    {"Music",    Anime::SeriesFormat::MUSIC   }
+	    {"TV",       Anime::SeriesFormat::Tv      },
+        {"TV short", Anime::SeriesFormat::TvShort},
+	    {"OVA",      Anime::SeriesFormat::Ova     },
+        {"Movie",    Anime::SeriesFormat::Movie   },
+	    {"Special",  Anime::SeriesFormat::Special },
+        {"ONA",      Anime::SeriesFormat::Ona     },
+	    {"Music",    Anime::SeriesFormat::Music   }
     };
 
 	if (map.find(str) == map.end())
-		return Anime::SeriesFormat::UNKNOWN;
+		return Anime::SeriesFormat::Unknown;
 	return map.at(str);
 }
 
-Anime::Services ToService(const std::string& str) {
-	static const std::unordered_map<std::string, Anime::Services> map = {
-	    {"AniList", Anime::Services::ANILIST}
+Anime::Service ToService(const std::string& str) {
+	static const std::unordered_map<std::string, Anime::Service> map = {
+	    {"AniList", Anime::Service::AniList}
     };
 
 	if (map.find(str) == map.end())
-		return Anime::Services::NONE;
+		return Anime::Service::None;
 	return map.at(str);
 }
 
 Anime::TitleLanguage ToLanguage(const std::string& str) {
 	static const std::unordered_map<std::string, Anime::TitleLanguage> map = {
-	    {"Romaji",  Anime::TitleLanguage::ROMAJI },
-	    {"Native",  Anime::TitleLanguage::NATIVE },
-	    {"English", Anime::TitleLanguage::ENGLISH}
+	    {"Romaji",  Anime::TitleLanguage::Romaji },
+	    {"Native",  Anime::TitleLanguage::Native },
+	    {"English", Anime::TitleLanguage::English}
     };
 
 	if (map.find(str) == map.end())
-		return Anime::TitleLanguage::ROMAJI;
+		return Anime::TitleLanguage::Romaji;
 	return map.at(str);
 }
 
 Anime::ScoreFormat ToScoreFormat(const std::string& str) {
 	static const std::unordered_map<std::string, Anime::ScoreFormat> map = {
-	    {"POINT_3",          Anime::ScoreFormat::POINT_3         },
-	    {"POINT_5",          Anime::ScoreFormat::POINT_5         },
-	    {"POINT_10",         Anime::ScoreFormat::POINT_10        },
-	    {"POINT_10_DECIMAL", Anime::ScoreFormat::POINT_10_DECIMAL},
-	    {"POINT_100",        Anime::ScoreFormat::POINT_100       }
+		{"3-point",          Anime::ScoreFormat::Point3},
+		{"5-point",          Anime::ScoreFormat::Point5},
+		{"10-point",         Anime::ScoreFormat::Point10        },
+		{"10-point Decimal", Anime::ScoreFormat::Point10Decimal},
+		{"100-point",        Anime::ScoreFormat::Point100       },
+		/* old values, provided for compatibility */
+	    {"POINT_3",          Anime::ScoreFormat::Point3         },
+	    {"POINT_5",          Anime::ScoreFormat::Point5         },
+	    {"POINT_10",         Anime::ScoreFormat::Point10        },
+	    {"POINT_10_DECIMAL", Anime::ScoreFormat::Point10Decimal},
+	    {"POINT_100",        Anime::ScoreFormat::Point100       }
     };
 
 	if (map.find(str) == map.end())
-		return Anime::ScoreFormat::POINT_100;
+		return Anime::ScoreFormat::Point100;
 	return map.at(str);
 }
 
@@ -182,79 +188,79 @@
 
 std::string ToLocalString(const Anime::ListStatus status) {
 	switch (status) {
-		case Anime::ListStatus::CURRENT: return Strings::ToUtf8String(QCoreApplication::tr("Currently watching"));
-		case Anime::ListStatus::PLANNING: return Strings::ToUtf8String(QCoreApplication::tr("Plan to watch"));
-		case Anime::ListStatus::COMPLETED: return Strings::ToUtf8String(QCoreApplication::tr("Completed"));
-		case Anime::ListStatus::DROPPED: return Strings::ToUtf8String(QCoreApplication::tr("Dropped"));
-		case Anime::ListStatus::PAUSED: return Strings::ToUtf8String(QCoreApplication::tr("On hold"));
+		case Anime::ListStatus::Current: return Strings::ToUtf8String(QCoreApplication::tr("Currently watching"));
+		case Anime::ListStatus::Planning: return Strings::ToUtf8String(QCoreApplication::tr("Plan to watch"));
+		case Anime::ListStatus::Completed: return Strings::ToUtf8String(QCoreApplication::tr("Completed"));
+		case Anime::ListStatus::Dropped: return Strings::ToUtf8String(QCoreApplication::tr("Dropped"));
+		case Anime::ListStatus::Paused: return Strings::ToUtf8String(QCoreApplication::tr("On hold"));
 		default:
-		case Anime::ListStatus::NOT_IN_LIST: return Strings::ToUtf8String(QCoreApplication::tr("Not in list"));
+		case Anime::ListStatus::NotInList: return Strings::ToUtf8String(QCoreApplication::tr("Not in list"));
 	}
 }
 
 std::string ToLocalString(const Anime::SeriesFormat format) {
 	switch (format) {
-		case Anime::SeriesFormat::TV: return Strings::ToUtf8String(QCoreApplication::tr("TV"));
-		case Anime::SeriesFormat::TV_SHORT: return Strings::ToUtf8String(QCoreApplication::tr("TV short"));
-		case Anime::SeriesFormat::OVA: return Strings::ToUtf8String(QCoreApplication::tr("OVA"));
-		case Anime::SeriesFormat::MOVIE: return Strings::ToUtf8String(QCoreApplication::tr("Movie"));
-		case Anime::SeriesFormat::SPECIAL: return Strings::ToUtf8String(QCoreApplication::tr("Special"));
-		case Anime::SeriesFormat::ONA: return Strings::ToUtf8String(QCoreApplication::tr("ONA"));
-		case Anime::SeriesFormat::MUSIC: return Strings::ToUtf8String(QCoreApplication::tr("Music"));
+		case Anime::SeriesFormat::Tv: return Strings::ToUtf8String(QCoreApplication::tr("TV"));
+		case Anime::SeriesFormat::TvShort: return Strings::ToUtf8String(QCoreApplication::tr("TV short"));
+		case Anime::SeriesFormat::Ova: return Strings::ToUtf8String(QCoreApplication::tr("OVA"));
+		case Anime::SeriesFormat::Movie: return Strings::ToUtf8String(QCoreApplication::tr("Movie"));
+		case Anime::SeriesFormat::Special: return Strings::ToUtf8String(QCoreApplication::tr("Special"));
+		case Anime::SeriesFormat::Ona: return Strings::ToUtf8String(QCoreApplication::tr("ONA"));
+		case Anime::SeriesFormat::Music: return Strings::ToUtf8String(QCoreApplication::tr("Music"));
 		default:
-		case Anime::SeriesFormat::UNKNOWN: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
+		case Anime::SeriesFormat::Unknown: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
 	}
 }
 
 std::string ToLocalString(const Anime::SeriesSeason season) {
 	switch (season) {
-		case Anime::SeriesSeason::WINTER: return Strings::ToUtf8String(QCoreApplication::tr("Winter"));
-		case Anime::SeriesSeason::SUMMER: return Strings::ToUtf8String(QCoreApplication::tr("Summer"));
-		case Anime::SeriesSeason::FALL: return Strings::ToUtf8String(QCoreApplication::tr("Fall"));
-		case Anime::SeriesSeason::SPRING: return Strings::ToUtf8String(QCoreApplication::tr("Spring"));
+		case Anime::SeriesSeason::Winter: return Strings::ToUtf8String(QCoreApplication::tr("Winter"));
+		case Anime::SeriesSeason::Summer: return Strings::ToUtf8String(QCoreApplication::tr("Summer"));
+		case Anime::SeriesSeason::Fall: return Strings::ToUtf8String(QCoreApplication::tr("Fall"));
+		case Anime::SeriesSeason::Spring: return Strings::ToUtf8String(QCoreApplication::tr("Spring"));
 		default:
-		case Anime::SeriesSeason::UNKNOWN: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
+		case Anime::SeriesSeason::Unknown: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
 	}
 }
 
 std::string ToLocalString(const Anime::SeriesStatus status) {
 	switch (status) {
-		case Anime::SeriesStatus::RELEASING: return Strings::ToUtf8String(QCoreApplication::tr("Currently airing"));
-		case Anime::SeriesStatus::FINISHED: return Strings::ToUtf8String(QCoreApplication::tr("Finished airing"));
-		case Anime::SeriesStatus::NOT_YET_RELEASED: return Strings::ToUtf8String(QCoreApplication::tr("Not yet aired"));
-		case Anime::SeriesStatus::CANCELLED: return Strings::ToUtf8String(QCoreApplication::tr("Cancelled"));
-		case Anime::SeriesStatus::HIATUS: return Strings::ToUtf8String(QCoreApplication::tr("On hiatus"));
+		case Anime::SeriesStatus::Releasing: return Strings::ToUtf8String(QCoreApplication::tr("Currently airing"));
+		case Anime::SeriesStatus::Finished: return Strings::ToUtf8String(QCoreApplication::tr("Finished airing"));
+		case Anime::SeriesStatus::NotYetReleased: return Strings::ToUtf8String(QCoreApplication::tr("Not yet aired"));
+		case Anime::SeriesStatus::Cancelled: return Strings::ToUtf8String(QCoreApplication::tr("Cancelled"));
+		case Anime::SeriesStatus::Hiatus: return Strings::ToUtf8String(QCoreApplication::tr("On hiatus"));
 		default:
-		case Anime::SeriesStatus::UNKNOWN: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
+		case Anime::SeriesStatus::Unknown: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
 	}
 }
 
-std::string ToLocalString(const Anime::Services service) {
+std::string ToLocalString(const Anime::Service service) {
 	switch (service) {
-		case Anime::Services::ANILIST: return Strings::ToUtf8String(QCoreApplication::tr("AniList"));
+		case Anime::Service::AniList: return Strings::ToUtf8String(QCoreApplication::tr("AniList"));
 		default:
-		case Anime::Services::NONE: return Strings::ToUtf8String(QCoreApplication::tr("None"));
+		case Anime::Service::None: return Strings::ToUtf8String(QCoreApplication::tr("None"));
 	}
 }
 
 std::string ToLocalString(const Anime::TitleLanguage language) {
 	switch (language) {
-		case Anime::TitleLanguage::NATIVE: return Strings::ToUtf8String(QCoreApplication::tr("Native"));
-		case Anime::TitleLanguage::ENGLISH: return Strings::ToUtf8String(QCoreApplication::tr("English"));
+		case Anime::TitleLanguage::Native: return Strings::ToUtf8String(QCoreApplication::tr("Native"));
+		case Anime::TitleLanguage::English: return Strings::ToUtf8String(QCoreApplication::tr("English"));
 		default:
-		case Anime::TitleLanguage::ROMAJI: return Strings::ToUtf8String(QCoreApplication::tr("Romaji"));
+		case Anime::TitleLanguage::Romaji: return Strings::ToUtf8String(QCoreApplication::tr("Romaji"));
 	}
 }
 
 std::string ToLocalString(const Anime::ScoreFormat format) {
 	switch (format) {
-		case Anime::ScoreFormat::POINT_3: return Strings::ToUtf8String(QCoreApplication::tr("3-point"));
-		case Anime::ScoreFormat::POINT_5: return Strings::ToUtf8String(QCoreApplication::tr("5-point"));
-		case Anime::ScoreFormat::POINT_10: return Strings::ToUtf8String(QCoreApplication::tr("10-point"));
-		case Anime::ScoreFormat::POINT_10_DECIMAL:
-			return Strings::ToUtf8String(QCoreApplication::tr("10-point (Decimal)"));
+		case Anime::ScoreFormat::Point3: return Strings::ToUtf8String(QCoreApplication::tr("3-point"));
+		case Anime::ScoreFormat::Point5: return Strings::ToUtf8String(QCoreApplication::tr("5-point"));
+		case Anime::ScoreFormat::Point10: return Strings::ToUtf8String(QCoreApplication::tr("10-point"));
+		case Anime::ScoreFormat::Point10Decimal:
+			return Strings::ToUtf8String(QCoreApplication::tr("10-point Decimal"));
 		default:
-		case Anime::ScoreFormat::POINT_100: return Strings::ToUtf8String(QCoreApplication::tr("100-point"));
+		case Anime::ScoreFormat::Point100: return Strings::ToUtf8String(QCoreApplication::tr("100-point"));
 	}
 }
 
--- a/src/gui/translate/config.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/translate/config.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -1,28 +1,40 @@
 #include "core/config.h"
+#include "core/strings.h"
 #include "gui/translate/config.h"
 
+#include <QCoreApplication>
+
 #include <unordered_map>
 
 namespace Translate {
 
-Themes ToTheme(const std::string& theme) {
-	const std::unordered_map<std::string, Themes> map = {
-	    {"Default", Themes::OS   },
-        {"Light",   Themes::LIGHT},
-        {"Dark",    Themes::DARK }
+Theme::Theme ToTheme(const std::string& theme) {
+	const std::unordered_map<std::string, Theme::Theme> map = {
+	    {"Default", Theme::Theme::Default   },
+        {"Light",   Theme::Theme::Light},
+        {"Dark",    Theme::Theme::Dark }
     };
 
 	if (map.find(theme) == map.end())
-		return Themes::OS;
+		return Theme::Theme::Default;
 	return map.at(theme);
 }
 
-std::string ToString(const Themes& theme) {
+std::string ToString(const Theme::Theme& theme) {
 	switch (theme) {
 		default:
-		case Themes::OS: return "Default";
-		case Themes::LIGHT: return "Light";
-		case Themes::DARK: return "Dark";
+		case Theme::Theme::Default: return "Default";
+		case Theme::Theme::Light: return "Light";
+		case Theme::Theme::Dark: return "Dark";
+	}
+}
+
+std::string ToLocalString(const Theme::Theme& theme) {
+	switch (theme) {
+		default:
+		case Theme::Theme::Default: return Strings::ToUtf8String(QCoreApplication::tr("Default"));
+		case Theme::Theme::Light: return Strings::ToUtf8String(QCoreApplication::tr("Light"));
+		case Theme::Theme::Dark: return Strings::ToUtf8String(QCoreApplication::tr("Dark"));
 	}
 }
 
--- a/src/gui/window.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/gui/window.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -484,7 +484,7 @@
 }
 
 void MainWindow::AsyncSynchronize(QAction* action, QStackedWidget* stack) {
-	if (session.config.service == Anime::Services::NONE) {
+	if (session.config.service == Anime::Service::None) {
 		QMessageBox msg;
 		msg.setWindowTitle(tr("Error synchronizing with service!"));
 		msg.setText(tr("It seems you haven't yet selected a service to use."));
--- a/src/services/anilist.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/services/anilist.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -74,21 +74,21 @@
 
 void ParseListStatus(std::string status, Anime::Anime& anime) {
 	static const std::unordered_map<std::string, Anime::ListStatus> map = {
-	    {"CURRENT",   Anime::ListStatus::CURRENT  },
-	    {"PLANNING",  Anime::ListStatus::PLANNING },
-	    {"COMPLETED", Anime::ListStatus::COMPLETED},
-	    {"DROPPED",   Anime::ListStatus::DROPPED  },
-	    {"PAUSED",    Anime::ListStatus::PAUSED   }
+	    {"CURRENT",   Anime::ListStatus::Current  },
+	    {"PLANNING",  Anime::ListStatus::Planning },
+	    {"COMPLETED", Anime::ListStatus::Completed},
+	    {"DROPPED",   Anime::ListStatus::Dropped  },
+	    {"PAUSED",    Anime::ListStatus::Paused   }
     };
 
 	if (status == "REPEATING") {
 		anime.SetUserIsRewatching(true);
-		anime.SetUserStatus(Anime::ListStatus::CURRENT);
+		anime.SetUserStatus(Anime::ListStatus::Current);
 		return;
 	}
 
 	if (map.find(status) == map.end()) {
-		anime.SetUserStatus(Anime::ListStatus::NOT_IN_LIST);
+		anime.SetUserStatus(Anime::ListStatus::NotInList);
 		return;
 	}
 
@@ -96,14 +96,14 @@
 }
 
 std::string ListStatusToString(const Anime::Anime& anime) {
-	if (anime.GetUserIsRewatching())
+	if (anime.GetUserIsRewatching() && anime.GetUserStatus() == Anime::ListStatus::Current)
 		return "REWATCHING";
 
 	switch (anime.GetUserStatus()) {
-		case Anime::ListStatus::PLANNING: return "PLANNING";
-		case Anime::ListStatus::COMPLETED: return "COMPLETED";
-		case Anime::ListStatus::DROPPED: return "DROPPED";
-		case Anime::ListStatus::PAUSED: return "PAUSED";
+		case Anime::ListStatus::Planning: return "PLANNING";
+		case Anime::ListStatus::Completed: return "COMPLETED";
+		case Anime::ListStatus::Dropped: return "DROPPED";
+		case Anime::ListStatus::Paused: return "PAUSED";
 		default: break;
 	}
 	return "CURRENT";
@@ -136,7 +136,7 @@
 	anime.SetPosterUrl(JSON::GetString<std::string>(json, "/coverImage/large"_json_pointer, ""));
 
 	anime.SetAudienceScore(JSON::GetNumber(json, "/averageScore"_json_pointer, 0));
-	anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, "")));
+	// anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, "")));
 	anime.SetDuration(JSON::GetNumber(json, "/duration"_json_pointer, 0));
 
 	std::string synopsis = JSON::GetString<std::string>(json, "/description"_json_pointer, "");
--- a/src/services/services.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/services/services.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -7,28 +7,28 @@
 
 void Synchronize() {
 	switch (session.config.service) {
-		case Anime::Services::ANILIST: AniList::GetAnimeList(); break;
+		case Anime::Service::AniList: AniList::GetAnimeList(); break;
 		default: break;
 	}
 }
 
 std::vector<int> Search(const std::string& search) {
 	switch (session.config.service) {
-		case Anime::Services::ANILIST: return AniList::Search(search);
+		case Anime::Service::AniList: return AniList::Search(search);
 		default: return {};
 	}
 }
 
 void UpdateAnimeEntry(int id) {
 	switch (session.config.service) {
-		case Anime::Services::ANILIST: AniList::UpdateAnimeEntry(id); break;
+		case Anime::Service::AniList: AniList::UpdateAnimeEntry(id); break;
 		default: break;
 	}
 }
 
 bool Authorize() {
 	switch (session.config.service) {
-		case Anime::Services::ANILIST: return AniList::AuthorizeUser();
+		case Anime::Service::AniList: return AniList::AuthorizeUser();
 		default: return true;
 	}
 }
--- a/src/track/media.cc	Thu Apr 18 17:24:42 2024 -0400
+++ b/src/track/media.cc	Fri Apr 19 13:24:06 2024 -0400
@@ -33,10 +33,8 @@
 bool GetCurrentlyPlaying(std::vector<std::string>& vec) {
 	std::vector<animone::Result> results;
 
-	if (!GetCurrentlyPlayingResults(results)) {
-		std::cout << "whoooops!" << std::endl;
+	if (!GetCurrentlyPlayingResults(results))
 		return false;
-	}
 
 	bool success = false;