Mercurial > minori
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 272:5437009cb10e | 273:f31305b9f60a |
|---|---|
| 46 # include "sys/osx/permissions.h" | 46 # include "sys/osx/permissions.h" |
| 47 #elif defined(WIN32) | 47 #elif defined(WIN32) |
| 48 # include "sys/win32/dark_theme.h" | 48 # include "sys/win32/dark_theme.h" |
| 49 #endif | 49 #endif |
| 50 | 50 |
| 51 void PlayingThread::run() { | 51 void MainWindowPlayingThread::run() { |
| 52 std::vector<std::string> files; | 52 std::vector<std::string> files; |
| 53 Track::Media::GetCurrentlyPlaying(files); | 53 Track::Media::GetCurrentlyPlaying(files); |
| 54 emit Done(files); | 54 emit Done(files); |
| 55 } | 55 } |
| 56 | 56 |
| 57 MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { | 57 MainWindowAsyncSynchronizeThread::MainWindowAsyncSynchronizeThread(QAction* action, AnimeListPage* page, QObject* parent) : QThread(parent) { |
| 58 SetAction(action); | |
| 59 SetPage(page); | |
| 60 } | |
| 61 | |
| 62 void MainWindowAsyncSynchronizeThread::SetAction(QAction* action) { | |
| 63 action_ = action; | |
| 64 } | |
| 65 | |
| 66 void MainWindowAsyncSynchronizeThread::SetPage(AnimeListPage* page) { | |
| 67 page_ = page; | |
| 68 } | |
| 69 | |
| 70 void MainWindowAsyncSynchronizeThread::run() { | |
| 71 action_->setEnabled(false); | |
| 72 Services::Synchronize(); | |
| 73 page_->Refresh(); | |
| 74 action_->setEnabled(true); | |
| 75 } | |
| 76 | |
| 77 MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), async_synchronize_thread_(nullptr, nullptr) { | |
| 58 setWindowIcon(QIcon(":/icons/favicon.png")); | 78 setWindowIcon(QIcon(":/icons/favicon.png")); |
| 59 | 79 |
| 60 main_widget.reset(new QWidget(this)); | 80 sidebar_.setFixedWidth(128); |
| 61 new QHBoxLayout(main_widget.get()); | 81 sidebar_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); |
| 82 | |
| 83 connect(&sidebar_, &SideBar::CurrentItemChanged, &stack_, &QStackedWidget::setCurrentIndex); | |
| 84 | |
| 85 new QHBoxLayout(&main_widget_); | |
| 62 | 86 |
| 63 AddMainWidgets(); | 87 AddMainWidgets(); |
| 64 setCentralWidget(main_widget.get()); | 88 setCentralWidget(&main_widget_); |
| 65 | 89 |
| 66 CreateBars(); | 90 CreateBars(); |
| 67 | 91 |
| 68 NowPlayingPage* page = reinterpret_cast<NowPlayingPage*>(stack->widget(static_cast<int>(Pages::NOW_PLAYING))); | 92 NowPlayingPage* page = reinterpret_cast<NowPlayingPage*>(stack_.widget(static_cast<int>(Pages::NOW_PLAYING))); |
| 69 | 93 |
| 70 qRegisterMetaType<std::vector<std::string>>(); | 94 connect(&playing_thread_, &MainWindowPlayingThread::Done, this, [page](const std::vector<std::string>& files) { |
| 71 | |
| 72 /* This thread will be destroyed on | |
| 73 * close of the program OR on the destruction | |
| 74 * of MainWindow | |
| 75 */ | |
| 76 thread.reset(new PlayingThread(this)); | |
| 77 | |
| 78 connect(thread.get(), &PlayingThread::Done, this, [page](const std::vector<std::string>& files) { | |
| 79 for (const auto& file : files) { | 95 for (const auto& file : files) { |
| 80 anitomy::Anitomy anitomy; | 96 anitomy::Anitomy anitomy; |
| 81 anitomy.Parse(Strings::ToWstring(file)); | 97 anitomy.Parse(Strings::ToWstring(file)); |
| 82 | 98 |
| 83 const auto& elements = anitomy.elements(); | 99 const auto& elements = anitomy.elements(); |
| 90 page->SetPlaying(Anime::db.items[id], elements); | 106 page->SetPlaying(Anime::db.items[id], elements); |
| 91 break; | 107 break; |
| 92 } | 108 } |
| 93 }); | 109 }); |
| 94 | 110 |
| 95 QTimer* timer = new QTimer(this); | 111 connect(&playing_thread_timer_, &QTimer::timeout, this, [this] { |
| 96 | 112 if (playing_thread_.isRunning()) |
| 97 connect(timer, &QTimer::timeout, this, [this, page] { | |
| 98 if (!thread.get() || thread->isRunning()) | |
| 99 return; | 113 return; |
| 100 | 114 |
| 101 thread->start(); | 115 playing_thread_.start(); |
| 102 }); | 116 }); |
| 103 | 117 |
| 104 #ifdef MACOSX | 118 #ifdef MACOSX |
| 105 if (!osx::AskForPermissions()) | 119 if (!osx::AskForPermissions()) |
| 106 return; | 120 return; |
| 107 #endif | 121 #endif |
| 108 | 122 |
| 109 timer->start(5000); | 123 playing_thread_timer_.start(5000); |
| 110 } | 124 } |
| 111 | 125 |
| 112 void MainWindow::AddMainWidgets() { | 126 void MainWindow::AddMainWidgets() { |
| 113 int page = static_cast<int>(Pages::ANIME_LIST); | 127 int page = static_cast<int>(Pages::ANIME_LIST); |
| 114 | 128 |
| 115 if (sidebar.get()) { | 129 sidebar_.clear(); |
| 116 main_widget->layout()->removeWidget(sidebar.get()); | 130 |
| 117 sidebar.reset(); | 131 sidebar_.AddItem(tr("Now Playing"), SideBar::CreateIcon(":/icons/16x16/film.png")); |
| 118 } | 132 sidebar_.AddSeparator(); |
| 119 | 133 sidebar_.AddItem(tr("Anime List"), SideBar::CreateIcon(":/icons/16x16/document-list.png")); |
| 120 if (stack.get()) { | 134 sidebar_.AddItem(tr("History"), SideBar::CreateIcon(":/icons/16x16/clock-history-frame.png")); |
| 121 page = stack->currentIndex(); | 135 sidebar_.AddItem(tr("Statistics"), SideBar::CreateIcon(":/icons/16x16/chart.png")); |
| 122 main_widget->layout()->removeWidget(stack.get()); | 136 sidebar_.AddSeparator(); |
| 123 } | 137 sidebar_.AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png")); |
| 124 | 138 sidebar_.AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png")); |
| 125 sidebar.reset(new SideBar(main_widget.get())); | 139 sidebar_.AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png")); |
| 126 sidebar->setFixedWidth(128); | 140 |
| 127 sidebar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); | 141 while (stack_.count()) |
| 128 | 142 stack_.removeWidget(stack_.widget(0)); |
| 129 sidebar->AddItem(tr("Now Playing"), SideBar::CreateIcon(":/icons/16x16/film.png")); | 143 |
| 130 sidebar->AddSeparator(); | 144 /* can we allocate these on the stack? */ |
| 131 sidebar->AddItem(tr("Anime List"), SideBar::CreateIcon(":/icons/16x16/document-list.png")); | 145 stack_.addWidget(new NowPlayingPage(&main_widget_)); |
| 132 sidebar->AddItem(tr("History"), SideBar::CreateIcon(":/icons/16x16/clock-history-frame.png")); | |
| 133 sidebar->AddItem(tr("Statistics"), SideBar::CreateIcon(":/icons/16x16/chart.png")); | |
| 134 sidebar->AddSeparator(); | |
| 135 sidebar->AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png")); | |
| 136 sidebar->AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png")); | |
| 137 sidebar->AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png")); | |
| 138 | |
| 139 stack.reset(new QStackedWidget(main_widget.get())); | |
| 140 | |
| 141 stack->addWidget(new NowPlayingPage(main_widget.get())); | |
| 142 /* ---- */ | 146 /* ---- */ |
| 143 stack->addWidget(new AnimeListPage(main_widget.get())); | 147 stack_.addWidget(new AnimeListPage(&main_widget_)); |
| 144 stack->addWidget(new HistoryPage(main_widget.get())); | 148 stack_.addWidget(new HistoryPage(&main_widget_)); |
| 145 stack->addWidget(new StatisticsPage(main_widget.get())); | 149 stack_.addWidget(new StatisticsPage(&main_widget_)); |
| 146 /* ---- */ | 150 /* ---- */ |
| 147 stack->addWidget(new SearchPage(main_widget.get())); | 151 stack_.addWidget(new SearchPage(&main_widget_)); |
| 148 stack->addWidget(new SeasonsPage(main_widget.get())); | 152 stack_.addWidget(new SeasonsPage(&main_widget_)); |
| 149 stack->addWidget(new TorrentsPage(main_widget.get())); | 153 stack_.addWidget(new TorrentsPage(&main_widget_)); |
| 150 | 154 |
| 151 connect(sidebar.get(), &SideBar::CurrentItemChanged, stack.get(), &QStackedWidget::setCurrentIndex); | 155 sidebar_.SetCurrentItem(page); |
| 152 sidebar->SetCurrentItem(page); | 156 |
| 153 | 157 main_widget_.layout()->addWidget(&sidebar_); |
| 154 main_widget->layout()->addWidget(sidebar.get()); | 158 main_widget_.layout()->addWidget(&stack_); |
| 155 main_widget->layout()->addWidget(stack.get()); | |
| 156 } | 159 } |
| 157 | 160 |
| 158 void MainWindow::CreateBars() { | 161 void MainWindow::CreateBars() { |
| 159 QMenuBar* menubar = new QMenuBar(this); | 162 QMenuBar* menubar = new QMenuBar(this); |
| 160 QAction* sync_action; | 163 QAction* sync_action; |
| 199 { | 202 { |
| 200 { | 203 { |
| 201 sync_action = menu->addAction(tr("Synchronize &list")); | 204 sync_action = menu->addAction(tr("Synchronize &list")); |
| 202 | 205 |
| 203 connect(sync_action, &QAction::triggered, this, | 206 connect(sync_action, &QAction::triggered, this, |
| 204 [this, sync_action] { AsyncSynchronize(sync_action, stack.get()); }); | 207 [this, sync_action] { AsyncSynchronize(sync_action, &stack_); }); |
| 205 | 208 |
| 206 sync_action->setIcon(QIcon(":/icons/24x24/arrow-circle-double-135.png")); | 209 sync_action->setIcon(QIcon(":/icons/24x24/arrow-circle-double-135.png")); |
| 207 sync_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_S)); | 210 sync_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_S)); |
| 208 } | 211 } |
| 209 | 212 |
| 288 pages_group->setExclusive(true); | 291 pages_group->setExclusive(true); |
| 289 | 292 |
| 290 { | 293 { |
| 291 QAction* action = pages_group->addAction(menu->addAction(tr("&Now Playing"))); | 294 QAction* action = pages_group->addAction(menu->addAction(tr("&Now Playing"))); |
| 292 action->setCheckable(true); | 295 action->setCheckable(true); |
| 293 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(0); }); | 296 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(0); }); |
| 294 } | 297 } |
| 295 | 298 |
| 296 { | 299 { |
| 297 QAction* action = pages_group->addAction(menu->addAction(tr("&Anime List"))); | 300 QAction* action = pages_group->addAction(menu->addAction(tr("&Anime List"))); |
| 298 action->setCheckable(true); | 301 action->setCheckable(true); |
| 299 action->setChecked(true); | 302 action->setChecked(true); |
| 300 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(1); }); | 303 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(1); }); |
| 301 } | 304 } |
| 302 | 305 |
| 303 { | 306 { |
| 304 QAction* action = pages_group->addAction(menu->addAction(tr("&History"))); | 307 QAction* action = pages_group->addAction(menu->addAction(tr("&History"))); |
| 305 action->setCheckable(true); | 308 action->setCheckable(true); |
| 306 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(2); }); | 309 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(2); }); |
| 307 } | 310 } |
| 308 | 311 |
| 309 { | 312 { |
| 310 QAction* action = pages_group->addAction(menu->addAction(tr("&Statistics"))); | 313 QAction* action = pages_group->addAction(menu->addAction(tr("&Statistics"))); |
| 311 action->setCheckable(true); | 314 action->setCheckable(true); |
| 312 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(3); }); | 315 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(3); }); |
| 313 } | 316 } |
| 314 | 317 |
| 315 { | 318 { |
| 316 QAction* action = pages_group->addAction(menu->addAction(tr("S&earch"))); | 319 QAction* action = pages_group->addAction(menu->addAction(tr("S&earch"))); |
| 317 action->setCheckable(true); | 320 action->setCheckable(true); |
| 318 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(4); }); | 321 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(4); }); |
| 319 } | 322 } |
| 320 | 323 |
| 321 { | 324 { |
| 322 QAction* action = pages_group->addAction(menu->addAction(tr("Se&asons"))); | 325 QAction* action = pages_group->addAction(menu->addAction(tr("Se&asons"))); |
| 323 action->setCheckable(true); | 326 action->setCheckable(true); |
| 324 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(5); }); | 327 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(5); }); |
| 325 } | 328 } |
| 326 | 329 |
| 327 { | 330 { |
| 328 QAction* action = pages_group->addAction(menu->addAction(tr("&Torrents"))); | 331 QAction* action = pages_group->addAction(menu->addAction(tr("&Torrents"))); |
| 329 action->setCheckable(true); | 332 action->setCheckable(true); |
| 330 connect(action, &QAction::toggled, this, [this] { sidebar->SetCurrentItem(6); }); | 333 connect(action, &QAction::toggled, this, [this] { sidebar_.SetCurrentItem(6); }); |
| 331 } | 334 } |
| 332 | 335 |
| 333 /* pain in my ass */ | 336 /* pain in the ass */ |
| 334 connect(sidebar.get(), &SideBar::CurrentItemChanged, this, [pages_group](int index) { | 337 connect(&sidebar_, &SideBar::CurrentItemChanged, this, [pages_group](int index) { |
| 335 QAction* checked = pages_group->checkedAction(); | 338 QAction* checked = pages_group->checkedAction(); |
| 336 | 339 |
| 337 const QList<QAction*>& actions = pages_group->actions(); | 340 const QList<QAction*>& actions = pages_group->actions(); |
| 338 if (index > actions.size()) | 341 if (index > actions.size()) |
| 339 return; | 342 return; |
| 493 SettingsDialog dialog; | 496 SettingsDialog dialog; |
| 494 dialog.exec(); | 497 dialog.exec(); |
| 495 } | 498 } |
| 496 } | 499 } |
| 497 | 500 |
| 498 QThreadPool::globalInstance()->start([stack, action] { | 501 /* FIXME: make this use a QThread; this is *very* unsafe */ |
| 499 action->setEnabled(false); | 502 AnimeListPage* page = reinterpret_cast<AnimeListPage*>(stack->widget(static_cast<int>(Pages::ANIME_LIST))); |
| 500 Services::Synchronize(); | 503 if (!async_synchronize_thread_.isRunning()) { |
| 501 reinterpret_cast<AnimeListPage*>(stack->widget(static_cast<int>(Pages::ANIME_LIST)))->Refresh(); | 504 async_synchronize_thread_.SetAction(action); |
| 502 action->setEnabled(true); | 505 async_synchronize_thread_.SetPage(page); |
| 503 }); | 506 async_synchronize_thread_.start(); |
| 507 } | |
| 504 } | 508 } |
| 505 | 509 |
| 506 void MainWindow::RetranslateUI() { | 510 void MainWindow::RetranslateUI() { |
| 507 /* This kinda sucks but nobody's really going to be changing | 511 /* This kinda sucks but nobody's really going to be changing |
| 508 the application language all the time :p */ | 512 the application language all the time :p */ |
