Mercurial > minori
comparison src/gui/pages/anime_list.cc @ 366:886f66775f31
animone: add preliminary AT-SPI stuff
anime_list: finish the regular singular right click menu
author | Paper <paper@tflc.us> |
---|---|
date | Sun, 17 Nov 2024 19:56:01 -0500 |
parents | b5d6c27c308f |
children |
comparison
equal
deleted
inserted
replaced
365:f81bed4e04ac | 366:886f66775f31 |
---|---|
12 #include "core/anime.h" | 12 #include "core/anime.h" |
13 #include "core/anime_db.h" | 13 #include "core/anime_db.h" |
14 #include "core/session.h" | 14 #include "core/session.h" |
15 #include "core/strings.h" | 15 #include "core/strings.h" |
16 #include "core/time.h" | 16 #include "core/time.h" |
17 #include "library/library.h" | |
17 #include "gui/dialog/information.h" | 18 #include "gui/dialog/information.h" |
18 #include "gui/translate/anime.h" | 19 #include "gui/translate/anime.h" |
19 #include "services/services.h" | 20 #include "services/services.h" |
20 | 21 |
21 #include <QDate> | 22 #include <QDate> |
28 #include <QStylePainter> | 29 #include <QStylePainter> |
29 #include <QStyledItemDelegate> | 30 #include <QStyledItemDelegate> |
30 #include <QThreadPool> | 31 #include <QThreadPool> |
31 #include <QRunnable> | 32 #include <QRunnable> |
32 #include <QTreeView> | 33 #include <QTreeView> |
33 | 34 #include <QDesktopServices> |
34 #include <set> | 35 #include <QUrl> |
36 | |
37 #include <iostream> | |
38 #include <vector> | |
35 | 39 |
36 AnimeListPageUpdateEntryThread::AnimeListPageUpdateEntryThread(QObject* parent) : QThread(parent) {} | 40 AnimeListPageUpdateEntryThread::AnimeListPageUpdateEntryThread(QObject* parent) : QThread(parent) {} |
37 | 41 |
38 void AnimeListPageUpdateEntryThread::AddToQueue(int id) { | 42 void AnimeListPageUpdateEntryThread::AddToQueue(int id) { |
39 const std::lock_guard<std::mutex> guard(queue_mutex_); | 43 const std::lock_guard<std::mutex> guard(queue_mutex_); |
270 tree_view->setColumnHidden(i, !checked); | 274 tree_view->setColumnHidden(i, !checked); |
271 | 275 |
272 if (checked && (tree_view->columnWidth(i) <= 5)) | 276 if (checked && (tree_view->columnWidth(i) <= 5)) |
273 tree_view->resizeColumnToContents(i); | 277 tree_view->resizeColumnToContents(i); |
274 | 278 |
275 // SaveSettings(); | 279 // FIXME save the state of this |
276 }); | 280 }); |
277 | 281 |
278 action->setCheckable(true); | 282 action->setCheckable(true); |
279 action->setChecked(!tree_view->isColumnHidden(i)); | 283 action->setChecked(!tree_view->isColumnHidden(i)); |
280 } | 284 } |
288 }); | 292 }); |
289 menu->popup(QCursor::pos()); | 293 menu->popup(QCursor::pos()); |
290 } | 294 } |
291 | 295 |
292 void AnimeListPage::DisplayListMenu() { | 296 void AnimeListPage::DisplayListMenu() { |
293 QMenu* menu = new QMenu(this); | 297 QMenu *const menu = new QMenu(this); |
294 menu->setAttribute(Qt::WA_DeleteOnClose); | 298 menu->setAttribute(Qt::WA_DeleteOnClose); |
295 menu->setToolTipsVisible(true); | 299 menu->setToolTipsVisible(true); |
296 | 300 |
297 AnimeListPageModel* source_model = | 301 AnimeListPageModel* source_model = |
298 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); | 302 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); |
301 | 305 |
302 std::set<Anime::Anime*> animes; | 306 std::set<Anime::Anime*> animes; |
303 for (const auto& index : selection.indexes()) { | 307 for (const auto& index : selection.indexes()) { |
304 if (!index.isValid()) | 308 if (!index.isValid()) |
305 continue; | 309 continue; |
306 Anime::Anime* anime = source_model->GetAnimeFromIndex(index); | 310 |
311 Anime::Anime *const anime = source_model->GetAnimeFromIndex(index); | |
307 if (!anime) | 312 if (!anime) |
308 continue; | 313 continue; |
314 | |
309 animes.insert(&Anime::db.items[anime->GetId()]); | 315 animes.insert(&Anime::db.items[anime->GetId()]); |
310 } | 316 } |
311 | 317 |
312 menu->addAction(tr("Information"), [this, animes] { | 318 if (animes.size() > 1) { |
313 for (auto& anime : animes) { | 319 // menu in Taiga: |
320 // | |
321 // Set date started -> | |
322 // Clear | |
323 // Set to date started airing | |
324 // Set date completed -> | |
325 // Clear | |
326 // Set to date finished airing | |
327 // Set to last updated | |
328 // Set episode... | |
329 // Set score -> | |
330 // 0 | |
331 // 10 | |
332 // ... | |
333 // 100 | |
334 // Set status -> | |
335 // Currently watching | |
336 // ... | |
337 // Plan to watch | |
338 // Set notes... | |
339 // ---------------- | |
340 // Invert selection | |
341 // ---------------- | |
342 // Delete from list... <Del> | |
343 } else if (animes.size() > 0) { | |
344 // menu in Taiga: | |
345 // | |
346 // Information | |
347 // Search -> | |
348 // AniDB | |
349 // AniList | |
350 // Anime News Network | |
351 // Kitsu | |
352 // MyAnimeList | |
353 // Reddit | |
354 // Wikipedia | |
355 // YouTube | |
356 // ---------------- | |
357 // Custom RSS feed | |
358 // Nyaa.si | |
359 // ---------------- | |
360 // Edit | |
361 // Delete from list... <Del> | |
362 // ---------------- | |
363 // Open folder <Ctrl+O> | |
364 // Scan available episodes <F5> | |
365 // ---------------- | |
366 // Play episode -> | |
367 // grid of episodes (dunno how to implement this) | |
368 // Play last episode (#<episode>) | |
369 // Play next episode (#<episode>) <Ctrl+N> | |
370 // Play random episode <Ctrl+R> (why?) | |
371 | |
372 Anime::Anime *anime = *animes.begin(); | |
373 | |
374 menu->addAction(tr("Information"), [this, anime] { | |
314 InformationDialog* dialog = new InformationDialog( | 375 InformationDialog* dialog = new InformationDialog( |
315 anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); | 376 anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); |
316 | 377 |
317 dialog->show(); | 378 dialog->show(); |
318 dialog->raise(); | 379 dialog->raise(); |
319 dialog->activateWindow(); | 380 dialog->activateWindow(); |
320 connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); | 381 connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); |
321 } | 382 }); |
322 }); | 383 |
323 menu->addSeparator(); | 384 menu->addSeparator(); |
324 menu->addAction(tr("Edit"), [this, animes] { | 385 |
325 for (auto& anime : animes) { | 386 menu->addAction(tr("Edit"), [this, anime] { |
326 InformationDialog* dialog = new InformationDialog( | 387 InformationDialog* dialog = new InformationDialog( |
327 anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, this); | 388 anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, this); |
328 | 389 |
329 dialog->show(); | 390 dialog->show(); |
330 dialog->raise(); | 391 dialog->raise(); |
331 dialog->activateWindow(); | 392 dialog->activateWindow(); |
332 connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); | 393 connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); |
394 }); | |
395 menu->addAction(tr("Delete from list..."), [this, anime] { | |
396 RemoveAnime(anime->GetId()); | |
397 }, QKeySequence(QKeySequence::Delete)); | |
398 | |
399 menu->addSeparator(); | |
400 | |
401 menu->addAction(tr("Open folder"), [this, anime] { | |
402 std::optional<std::filesystem::path> path = Library::db.GetAnimeFolder(anime->GetId()); | |
403 if (!path) // ... | |
404 return; | |
405 | |
406 QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(path.value().u8string()))); | |
407 }); | |
408 menu->addAction(tr("Scan available episodes"), [this, anime] { | |
409 Library::db.Refresh(anime->GetId()); | |
410 }); | |
411 | |
412 menu->addSeparator(); | |
413 | |
414 { | |
415 QMenu *submenu = menu->addMenu(tr("Play episode")); | |
416 | |
417 // this submenu actually uses win32 API magic to | |
418 // make a *grid* of episodes (weird!) | |
419 | |
420 (void)submenu; | |
333 } | 421 } |
334 }); | 422 |
335 menu->addAction(tr("Delete from list..."), [this, animes] { | 423 const int progress = anime->GetUserProgress(); |
336 for (auto& anime : animes) { | 424 const int episodes = anime->GetEpisodes(); |
337 RemoveAnime(anime->GetId()); | 425 |
426 // I think this is right? | |
427 if (progress > 0) { | |
428 menu->addAction(tr("Play last episode (#%1)").arg(progress), [this, anime, progress] { | |
429 const int id = anime->GetId(); | |
430 | |
431 if (Library::db.items.find(id) == Library::db.items.end() | |
432 || Library::db.items[id].find(progress) == Library::db.items[id].end()) | |
433 return; | |
434 | |
435 QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress].u8string()))); | |
436 }); | |
338 } | 437 } |
339 }); | 438 |
340 menu->popup(QCursor::pos()); | 439 if (progress < episodes) { |
440 menu->addAction(tr("Play next episode (#%1)").arg(progress + 1), [this, anime, progress] { | |
441 const int id = anime->GetId(); | |
442 | |
443 if (Library::db.items.find(id) == Library::db.items.end() | |
444 || Library::db.items[id].find(progress + 1) == Library::db.items[id].end()) | |
445 return; | |
446 | |
447 QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress + 1].u8string()))); | |
448 }, QKeySequence(Qt::CTRL | Qt::Key_N)); | |
449 } | |
450 | |
451 menu->addAction(tr("Play random episode"), [this, anime, episodes] { | |
452 const int id = anime->GetId(); | |
453 | |
454 std::uniform_int_distribution<int> distrib(1, episodes); | |
455 const int episode = distrib(session.gen); | |
456 | |
457 if (Library::db.items.find(id) == Library::db.items.end() | |
458 || Library::db.items[id].find(episode) == Library::db.items[id].end()) | |
459 return; | |
460 | |
461 QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][episode].u8string()))); | |
462 }, QKeySequence(Qt::CTRL | Qt::Key_R)); | |
463 | |
464 menu->popup(QCursor::pos()); | |
465 } else { | |
466 // Where are we now? | |
467 } | |
341 } | 468 } |
342 | 469 |
343 void AnimeListPage::ItemDoubleClicked() { | 470 void AnimeListPage::ItemDoubleClicked() { |
344 /* throw out any other garbage */ | 471 /* throw out any other garbage */ |
345 const QItemSelection selection = | 472 const QItemSelection selection = |