Mercurial > minori
changeset 374:f7bb2978de48
gui/pages/anime_list: add Search right-click menu, don't create menu items that do nothing
author | Paper <paper@tflc.us> |
---|---|
date | Fri, 25 Jul 2025 11:03:34 -0400 |
parents | fbc8c617de80 |
children | abd956418fe9 |
files | src/gui/pages/anime_list.cc |
diffstat | 1 files changed, 108 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/src/gui/pages/anime_list.cc Fri Jul 25 11:03:05 2025 -0400 +++ b/src/gui/pages/anime_list.cc Fri Jul 25 11:03:34 2025 -0400 @@ -55,7 +55,10 @@ int id = queue_.front(); /* unlock the mutex for a long blocking operation, so items - * can be added without worry */ + * can be added without worry + * + * NOTE: this code is duplicated elsewhere; is it better to + * have lots of threads, or just one main "worker" thread? */ queue_mutex_.unlock(); Services::UpdateAnimeEntry(id); queue_mutex_.lock(); @@ -361,35 +364,8 @@ // ---------------- // Delete from list... <Del> } else if (animes.size() > 0) { - // menu in Taiga: - // - // Information - // Search -> - // AniDB - // AniList - // Anime News Network - // Kitsu - // MyAnimeList - // Reddit - // Wikipedia - // YouTube - // ---------------- - // Custom RSS feed - // Nyaa.si - // ---------------- - // Edit - // Delete from list... <Del> - // ---------------- - // Open folder <Ctrl+O> - // Scan available episodes <F5> - // ---------------- - // Play episode -> - // grid of episodes (dunno how to implement this) - // Play last episode (#<episode>) - // Play next episode (#<episode>) <Ctrl+N> - // Play random episode <Ctrl+R> (why?) - Anime::Anime *anime = *animes.begin(); + std::optional<std::filesystem::path> path = Library::db.GetAnimeFolder(anime->GetId()); menu->addAction(tr("Information"), [this, anime] { InformationDialog *dialog = new InformationDialog( @@ -402,6 +378,52 @@ connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); }); + { + struct { + bool sep; + QString name; + QString format; + } net[] = { + /* note: the format should not be percent formatted; Qt does + * that automatically */ + + {0, tr("AniDB"), "" /* ??? */}, + {0, tr("AniList"), "" /* ??? */}, + {0, tr("Anime News Network"), "https://www.animenewsnetwork.com/search?q=%1"}, + {0, tr("Kitsu"), "" /* ??? */}, + {0, tr("MyAnimeList"), "https://myanimelist.net/search/all?q=%1&cat=all"}, + {0, tr("Reddit"), "https://www.reddit.com/search?q=%1"}, + {0, tr("Wikipedia"), "https://en.wikipedia.org/w/index.php?search=%1&title=Special:Search&ns0=1"}, + {0, tr("YouTube"), "https://www.youtube.com/results?search_query=%1"}, + {1, /* ------------------- */}, + {0, tr("Custom RSS feed"), "" /* ??? */}, + {0, tr("Nyaa.si"), "https://nyaa.si/?f=0&c=0_0&q=%1"}, + }; + size_t i; + QMenu *msearch = menu->addMenu(tr("Search")); + + for (i = 0; i < (sizeof(net)/sizeof(net[0])); i++) { + if (net[i].sep) { + msearch->addSeparator(); + } else { + if (net[i].format.isEmpty()) + continue; + + msearch->addAction(net[i].name, [anime, net, i] { + /* I suppose romaji is probably the safest */ + std::optional<std::string> title = anime->GetTitle(Anime::TitleLanguage::Romaji); + if (!title) + return; /* wat */ + + QString str = net[i].format.arg(Strings::ToQString(title.value())); + QUrl url(str); + + QDesktopServices::openUrl(url); + }); + } + } + } + menu->addSeparator(); menu->addAction(tr("Edit"), [this, anime] { @@ -420,76 +442,79 @@ menu->addSeparator(); - menu->addAction(tr("Open folder"), [this, anime] { - std::optional<std::filesystem::path> path = Library::db.GetAnimeFolder(anime->GetId()); - if (!path) // ... - return; - - QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(path.value().u8string()))); - }); - menu->addAction(tr("Scan available episodes"), [this, anime] { Library::db.Refresh(anime->GetId()); }); - - menu->addSeparator(); - - { - QMenu *submenu = menu->addMenu(tr("Play episode")); - - // this submenu actually uses win32 API magic to - // make a *grid* of episodes (weird!) - - (void)submenu; + if (path) { + menu->addAction(tr("Open folder"), [path] { + QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(path.value().u8string()))); + }, QKeySequence(QKeySequence::Open)); } - const int progress = anime->GetUserProgress(); - const int episodes = anime->GetEpisodes(); + menu->addAction(tr("Scan available episodes"), + [this, anime] { Library::db.Refresh(anime->GetId()); }, + QKeySequence(QKeySequence::Refresh)); + + if (path) { + menu->addSeparator(); + + { + QMenu *submenu = menu->addMenu(tr("Play episode")); - // I think this is right? - if (progress > 0) { - menu->addAction(tr("Play last episode (#%1)").arg(progress), [this, anime, progress] { - const int id = anime->GetId(); + // this submenu actually uses win32 API magic to + // make a *grid* of episodes (weird!) + + (void)submenu; + } + + const int progress = anime->GetUserProgress(); + const int episodes = anime->GetEpisodes(); + + // I think this is right? + if (progress > 0) { + menu->addAction(tr("Play last episode (#%1)").arg(progress), [this, anime, progress] { + const int id = anime->GetId(); - if (Library::db.items.find(id) == Library::db.items.end() || - Library::db.items[id].find(progress) == Library::db.items[id].end()) - return; + if (Library::db.items.find(id) == Library::db.items.end() || + Library::db.items[id].find(progress) == Library::db.items[id].end()) + return; + + QDesktopServices::openUrl( + QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress].u8string()))); + }); + } - QDesktopServices::openUrl( - QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress].u8string()))); - }); - } + if (progress < episodes) { + menu->addAction( + tr("Play next episode (#%1)").arg(progress + 1), + [this, anime, progress] { + const int id = anime->GetId(); + + if (Library::db.items.find(id) == Library::db.items.end() || + Library::db.items[id].find(progress + 1) == Library::db.items[id].end()) + return; - if (progress < episodes) { + QDesktopServices::openUrl( + QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress + 1].u8string()))); + }, + QKeySequence(Qt::CTRL | Qt::Key_N)); + } + menu->addAction( - tr("Play next episode (#%1)").arg(progress + 1), - [this, anime, progress] { + tr("Play random episode"), + [this, anime, episodes] { const int id = anime->GetId(); + std::uniform_int_distribution<int> distrib(1, episodes); + const int episode = distrib(session.gen); + if (Library::db.items.find(id) == Library::db.items.end() || - Library::db.items[id].find(progress + 1) == Library::db.items[id].end()) + Library::db.items[id].find(episode) == Library::db.items[id].end()) return; QDesktopServices::openUrl( - QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress + 1].u8string()))); + QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][episode].u8string()))); }, - QKeySequence(Qt::CTRL | Qt::Key_N)); + QKeySequence(Qt::CTRL | Qt::Key_R)); } - menu->addAction( - tr("Play random episode"), - [this, anime, episodes] { - const int id = anime->GetId(); - - std::uniform_int_distribution<int> distrib(1, episodes); - const int episode = distrib(session.gen); - - if (Library::db.items.find(id) == Library::db.items.end() || - Library::db.items[id].find(episode) == Library::db.items[id].end()) - return; - - QDesktopServices::openUrl( - QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][episode].u8string()))); - }, - QKeySequence(Qt::CTRL | Qt::Key_R)); - menu->popup(QCursor::pos()); } else { // Where are we now?