Mercurial > minori
comparison src/gui/window.cc @ 250:c130f47f6f48
*: many many changes
e.g. the search page is actually implemented now!
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Sun, 04 Feb 2024 21:17:17 -0500 |
| parents | 06d6c351925c |
| children | fe702c8f161f |
comparison
equal
deleted
inserted
replaced
| 249:6b2441c776dd | 250:c130f47f6f48 |
|---|---|
| 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 enum class Pages { | |
| 52 NOW_PLAYING, | |
| 53 | |
| 54 ANIME_LIST, | |
| 55 HISTORY, | |
| 56 STATISTICS, | |
| 57 | |
| 58 SEARCH, | |
| 59 SEASONS, | |
| 60 TORRENTS | |
| 61 }; | |
| 62 | |
| 63 void PlayingThread::run() { | 51 void PlayingThread::run() { |
| 64 std::vector<std::string> files; | 52 std::vector<std::string> files; |
| 65 Track::Media::GetCurrentlyPlaying(files); | 53 Track::Media::GetCurrentlyPlaying(files); |
| 66 emit Done(files); | 54 emit Done(files); |
| 67 } | 55 } |
| 122 timer->start(5000); | 110 timer->start(5000); |
| 123 } | 111 } |
| 124 | 112 |
| 125 void MainWindow::AddMainWidgets() { | 113 void MainWindow::AddMainWidgets() { |
| 126 int page = static_cast<int>(Pages::ANIME_LIST); | 114 int page = static_cast<int>(Pages::ANIME_LIST); |
| 115 | |
| 127 if (sidebar.get()) { | 116 if (sidebar.get()) { |
| 128 main_widget->layout()->removeWidget(sidebar.get()); | 117 main_widget->layout()->removeWidget(sidebar.get()); |
| 129 sidebar.reset(); | 118 sidebar.reset(); |
| 130 } | 119 } |
| 131 | 120 |
| 147 sidebar->AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png")); | 136 sidebar->AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png")); |
| 148 sidebar->AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png")); | 137 sidebar->AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png")); |
| 149 sidebar->AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png")); | 138 sidebar->AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png")); |
| 150 | 139 |
| 151 stack.reset(new QStackedWidget(main_widget.get())); | 140 stack.reset(new QStackedWidget(main_widget.get())); |
| 141 | |
| 152 stack->addWidget(new NowPlayingPage(main_widget.get())); | 142 stack->addWidget(new NowPlayingPage(main_widget.get())); |
| 143 /* ---- */ | |
| 153 stack->addWidget(new AnimeListPage(main_widget.get())); | 144 stack->addWidget(new AnimeListPage(main_widget.get())); |
| 154 stack->addWidget(new HistoryPage(main_widget.get())); | 145 stack->addWidget(new HistoryPage(main_widget.get())); |
| 155 stack->addWidget(new StatisticsPage(main_widget.get())); | 146 stack->addWidget(new StatisticsPage(main_widget.get())); |
| 147 /* ---- */ | |
| 156 stack->addWidget(new SearchPage(main_widget.get())); | 148 stack->addWidget(new SearchPage(main_widget.get())); |
| 157 stack->addWidget(new SeasonsPage(main_widget.get())); | 149 stack->addWidget(new SeasonsPage(main_widget.get())); |
| 158 stack->addWidget(new TorrentsPage(main_widget.get())); | 150 stack->addWidget(new TorrentsPage(main_widget.get())); |
| 159 | 151 |
| 160 connect(sidebar.get(), &SideBar::CurrentItemChanged, stack.get(), &QStackedWidget::setCurrentIndex); | 152 connect(sidebar.get(), &SideBar::CurrentItemChanged, stack.get(), &QStackedWidget::setCurrentIndex); |
| 164 main_widget->layout()->addWidget(stack.get()); | 156 main_widget->layout()->addWidget(stack.get()); |
| 165 } | 157 } |
| 166 | 158 |
| 167 void MainWindow::CreateBars() { | 159 void MainWindow::CreateBars() { |
| 168 QMenuBar* menubar = new QMenuBar(this); | 160 QMenuBar* menubar = new QMenuBar(this); |
| 169 QMenu* folder_menu; /* this is used twice, so we declare it here */ | |
| 170 QAction* sync_action; | 161 QAction* sync_action; |
| 171 | 162 |
| 172 { | 163 { |
| 173 /* File */ | 164 /* File */ |
| 174 QMenu* menu = menubar->addMenu(tr("&File")); | 165 QMenu* menu = menubar->addMenu(tr("&File")); |
| 175 | 166 |
| 176 { | 167 { |
| 177 folder_menu = menu->addMenu(tr("&Library folders")); | 168 folder_menu = menu->addMenu(tr("&Library folders")); |
| 178 | 169 |
| 179 /* add in all of our existing folders... */ | 170 UpdateFolderMenu(); |
| 180 std::size_t i = 0; | |
| 181 for (const auto& path : session.config.library.paths) { | |
| 182 const QString folder = Strings::ToQString(path); | |
| 183 QAction* action = folder_menu->addAction(folder, [folder]{ | |
| 184 QDesktopServices::openUrl(QUrl::fromLocalFile(folder)); | |
| 185 }); | |
| 186 if (i < 9) | |
| 187 action->setShortcut(QKeySequence(Qt::ALT | static_cast<Qt::Modifier>(Qt::Key_1 + i))); | |
| 188 else if (i == 9) | |
| 189 action->setShortcut(QKeySequence(Qt::ALT | Qt::Key_0)); | |
| 190 /* don't bother with a shortcut in case of more... */ | |
| 191 i++; | |
| 192 } | |
| 193 | |
| 194 folder_menu->addSeparator(); | |
| 195 | |
| 196 { | |
| 197 folder_menu->addAction(tr("&Add new folder..."), [this]{ | |
| 198 const QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), | |
| 199 QDir::homePath(), | |
| 200 QFileDialog::ShowDirsOnly | |
| 201 | QFileDialog::DontResolveSymlinks); | |
| 202 if (dir.isEmpty()) | |
| 203 return; | |
| 204 session.config.library.paths.insert(Strings::ToUtf8String(dir)); | |
| 205 /* we have to recreate the menu bar to add the new folder */ | |
| 206 CreateBars(); | |
| 207 }); | |
| 208 } | |
| 209 } | 171 } |
| 210 | 172 |
| 211 { | 173 { |
| 212 menu->addAction(tr("&Scan available episodes"), []{ | 174 menu->addAction(tr("&Scan available episodes"), []{ |
| 213 Library::SearchLibraryFolders(); | 175 Library::SearchLibraryFolders(); |
| 227 // } | 189 // } |
| 228 | 190 |
| 229 menu->addSeparator(); | 191 menu->addSeparator(); |
| 230 | 192 |
| 231 { | 193 { |
| 232 QAction* action = menu->addAction(tr("E&xit"), qApp, &QApplication::quit); | 194 QAction* action = menu->addAction(tr("E&xit"), this, &MainWindow::close); |
| 233 action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); | 195 action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); |
| 234 } | 196 } |
| 235 } | 197 } |
| 236 | 198 |
| 237 { | 199 { |
| 312 | 274 |
| 313 { | 275 { |
| 314 QAction* action = menu->addAction(tr("&Settings"), [this] { | 276 QAction* action = menu->addAction(tr("&Settings"), [this] { |
| 315 SettingsDialog dialog(this); | 277 SettingsDialog dialog(this); |
| 316 dialog.exec(); | 278 dialog.exec(); |
| 317 CreateBars(); | 279 UpdateFolderMenu(); |
| 318 }); | 280 }); |
| 319 action->setMenuRole(QAction::PreferencesRole); | 281 action->setMenuRole(QAction::PreferencesRole); |
| 320 } | 282 } |
| 321 } | 283 } |
| 322 | 284 |
| 324 /* View */ | 286 /* View */ |
| 325 QMenu* menu = menubar->addMenu(tr("&View")); | 287 QMenu* menu = menubar->addMenu(tr("&View")); |
| 326 | 288 |
| 327 { | 289 { |
| 328 /* Pages... */ | 290 /* Pages... */ |
| 329 std::map<QAction*, int> page_to_index_map = {}; | 291 QActionGroup* pages_group = new QActionGroup(menu); |
| 330 | |
| 331 QActionGroup* pages_group = new QActionGroup(this); | |
| 332 pages_group->setExclusive(true); | 292 pages_group->setExclusive(true); |
| 333 | 293 |
| 334 { | 294 { |
| 335 QAction* action = pages_group->addAction(menu->addAction(tr("&Now Playing"))); | 295 QAction* action = pages_group->addAction(menu->addAction(tr("&Now Playing"))); |
| 336 action->setCheckable(true); | 296 action->setCheckable(true); |
| 337 page_to_index_map[action] = 0; | 297 connect(action, &QAction::toggled, this, [this] { |
| 298 sidebar->SetCurrentItem(0); | |
| 299 }); | |
| 338 } | 300 } |
| 339 | 301 |
| 340 { | 302 { |
| 341 QAction* action = pages_group->addAction(menu->addAction(tr("&Anime List"))); | 303 QAction* action = pages_group->addAction(menu->addAction(tr("&Anime List"))); |
| 342 action->setCheckable(true); | 304 action->setCheckable(true); |
| 343 action->setChecked(true); | 305 action->setChecked(true); |
| 344 page_to_index_map[action] = 1; | 306 connect(action, &QAction::toggled, this, [this] { |
| 307 sidebar->SetCurrentItem(1); | |
| 308 }); | |
| 345 } | 309 } |
| 346 | 310 |
| 347 { | 311 { |
| 348 QAction* action = pages_group->addAction(menu->addAction(tr("&History"))); | 312 QAction* action = pages_group->addAction(menu->addAction(tr("&History"))); |
| 349 action->setCheckable(true); | 313 action->setCheckable(true); |
| 350 page_to_index_map[action] = 2; | 314 connect(action, &QAction::toggled, this, [this] { |
| 315 sidebar->SetCurrentItem(2); | |
| 316 }); | |
| 351 } | 317 } |
| 352 | 318 |
| 353 { | 319 { |
| 354 QAction* action = pages_group->addAction(menu->addAction(tr("&Statistics"))); | 320 QAction* action = pages_group->addAction(menu->addAction(tr("&Statistics"))); |
| 355 action->setCheckable(true); | 321 action->setCheckable(true); |
| 356 page_to_index_map[action] = 3; | 322 connect(action, &QAction::toggled, this, [this] { |
| 323 sidebar->SetCurrentItem(3); | |
| 324 }); | |
| 357 } | 325 } |
| 358 | 326 |
| 359 { | 327 { |
| 360 QAction* action = pages_group->addAction(menu->addAction(tr("S&earch"))); | 328 QAction* action = pages_group->addAction(menu->addAction(tr("S&earch"))); |
| 361 action->setCheckable(true); | 329 action->setCheckable(true); |
| 362 page_to_index_map[action] = 4; | 330 connect(action, &QAction::toggled, this, [this] { |
| 331 sidebar->SetCurrentItem(4); | |
| 332 }); | |
| 363 } | 333 } |
| 364 | 334 |
| 365 { | 335 { |
| 366 QAction* action = pages_group->addAction(menu->addAction(tr("Se&asons"))); | 336 QAction* action = pages_group->addAction(menu->addAction(tr("Se&asons"))); |
| 367 action->setCheckable(true); | 337 action->setCheckable(true); |
| 368 page_to_index_map[action] = 5; | 338 connect(action, &QAction::toggled, this, [this] { |
| 339 sidebar->SetCurrentItem(5); | |
| 340 }); | |
| 369 } | 341 } |
| 370 | 342 |
| 371 { | 343 { |
| 372 QAction* action = pages_group->addAction(menu->addAction(tr("&Torrents"))); | 344 QAction* action = pages_group->addAction(menu->addAction(tr("&Torrents"))); |
| 373 action->setCheckable(true); | 345 action->setCheckable(true); |
| 374 page_to_index_map[action] = 6; | 346 connect(action, &QAction::toggled, this, [this] { |
| 347 sidebar->SetCurrentItem(6); | |
| 348 }); | |
| 375 } | 349 } |
| 376 | 350 |
| 377 /* pain in my ass */ | 351 /* pain in my ass */ |
| 378 connect(sidebar.get(), &SideBar::CurrentItemChanged, this, | 352 connect(sidebar.get(), &SideBar::CurrentItemChanged, this, [pages_group](int index) { |
| 379 [pages_group](int index) { pages_group->actions()[index]->setChecked(true); }); | 353 QAction* checked = pages_group->checkedAction(); |
| 380 | 354 |
| 381 connect(pages_group, &QActionGroup::triggered, this, | 355 const QList<QAction*>& actions = pages_group->actions(); |
| 382 [this, page_to_index_map](QAction* action) { sidebar->SetCurrentItem(page_to_index_map.at(action)); }); | 356 if (index > actions.size()) |
| 357 return; | |
| 358 | |
| 359 if (checked) | |
| 360 checked->setChecked(false); | |
| 361 actions[index]->setChecked(true); | |
| 362 }); | |
| 383 } | 363 } |
| 384 | 364 |
| 385 menu->addSeparator(); | 365 menu->addSeparator(); |
| 386 | 366 |
| 387 // { | 367 // { |
| 477 | 457 |
| 478 toolbar->addSeparator(); | 458 toolbar->addSeparator(); |
| 479 toolbar->addAction(QIcon(":/icons/24x24/gear.png"), tr("S&ettings"), [this] { | 459 toolbar->addAction(QIcon(":/icons/24x24/gear.png"), tr("S&ettings"), [this] { |
| 480 SettingsDialog dialog(this); | 460 SettingsDialog dialog(this); |
| 481 dialog.exec(); | 461 dialog.exec(); |
| 482 CreateBars(); | 462 /* library folders might have changed! */ |
| 463 UpdateFolderMenu(); | |
| 483 }); | 464 }); |
| 484 addToolBar(toolbar); | 465 addToolBar(toolbar); |
| 466 } | |
| 467 } | |
| 468 | |
| 469 void MainWindow::UpdateFolderMenu() { | |
| 470 if (!folder_menu) | |
| 471 return; | |
| 472 | |
| 473 folder_menu->clear(); | |
| 474 | |
| 475 /* add in all of our existing folders... */ | |
| 476 std::size_t i = 0; | |
| 477 for (const auto& path : session.config.library.paths) { | |
| 478 const QString folder = Strings::ToQString(path); | |
| 479 QAction* action = folder_menu->addAction(folder, [folder]{ | |
| 480 QDesktopServices::openUrl(QUrl::fromLocalFile(folder)); | |
| 481 }); | |
| 482 | |
| 483 if (i < 9) { | |
| 484 /* Qt::Key_1 is equivalent to 1 in ASCII, so we can use the same | |
| 485 * stupid `'0' + i` trick here | |
| 486 */ | |
| 487 action->setShortcut(QKeySequence(Qt::ALT | static_cast<Qt::Modifier>(Qt::Key_1 + i))); | |
| 488 } else if (i == 9) { | |
| 489 action->setShortcut(QKeySequence(Qt::ALT | Qt::Key_0)); | |
| 490 } | |
| 491 /* don't bother with a shortcut in case of more... */ | |
| 492 i++; | |
| 493 } | |
| 494 | |
| 495 folder_menu->addSeparator(); | |
| 496 | |
| 497 { | |
| 498 folder_menu->addAction(tr("&Add new folder..."), [this]{ | |
| 499 const QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), | |
| 500 QDir::homePath(), | |
| 501 QFileDialog::ShowDirsOnly | |
| 502 | QFileDialog::DontResolveSymlinks); | |
| 503 if (dir.isEmpty()) | |
| 504 return; | |
| 505 session.config.library.paths.insert(Strings::ToUtf8String(dir)); | |
| 506 UpdateFolderMenu(); | |
| 507 }); | |
| 485 } | 508 } |
| 486 } | 509 } |
| 487 | 510 |
| 488 void MainWindow::SetActivePage(QWidget* page) { | 511 void MainWindow::SetActivePage(QWidget* page) { |
| 489 this->setCentralWidget(page); | 512 this->setCentralWidget(page); |
