view src/gui/dialog/information.cc @ 101:c537996cf67b

*: multitude of config changes 1. theme is now configurable from the settings menu (but you have to restart for it to apply) 2. config is now stored in an INI file, with no method of conversion from json (this repo is private-ish anyway)
author Paper <mrpapersonic@gmail.com>
date Fri, 03 Nov 2023 14:06:02 -0400
parents e6fab256ddc4
children 6d8da6e64d61
line wrap: on
line source

#include "gui/dialog/information.h"
#include "core/anime.h"
#include "core/anime_db.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.SetUserProgress(_progress);
	anime.SetUserScore(_score);
	anime.SetUserIsRewatching(_rewatching);
	anime.SetUserStatus(_status);
	anime.SetUserNotes(_notes);
	anime.SetUserDateStarted(_started);
	anime.SetUserDateCompleted(_completed);
}

InformationDialog::InformationDialog(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, 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);

	/* 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);

	constexpr int LAYOUT_HORIZ_SPACING = 25;
	constexpr int LAYOUT_VERT_SPACING  = 5;
	constexpr int LAYOUT_ITEM_WIDTH    = 175;

	QVBoxLayout* al_layout = new QVBoxLayout(sg_anime_list_content);
	al_layout->setSpacing(LAYOUT_VERT_SPACING);
	al_layout->setContentsMargins(12, 0, 0, 0);

	const auto CREATE_SECTION = [](QWidget* parent, std::function<void(QWidget*, QGridLayout*)> x) {
		QWidget* section = new QWidget(parent);
		QGridLayout* layout = new QGridLayout(section);
		layout->setHorizontalSpacing(LAYOUT_HORIZ_SPACING);
		layout->setVerticalSpacing(LAYOUT_VERT_SPACING);
		layout->setContentsMargins(0, 0, 0, 0);
		x(section, layout);
		parent->layout()->addWidget(section);
	};

	CREATE_SECTION(sg_anime_list_content, [this, &anime](QWidget* section, QGridLayout* layout){
		/* Episodes watched... */
		layout->addWidget(new QLabel(tr("Episodes watched:"), section), 0, 0);

		QSpinBox* spin_box = new QSpinBox(section);
		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());
		spin_box->setFixedWidth(LAYOUT_ITEM_WIDTH);
		layout->addWidget(spin_box, 1, 0);

		/* Rewatching? */
		QCheckBox* checkbox = new QCheckBox(tr("Rewatching"));
		connect(checkbox, QOverload<int>::of(&QCheckBox::stateChanged), this,
		        [this](int state) { _rewatching = (state == Qt::Checked); });
		checkbox->setCheckState((_rewatching = anime.GetUserIsRewatching()) ? Qt::Checked : Qt::Unchecked);
		checkbox->setFixedWidth(LAYOUT_ITEM_WIDTH);
		layout->addWidget(checkbox, 1, 1);
		layout->setColumnStretch(layout->columnCount(), 1);
	});

	CREATE_SECTION(sg_anime_list_content, [this, &anime](QWidget* section, QGridLayout* layout){
		/* Status */
		layout->addWidget(new QLabel(tr("Status:"), section), 0, 0);

		QComboBox* combo_box = new QComboBox(section);

		for (unsigned int i = 0; i < Anime::ListStatuses.size(); i++)
			combo_box->addItem(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])), static_cast<int>(Anime::ListStatuses[i]));

		connect(combo_box, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this, combo_box](int) {
			_status = static_cast<Anime::ListStatus>(combo_box->currentData().toInt());
		});
		/* this should NEVER, EVER, be NOT_IN_LIST */
		combo_box->setCurrentIndex(static_cast<int>(_status = anime.GetUserStatus()) - 1);
		combo_box->setFixedWidth(LAYOUT_ITEM_WIDTH);
		layout->addWidget(combo_box, 1, 0);

		/* Score */
		layout->addWidget(new QLabel(tr("Score:"), section), 0, 1);

		QSpinBox* spin_box = new QSpinBox(section);
		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());
		spin_box->setFixedWidth(LAYOUT_ITEM_WIDTH);
		layout->addWidget(spin_box, 1, 1);
		layout->setColumnStretch(layout->columnCount(), 1);
	});

	CREATE_SECTION(sg_anime_list_content, [this, &anime](QWidget* section, QGridLayout* layout){
		layout->addWidget(new QLabel(tr("Notes:"), section), 0, 0);

		QLineEdit* line_edit = new QLineEdit(section);
		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"));
		layout->addWidget(line_edit, 1, 0);
	});

	CREATE_SECTION(sg_anime_list_content, [this, &anime](QWidget* section, QGridLayout* layout){
		/* Started */
		layout->addWidget(new QLabel(tr("Date started:"), section), 0, 0);

		OptionalDate* date = new OptionalDate(true, section);
		connect(date, &OptionalDate::DataChanged, this,
		        [this](bool enabled, Date date) { _started = enabled ? date : Date(); });
		date->setFixedWidth(LAYOUT_ITEM_WIDTH);
		_started = anime.GetUserDateStarted();
		if (!_started.IsValid()) {
			date->SetEnabled(false);
			_started = anime.GetAirDate();
		}
		date->SetDate(_started);
		layout->addWidget(date, 1, 0);

		/* Completed */
		layout->addWidget(new QLabel(tr("Date completed:"), section), 0, 1);

		date = new OptionalDate(true, section);
		connect(date, &OptionalDate::DataChanged, this,
		        [this](bool enabled, Date date) { _completed = enabled ? date : Date(); });
		date->setFixedWidth(LAYOUT_ITEM_WIDTH);
		_completed = anime.GetUserDateCompleted();
		if (!_completed.IsValid()) {
			date->SetEnabled(false);
			_completed = anime.GetAirDate();
		}
		date->SetDate(_completed);
		layout->addWidget(date, 1, 1);
		layout->setColumnStretch(layout->columnCount(), 1);
	});

	settings_layout->addWidget(sg_anime_list_content);

/*
	// commenting this out until it actually gets implemented :)

	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_SECTION(sg_local_content, [this, &anime](QWidget* section, QGridLayout* layout){
		layout->addWidget(new QLabel(tr("Alternative titles:"), section), 0, 0);

		QLineEdit* line_edit = new QLineEdit("", section);
		line_edit->setPlaceholderText(
		    tr("Enter alternative titles here, separated by a semicolon (i.e. Title 1; Title 2)"));
		layout->addWidget(line_edit, 1, 0);

		QCheckBox* checkbox = new QCheckBox(tr("Use the first alternative title to search for torrents"));
		layout->addWidget(checkbox, 2, 0);
	});

	settings_layout->addWidget(sg_local_content);
*/
#undef CREATE_SECTION
#undef CREATE_FULL_WIDTH_SECTION

	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);
	main_layout->setSpacing(12);

	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, &anime] {
		SaveData(anime);
		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"