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