diff src/gui/window.cc @ 273:f31305b9f60a

*: various code safety changes this also makes the code build on Qt 5.7. I can't test it though because I don't have it working... FAIL!
author Paper <paper@paper.us.eu.org>
date Thu, 18 Apr 2024 16:53:17 -0400
parents 862d0d8619f6
children 657fda1b9cac
line wrap: on
line diff
--- a/src/gui/window.cc	Thu Apr 18 16:51:35 2024 -0400
+++ b/src/gui/window.cc	Thu Apr 18 16:53:17 2024 -0400
@@ -48,34 +48,50 @@
 #	include "sys/win32/dark_theme.h"
 #endif
 
-void PlayingThread::run() {
+void MainWindowPlayingThread::run() {
 	std::vector<std::string> files;
 	Track::Media::GetCurrentlyPlaying(files);
 	emit Done(files);
 }
 
-MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
+MainWindowAsyncSynchronizeThread::MainWindowAsyncSynchronizeThread(QAction* action, AnimeListPage* page, QObject* parent) : QThread(parent) {
+	SetAction(action);
+	SetPage(page);
+}
+
+void MainWindowAsyncSynchronizeThread::SetAction(QAction* action) {
+	action_ = action;
+}
+
+void MainWindowAsyncSynchronizeThread::SetPage(AnimeListPage* page) {
+	page_ = page;
+}
+
+void MainWindowAsyncSynchronizeThread::run() {
+	action_->setEnabled(false);
+	Services::Synchronize();
+	page_->Refresh();
+	action_->setEnabled(true);
+}
+
+MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), async_synchronize_thread_(nullptr, nullptr) {
 	setWindowIcon(QIcon(":/icons/favicon.png"));
 
-	main_widget.reset(new QWidget(this));
-	new QHBoxLayout(main_widget.get());
+	sidebar_.setFixedWidth(128);
+	sidebar_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+
+	connect(&sidebar_, &SideBar::CurrentItemChanged, &stack_, &QStackedWidget::setCurrentIndex);
+
+	new QHBoxLayout(&main_widget_);
 
 	AddMainWidgets();
-	setCentralWidget(main_widget.get());
+	setCentralWidget(&main_widget_);
 
 	CreateBars();
 
-	NowPlayingPage* page = reinterpret_cast<NowPlayingPage*>(stack->widget(static_cast<int>(Pages::NOW_PLAYING)));
-
-	qRegisterMetaType<std::vector<std::string>>();
+	NowPlayingPage* page = reinterpret_cast<NowPlayingPage*>(stack_.widget(static_cast<int>(Pages::NOW_PLAYING)));
 
-	/* This thread will be destroyed on
-	 * close of the program OR on the destruction
-	 * of MainWindow
-	 */
-	thread.reset(new PlayingThread(this));
-
-	connect(thread.get(), &PlayingThread::Done, this, [page](const std::vector<std::string>& files) {
+	connect(&playing_thread_, &MainWindowPlayingThread::Done, this, [page](const std::vector<std::string>& files) {
 		for (const auto& file : files) {
 			anitomy::Anitomy anitomy;
 			anitomy.Parse(Strings::ToWstring(file));
@@ -92,13 +108,11 @@
 		}
 	});
 
-	QTimer* timer = new QTimer(this);
-
-	connect(timer, &QTimer::timeout, this, [this, page] {
-		if (!thread.get() || thread->isRunning())
+	connect(&playing_thread_timer_, &QTimer::timeout, this, [this] {
+		if (playing_thread_.isRunning())
 			return;
 
-		thread->start();
+		playing_thread_.start();
 	});
 
 #ifdef MACOSX
@@ -106,53 +120,42 @@
 		return;
 #endif
 
-	timer->start(5000);
+	playing_thread_timer_.start(5000);
 }
 
 void MainWindow::AddMainWidgets() {
 	int page = static_cast<int>(Pages::ANIME_LIST);
 
-	if (sidebar.get()) {
-		main_widget->layout()->removeWidget(sidebar.get());
-		sidebar.reset();
-	}
+	sidebar_.clear();
 
-	if (stack.get()) {
-		page = stack->currentIndex();
-		main_widget->layout()->removeWidget(stack.get());
-	}
+	sidebar_.AddItem(tr("Now Playing"), SideBar::CreateIcon(":/icons/16x16/film.png"));
+	sidebar_.AddSeparator();
+	sidebar_.AddItem(tr("Anime List"), SideBar::CreateIcon(":/icons/16x16/document-list.png"));
+	sidebar_.AddItem(tr("History"), SideBar::CreateIcon(":/icons/16x16/clock-history-frame.png"));
+	sidebar_.AddItem(tr("Statistics"), SideBar::CreateIcon(":/icons/16x16/chart.png"));
+	sidebar_.AddSeparator();
+	sidebar_.AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png"));
+	sidebar_.AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png"));
+	sidebar_.AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png"));
 
-	sidebar.reset(new SideBar(main_widget.get()));
-	sidebar->setFixedWidth(128);
-	sidebar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+	while (stack_.count())
+		stack_.removeWidget(stack_.widget(0));
 
-	sidebar->AddItem(tr("Now Playing"), SideBar::CreateIcon(":/icons/16x16/film.png"));
-	sidebar->AddSeparator();
-	sidebar->AddItem(tr("Anime List"), SideBar::CreateIcon(":/icons/16x16/document-list.png"));
-	sidebar->AddItem(tr("History"), SideBar::CreateIcon(":/icons/16x16/clock-history-frame.png"));
-	sidebar->AddItem(tr("Statistics"), SideBar::CreateIcon(":/icons/16x16/chart.png"));
-	sidebar->AddSeparator();
-	sidebar->AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png"));
-	sidebar->AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png"));
-	sidebar->AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png"));
-
-	stack.reset(new QStackedWidget(main_widget.get()));
-
-	stack->addWidget(new NowPlayingPage(main_widget.get()));
+	/* can we allocate these on the stack? */
+	stack_.addWidget(new NowPlayingPage(&main_widget_));
+	/* ---- */
+	stack_.addWidget(new AnimeListPage(&main_widget_));
+	stack_.addWidget(new HistoryPage(&main_widget_));
+	stack_.addWidget(new StatisticsPage(&main_widget_));
 	/* ---- */
-	stack->addWidget(new AnimeListPage(main_widget.get()));
-	stack->addWidget(new HistoryPage(main_widget.get()));
-	stack->addWidget(new StatisticsPage(main_widget.get()));
-	/* ---- */
-	stack->addWidget(new SearchPage(main_widget.get()));
-	stack->addWidget(new SeasonsPage(main_widget.get()));
-	stack->addWidget(new TorrentsPage(main_widget.get()));
+	stack_.addWidget(new SearchPage(&main_widget_));
+	stack_.addWidget(new SeasonsPage(&main_widget_));
+	stack_.addWidget(new TorrentsPage(&main_widget_));
 
-	connect(sidebar.get(), &SideBar::CurrentItemChanged, stack.get(), &QStackedWidget::setCurrentIndex);
-	sidebar->SetCurrentItem(page);
+	sidebar_.SetCurrentItem(page);
 
-	main_widget->layout()->addWidget(sidebar.get());
-	main_widget->layout()->addWidget(stack.get());
+	main_widget_.layout()->addWidget(&sidebar_);
+	main_widget_.layout()->addWidget(&stack_);
 }
 
 void MainWindow::CreateBars() {
@@ -201,7 +204,7 @@
 				sync_action = menu->addAction(tr("Synchronize &list"));
 
 				connect(sync_action, &QAction::triggered, this,
-				        [this, sync_action] { AsyncSynchronize(sync_action, stack.get()); });
+				        [this, sync_action] { AsyncSynchronize(sync_action, &stack_); });
 
 				sync_action->setIcon(QIcon(":/icons/24x24/arrow-circle-double-135.png"));
 				sync_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_S));
@@ -290,48 +293,48 @@
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("&Now Playing")));
 				action->setCheckable(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(0); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(0); });
 			}
 
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("&Anime List")));
 				action->setCheckable(true);
 				action->setChecked(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(1); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(1); });
 			}
 
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("&History")));
 				action->setCheckable(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(2); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(2); });
 			}
 
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("&Statistics")));
 				action->setCheckable(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(3); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(3); });
 			}
 
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("S&earch")));
 				action->setCheckable(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(4); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(4); });
 			}
 
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("Se&asons")));
 				action->setCheckable(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(5); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(5); });
 			}
 
 			{
 				QAction* action = pages_group->addAction(menu->addAction(tr("&Torrents")));
 				action->setCheckable(true);
-				connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(6); });
+				connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(6); });
 			}
 
-			/* pain in my ass */
-			connect(sidebar.get(), &SideBar::CurrentItemChanged, this, [pages_group](int index) {
+			/* pain in the ass */
+			connect(&sidebar_, &SideBar::CurrentItemChanged, this, [pages_group](int index) {
 				QAction* checked = pages_group->checkedAction();
 
 				const QList<QAction*>& actions = pages_group->actions();
@@ -495,12 +498,13 @@
 		}
 	}
 
-	QThreadPool::globalInstance()->start([stack, action] {
-		action->setEnabled(false);
-		Services::Synchronize();
-		reinterpret_cast<AnimeListPage*>(stack->widget(static_cast<int>(Pages::ANIME_LIST)))->Refresh();
-		action->setEnabled(true);
-	});
+	/* FIXME: make this use a QThread; this is *very* unsafe */
+	AnimeListPage* page = reinterpret_cast<AnimeListPage*>(stack->widget(static_cast<int>(Pages::ANIME_LIST)));
+	if (!async_synchronize_thread_.isRunning()) {
+		async_synchronize_thread_.SetAction(action);
+		async_synchronize_thread_.SetPage(page);
+		async_synchronize_thread_.start();
+	}
 }
 
 void MainWindow::RetranslateUI() {