diff src/gui/dialog/information.cc @ 81:9b2b41f83a5e

boring: mass rename to cc because this is a very unix-y project, it makes more sense to use the 'cc' extension
author Paper <mrpapersonic@gmail.com>
date Mon, 23 Oct 2023 12:07:27 -0400
parents src/gui/dialog/information.cpp@6f7385bd334c
children d02fdf1d6708
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/dialog/information.cc	Mon Oct 23 12:07:27 2023 -0400
@@ -0,0 +1,281 @@
+#include "gui/dialog/information.h"
+#include "core/anime.h"
+#include "core/anime_db.h"
+#include "core/array.h"
+#include "core/strings.h"
+#include "gui/pages/anime_list.h"
+#include "gui/translate/anime.h"
+#include "gui/widgets/anime_info.h"
+#include "gui/widgets/optional_date.h"
+#include "gui/widgets/poster.h"
+#include "gui/widgets/text.h"
+#include "gui/window.h"
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDateEdit>
+#include <QDebug>
+#include <QDialogButtonBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPlainTextEdit>
+#include <QSpinBox>
+#include <QStringList>
+#include <QTextStream>
+#include <QVBoxLayout>
+#include <functional>
+
+/* TODO: Taiga disables rendering of the tab widget entirely when the anime is not part of a list,
+   which sucks. Think of a better way to implement this later. */
+void InformationDialog::SaveData() {
+	Anime::Anime& anime = Anime::db.items[id];
+	anime.SetUserProgress(progress);
+	anime.SetUserScore(score);
+	anime.SetUserIsRewatching(rewatching);
+	anime.SetUserStatus(status);
+	anime.SetUserNotes(notes);
+	anime.SetUserDateStarted(started);
+	anime.SetUserDateCompleted(completed);
+}
+
+InformationDialog::InformationDialog(const Anime::Anime& anime, std::function<void()> accept, QWidget* parent)
+    : QDialog(parent) {
+	setFixedSize(842, 613);
+	setWindowTitle(tr("Anime Information"));
+	setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
+
+	{
+		QPalette pal(palette());
+		pal.setColor(QPalette::Window, pal.color(QPalette::Base));
+		setPalette(pal);
+	}
+
+	QWidget* widget = new QWidget(this);
+
+	/* "sidebar", includes... just the anime image :) */
+	QWidget* sidebar = new QWidget(widget);
+	QVBoxLayout* sidebar_layout = new QVBoxLayout(sidebar);
+	Poster* poster = new Poster(anime.GetId(), sidebar);
+	sidebar_layout->addWidget(poster);
+	sidebar_layout->setContentsMargins(0, 0, 0, 0);
+	sidebar_layout->addStretch();
+
+	/* main widget */
+	QWidget* main_widget = new QWidget(widget);
+
+	main_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+	id = anime.GetId();
+	/* anime title header text */
+	TextWidgets::Title* anime_title =
+	    new TextWidgets::Title(Strings::ToQString(anime.GetUserPreferredTitle()), main_widget);
+
+	/* tabbed widget */
+	QTabWidget* tabbed_widget = new QTabWidget(main_widget);
+	tabbed_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+	/* main info tab */
+	AnimeInfoWidget* main_information_widget = new AnimeInfoWidget(anime, tabbed_widget);
+
+	{
+		QPalette pal(main_information_widget->palette());
+		pal.setColor(QPalette::Base, pal.color(QPalette::Window));
+		main_information_widget->setPalette(pal);
+	}
+
+	QWidget* settings_widget = new QWidget(tabbed_widget);
+	settings_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
+
+	QVBoxLayout* settings_layout = new QVBoxLayout(settings_widget);
+	settings_layout->addWidget(new TextWidgets::Header(tr("Anime list"), settings_widget));
+
+	QWidget* sg_anime_list_content = new QWidget(settings_widget);
+
+	QVBoxLayout* al_layout = new QVBoxLayout(sg_anime_list_content);
+	al_layout->setSpacing(5);
+	al_layout->setContentsMargins(12, 0, 0, 0);
+
+#define LAYOUT_HORIZ_SPACING 25
+#define LAYOUT_VERT_SPACING  5
+#define LAYOUT_ITEM_WIDTH    175
+/* Creates a subsection that takes up whatever space is necessary */
+#define CREATE_FULL_WIDTH_SUBSECTION(x) \
+	{ \
+		QWidget* subsection = new QWidget(section); \
+		subsection->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); \
+		QVBoxLayout* subsection_layout = new QVBoxLayout(subsection); \
+		subsection_layout->setSpacing(LAYOUT_VERT_SPACING); \
+		subsection_layout->setContentsMargins(0, 0, 0, 0); \
+		x; \
+		layout->addWidget(subsection, 0, Qt::AlignBottom); \
+	}
+
+/* Creates a section in the parent `a` */
+#define CREATE_FULL_WIDTH_SECTION(a, x) \
+	{ \
+		QWidget* section = new QWidget(a); \
+		QHBoxLayout* layout = new QHBoxLayout(section); \
+		layout->setSpacing(LAYOUT_HORIZ_SPACING); \
+		layout->setContentsMargins(0, 0, 0, 0); \
+		x; \
+		a->layout()->addWidget(section); \
+	}
+
+/* Creates a subsection with a width of 175 */
+#define CREATE_SUBSECTION(x) CREATE_FULL_WIDTH_SUBSECTION(x subsection->setFixedWidth(LAYOUT_ITEM_WIDTH);)
+/* Creates a section in the parent `a` */
+#define CREATE_SECTION(a, x) CREATE_FULL_WIDTH_SECTION(a, x layout->addStretch();)
+
+	CREATE_SECTION(sg_anime_list_content, {
+		/* Episodes watched section */
+		CREATE_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Episodes watched:"), subsection));
+
+			QSpinBox* spin_box = new QSpinBox(subsection);
+			connect(spin_box, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int i) { progress = i; });
+			spin_box->setRange(0, anime.GetEpisodes());
+			spin_box->setSingleStep(1);
+			spin_box->setValue(progress = anime.GetUserProgress());
+			subsection_layout->addWidget(spin_box);
+		});
+		CREATE_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr(" "), subsection));
+
+			QCheckBox* checkbox = new QCheckBox(tr("Rewatching"));
+			connect(checkbox, QOverload<int>::of(&QCheckBox::stateChanged), this,
+			        [this](int state) { rewatching = (state == Qt::Checked); });
+			checkbox->setCheckState(anime.GetUserIsRewatching() ? Qt::Checked : Qt::Unchecked);
+			subsection_layout->addWidget(checkbox);
+		});
+	});
+	CREATE_SECTION(sg_anime_list_content, {
+		/* Status & score section */
+		CREATE_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Status:"), subsection));
+
+			QStringList string_list;
+			for (unsigned int i = 0; i < ARRAYSIZE(Anime::ListStatuses); i++)
+				string_list.append(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])));
+
+			QComboBox* combo_box = new QComboBox(subsection);
+			combo_box->addItems(string_list);
+			connect(combo_box, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+			        [this](int i) { status = Anime::ListStatuses[i]; });
+			combo_box->setCurrentIndex(static_cast<int>(status = anime.GetUserStatus()) - 1);
+			subsection_layout->addWidget(combo_box);
+		});
+		CREATE_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Score:"), subsection));
+
+			QSpinBox* spin_box = new QSpinBox(subsection);
+			connect(spin_box, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int i) { score = i; });
+			spin_box->setRange(0, 100);
+			spin_box->setSingleStep(5);
+			spin_box->setValue(score = anime.GetUserScore());
+			subsection_layout->addWidget(spin_box);
+		});
+	});
+	CREATE_FULL_WIDTH_SECTION(sg_anime_list_content, {
+		/* Notes section */
+		CREATE_FULL_WIDTH_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Notes:"), subsection));
+
+			QLineEdit* line_edit = new QLineEdit(subsection);
+			connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) {
+				/* this sucks but I don't really want to implement anything smarter :) */
+				notes = Strings::ToUtf8String(text);
+			});
+			line_edit->setText(Strings::ToQString(notes = anime.GetUserNotes()));
+			line_edit->setPlaceholderText(tr("Enter your notes about this anime"));
+			subsection_layout->addWidget(line_edit);
+		});
+	});
+	CREATE_SECTION(sg_anime_list_content, {
+		/* Dates section */
+		CREATE_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Date started:"), subsection));
+
+			OptionalDate* date = new OptionalDate(true, subsection);
+			connect(date, &OptionalDate::DataChanged, this,
+			        [this](bool enabled, Date date) { started = (enabled) ? date : Date(); });
+			started = anime.GetUserDateStarted();
+			if (!started.IsValid()) {
+				date->SetEnabled(false);
+				started = anime.GetAirDate();
+			}
+			date->SetDate(started);
+			subsection_layout->addWidget(date);
+		});
+		CREATE_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Date completed:"), subsection));
+
+			OptionalDate* date = new OptionalDate(true, subsection);
+			connect(date, &OptionalDate::DataChanged, this,
+			        [this](bool enabled, Date date) { completed = (enabled) ? date : Date(); });
+			completed = anime.GetUserDateCompleted();
+			if (!completed.IsValid()) {
+				date->SetEnabled(false);
+				completed = anime.GetAirDate();
+			}
+			date->SetDate(completed);
+			subsection_layout->addWidget(date);
+		});
+	});
+
+	settings_layout->addWidget(sg_anime_list_content);
+
+	settings_layout->addWidget(new TextWidgets::Header(tr("Local settings"), settings_widget));
+
+	QWidget* sg_local_content = new QWidget(settings_widget);
+	QVBoxLayout* sg_local_layout = new QVBoxLayout(sg_local_content);
+	sg_local_layout->setSpacing(5);
+	sg_local_layout->setContentsMargins(12, 0, 0, 0);
+
+	CREATE_FULL_WIDTH_SECTION(sg_local_content, {
+		/* Alternative titles */
+		CREATE_FULL_WIDTH_SUBSECTION({
+			subsection_layout->addWidget(new QLabel(tr("Alternative titles:"), subsection));
+
+			QLineEdit* line_edit = new QLineEdit("", subsection);
+			line_edit->setPlaceholderText(
+			    tr("Enter alternative titles here, separated by a semicolon (i.e. Title 1; Title 2)"));
+			subsection_layout->addWidget(line_edit);
+
+			QCheckBox* checkbox = new QCheckBox(tr("Use the first alternative title to search for torrents"));
+			subsection_layout->addWidget(checkbox);
+		});
+	});
+#undef CREATE_SECTION
+#undef CREATE_SUBSECTION
+#undef CREATE_FULL_WIDTH_SECTION
+#undef CREATE_FULL_WIDTH_SUBSECTION
+
+	settings_layout->addWidget(sg_local_content);
+	settings_layout->addStretch();
+
+	tabbed_widget->addTab(main_information_widget, tr("Main information"));
+	tabbed_widget->addTab(settings_widget, tr("My list and settings"));
+
+	QVBoxLayout* main_layout = new QVBoxLayout(main_widget);
+	main_layout->addWidget(anime_title);
+	main_layout->addWidget(tabbed_widget);
+	main_layout->setContentsMargins(0, 0, 0, 0);
+
+	QHBoxLayout* layout = new QHBoxLayout(widget);
+	layout->addWidget(sidebar);
+	layout->addWidget(main_widget);
+	layout->setSpacing(12);
+
+	QDialogButtonBox* button_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+	connect(button_box, &QDialogButtonBox::accepted, this, [this, accept] {
+		SaveData();
+		accept();
+		QDialog::accept();
+	});
+	connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+	QVBoxLayout* buttons_layout = new QVBoxLayout(this);
+	buttons_layout->addWidget(widget);
+	buttons_layout->addWidget(button_box, 0, Qt::AlignBottom);
+}
+
+#include "gui/dialog/moc_information.cpp"