Mercurial > minori
diff src/gui/pages/anime_list.cc @ 370:ea3a74ed2ef9
*: hm, last commit wasn't quite finished?
author | Paper <paper@tflc.us> |
---|---|
date | Fri, 25 Jul 2025 10:22:04 -0400 |
parents | 886f66775f31 |
children | f7bb2978de48 |
line wrap: on
line diff
--- a/src/gui/pages/anime_list.cc Fri Jul 25 10:16:02 2025 -0400 +++ b/src/gui/pages/anime_list.cc Fri Jul 25 10:22:04 2025 -0400 @@ -14,38 +14,42 @@ #include "core/session.h" #include "core/strings.h" #include "core/time.h" -#include "library/library.h" #include "gui/dialog/information.h" #include "gui/translate/anime.h" +#include "library/library.h" #include "services/services.h" #include <QDate> #include <QDebug> +#include <QDesktopServices> #include <QHBoxLayout> #include <QHeaderView> #include <QMenu> #include <QProgressBar> +#include <QRunnable> #include <QShortcut> #include <QStylePainter> #include <QStyledItemDelegate> #include <QThreadPool> -#include <QRunnable> #include <QTreeView> -#include <QDesktopServices> #include <QUrl> #include <iostream> #include <vector> -AnimeListPageUpdateEntryThread::AnimeListPageUpdateEntryThread(QObject* parent) : QThread(parent) {} +AnimeListPageUpdateEntryThread::AnimeListPageUpdateEntryThread(QObject *parent) : QThread(parent) +{ +} -void AnimeListPageUpdateEntryThread::AddToQueue(int id) { +void AnimeListPageUpdateEntryThread::AddToQueue(int id) +{ const std::lock_guard<std::mutex> guard(queue_mutex_); queue_.push(id); } /* processes the queue... */ -void AnimeListPageUpdateEntryThread::run() { +void AnimeListPageUpdateEntryThread::run() +{ queue_mutex_.lock(); while (!queue_.empty() && !isInterruptionRequested()) { int id = queue_.front(); @@ -63,10 +67,12 @@ emit NeedRefresh(); } -AnimeListPageSortFilter::AnimeListPageSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { +AnimeListPageSortFilter::AnimeListPageSortFilter(QObject *parent) : QSortFilterProxyModel(parent) +{ } -bool AnimeListPageSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { +bool AnimeListPageSortFilter::lessThan(const QModelIndex &l, const QModelIndex &r) const +{ QVariant left = sourceModel()->data(l, sortRole()); QVariant right = sourceModel()->data(r, sortRole()); @@ -83,22 +89,26 @@ /* -------------------------------------------------- */ -AnimeListPageModel::AnimeListPageModel(QObject* parent, Anime::ListStatus _status) : QAbstractListModel(parent) { +AnimeListPageModel::AnimeListPageModel(QObject *parent, Anime::ListStatus _status) : QAbstractListModel(parent) +{ status = _status; return; } -int AnimeListPageModel::rowCount(const QModelIndex& parent) const { +int AnimeListPageModel::rowCount(const QModelIndex &parent) const +{ return list.size(); (void)(parent); } -int AnimeListPageModel::columnCount(const QModelIndex& parent) const { +int AnimeListPageModel::columnCount(const QModelIndex &parent) const +{ return NB_COLUMNS; (void)(parent); } -QVariant AnimeListPageModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { +QVariant AnimeListPageModel::headerData(const int section, const Qt::Orientation orientation, const int role) const +{ if (role == Qt::DisplayRole) { switch (section) { case AL_TITLE: return tr("Anime title"); @@ -133,7 +143,8 @@ return QAbstractListModel::headerData(section, orientation, role); } -QVariant AnimeListPageModel::data(const QModelIndex& index, int role) const { +QVariant AnimeListPageModel::data(const QModelIndex &index, int role) const +{ if (!index.isValid()) return QVariant(); switch (role) { @@ -142,7 +153,7 @@ case AL_TITLE: return Strings::ToQString(list[index.row()].GetUserPreferredTitle()); case AL_PROGRESS: return QString::number(list[index.row()].GetUserProgress()) + "/" + - QString::number(list[index.row()].GetEpisodes()); + QString::number(list[index.row()].GetEpisodes()); case AL_EPISODES: return list[index.row()].GetEpisodes(); case AL_SCORE: return Strings::ToQString(list[index.row()].GetUserPresentableScore()); case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat())); @@ -153,7 +164,8 @@ case AL_UPDATED: { if (list[index.row()].GetUserTimeUpdated() == 0) return QString("-"); - return Strings::ToQString(Time::GetSecondsAsRelativeString(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated())); + return Strings::ToQString(Time::GetSecondsAsRelativeString(Time::GetSystemTime() - + list[index.row()].GetUserTimeUpdated())); } case AL_NOTES: return Strings::ToQString(list[index.row()].GetUserNotes()); default: return ""; @@ -190,11 +202,13 @@ return QVariant(); } -Anime::Anime* AnimeListPageModel::GetAnimeFromIndex(QModelIndex index) { +Anime::Anime *AnimeListPageModel::GetAnimeFromIndex(QModelIndex index) +{ return &list.at(index.row()); } -void AnimeListPageModel::RefreshList() { +void AnimeListPageModel::RefreshList() +{ /* equivalent to hasChildren()... */ if (!rowCount(index(0))) { beginInsertRows(QModelIndex(), 0, 0); @@ -205,7 +219,7 @@ list.clear(); - for (const auto& a : Anime::db.items) + for (const auto &a : Anime::db.items) if (a.second.IsInUserList() && a.second.GetUserStatus() == status) list.push_back(a.second); @@ -214,7 +228,8 @@ /* ----------------------------------------------------------------- */ -int AnimeListPage::VisibleColumnsCount() const { +int AnimeListPage::VisibleColumnsCount() const +{ int count = 0; for (int i = 0, end = tree_view->header()->count(); i < end; i++) { @@ -225,7 +240,8 @@ return count; } -void AnimeListPage::SetColumnDefaults() { +void AnimeListPage::SetColumnDefaults() +{ tree_view->setColumnHidden(AnimeListPageModel::AL_SEASON, false); tree_view->setColumnHidden(AnimeListPageModel::AL_TYPE, false); tree_view->setColumnHidden(AnimeListPageModel::AL_UPDATED, false); @@ -240,7 +256,8 @@ tree_view->setColumnHidden(AnimeListPageModel::AL_NOTES, true); } -void AnimeListPage::UpdateAnime(int id) { +void AnimeListPage::UpdateAnime(int id) +{ /* this ought to just add to the thread's buffer. */ if (update_entry_thread_.isRunning()) update_entry_thread_.requestInterruption(); @@ -249,14 +266,16 @@ update_entry_thread_.start(); } -void AnimeListPage::RemoveAnime(int id) { - Anime::Anime& anime = Anime::db.items[id]; +void AnimeListPage::RemoveAnime(int id) +{ + Anime::Anime &anime = Anime::db.items[id]; anime.RemoveFromUserList(); Refresh(); } -void AnimeListPage::DisplayColumnHeaderMenu() { - QMenu* menu = new QMenu(this); +void AnimeListPage::DisplayColumnHeaderMenu() +{ + QMenu *menu = new QMenu(this); menu->setAttribute(Qt::WA_DeleteOnClose); menu->setTitle(tr("Column visibility")); menu->setToolTipsVisible(true); @@ -265,9 +284,9 @@ if (i == AnimeListPageModel::AL_TITLE) continue; const auto column_name = - sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); + sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); - QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { + QAction *action = menu->addAction(column_name, this, [this, i](const bool checked) { if (!checked && (VisibleColumnsCount() <= 1)) return; @@ -293,18 +312,19 @@ menu->popup(QCursor::pos()); } -void AnimeListPage::DisplayListMenu() { +void AnimeListPage::DisplayListMenu() +{ QMenu *const menu = new QMenu(this); menu->setAttribute(Qt::WA_DeleteOnClose); menu->setToolTipsVisible(true); - AnimeListPageModel* source_model = - reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); + AnimeListPageModel *source_model = + reinterpret_cast<AnimeListPageModel *>(sort_models[tab_bar->currentIndex()]->sourceModel()); const QItemSelection selection = - sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); + sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); - std::set<Anime::Anime*> animes; - for (const auto& index : selection.indexes()) { + std::set<Anime::Anime *> animes; + for (const auto &index : selection.indexes()) { if (!index.isValid()) continue; @@ -372,8 +392,9 @@ Anime::Anime *anime = *animes.begin(); menu->addAction(tr("Information"), [this, anime] { - InformationDialog* dialog = new InformationDialog( - anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); + InformationDialog *dialog = new InformationDialog( + anime, [this](Anime::Anime *anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, + this); dialog->show(); dialog->raise(); @@ -384,17 +405,18 @@ menu->addSeparator(); menu->addAction(tr("Edit"), [this, anime] { - InformationDialog* dialog = new InformationDialog( - anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, this); + InformationDialog *dialog = new InformationDialog( + anime, [this](Anime::Anime *anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, + this); dialog->show(); dialog->raise(); dialog->activateWindow(); connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); }); - menu->addAction(tr("Delete from list..."), [this, anime] { - RemoveAnime(anime->GetId()); - }, QKeySequence(QKeySequence::Delete)); + menu->addAction( + tr("Delete from list..."), [this, anime] { RemoveAnime(anime->GetId()); }, + QKeySequence(QKeySequence::Delete)); menu->addSeparator(); @@ -405,9 +427,7 @@ QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(path.value().u8string()))); }); - menu->addAction(tr("Scan available episodes"), [this, anime] { - Library::db.Refresh(anime->GetId()); - }); + menu->addAction(tr("Scan available episodes"), [this, anime] { Library::db.Refresh(anime->GetId()); }); menu->addSeparator(); @@ -428,38 +448,47 @@ 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()) + 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(); + 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 (Library::db.items.find(id) == Library::db.items.end() || + Library::db.items[id].find(progress + 1) == Library::db.items[id].end()) + return; - QDesktopServices::openUrl(QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress + 1].u8string()))); - }, QKeySequence(Qt::CTRL | Qt::Key_N)); + QDesktopServices::openUrl( + QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][progress + 1].u8string()))); + }, + QKeySequence(Qt::CTRL | Qt::Key_N)); } - menu->addAction(tr("Play random episode"), [this, anime, episodes] { - const int id = anime->GetId(); + 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); + 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; + 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)); + QDesktopServices::openUrl( + QUrl::fromLocalFile(Strings::ToQString(Library::db.items[id][episode].u8string()))); + }, + QKeySequence(Qt::CTRL | Qt::Key_R)); menu->popup(QCursor::pos()); } else { @@ -467,22 +496,23 @@ } } -void AnimeListPage::ItemDoubleClicked() { +void AnimeListPage::ItemDoubleClicked() +{ /* throw out any other garbage */ const QItemSelection selection = - sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); + sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); if (!selection.indexes().first().isValid()) { return; } - AnimeListPageModel* source_model = - reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); + AnimeListPageModel *source_model = + reinterpret_cast<AnimeListPageModel *>(sort_models[tab_bar->currentIndex()]->sourceModel()); const QModelIndex index = source_model->index(selection.indexes().first().row()); - Anime::Anime& anime = Anime::db.items[source_model->GetAnimeFromIndex(index)->GetId()]; + Anime::Anime &anime = Anime::db.items[source_model->GetAnimeFromIndex(index)->GetId()]; - InformationDialog* dialog = new InformationDialog( - &anime, [this](Anime::Anime* anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); + InformationDialog *dialog = new InformationDialog( + &anime, [this](Anime::Anime *anime) { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); dialog->show(); dialog->raise(); @@ -490,25 +520,29 @@ connect(dialog, &InformationDialog::finished, dialog, &InformationDialog::deleteLater); } -void AnimeListPage::RefreshList() { +void AnimeListPage::RefreshList() +{ for (unsigned int i = 0; i < sort_models.size(); i++) - reinterpret_cast<AnimeListPageModel*>(sort_models[i]->sourceModel())->RefreshList(); + reinterpret_cast<AnimeListPageModel *>(sort_models[i]->sourceModel())->RefreshList(); } -void AnimeListPage::RefreshTabs() { +void AnimeListPage::RefreshTabs() +{ for (unsigned int i = 0; i < sort_models.size(); i++) tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + - QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); + QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); } -void AnimeListPage::Refresh() { +void AnimeListPage::Refresh() +{ RefreshList(); RefreshTabs(); } /* -------- QTabWidget replication begin --------- */ -void AnimeListPage::InitBasicStyle(QStyleOptionTabWidgetFrame* option) const { +void AnimeListPage::InitBasicStyle(QStyleOptionTabWidgetFrame *option) const +{ if (!option) return; @@ -518,7 +552,8 @@ option->tabBarRect = tab_bar->geometry(); } -void AnimeListPage::InitStyle(QStyleOptionTabWidgetFrame* option) const { +void AnimeListPage::InitStyle(QStyleOptionTabWidgetFrame *option) const +{ if (!option) return; @@ -539,7 +574,8 @@ option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, this); } -void AnimeListPage::SetupLayout() { +void AnimeListPage::SetupLayout() +{ QStyleOptionTabWidgetFrame option; InitStyle(&option); @@ -552,7 +588,8 @@ tree_view->parentWidget()->setGeometry(contentsRect); } -void AnimeListPage::paintEvent(QPaintEvent*) { +void AnimeListPage::paintEvent(QPaintEvent *) +{ QStylePainter p(this); QStyleOptionTabWidgetFrame opt; @@ -561,26 +598,29 @@ p.drawPrimitive(QStyle::PE_FrameTabWidget, opt); } -void AnimeListPage::resizeEvent(QResizeEvent* e) { +void AnimeListPage::resizeEvent(QResizeEvent *e) +{ QWidget::resizeEvent(e); SetupLayout(); } -void AnimeListPage::showEvent(QShowEvent*) { +void AnimeListPage::showEvent(QShowEvent *) +{ SetupLayout(); Refresh(); } /* --------- QTabWidget replication end ---------- */ -AnimeListPage::AnimeListPage(QWidget* parent) : QWidget(parent) { +AnimeListPage::AnimeListPage(QWidget *parent) : QWidget(parent) +{ /* Tab bar */ tab_bar = new QTabBar(this); tab_bar->setExpanding(false); tab_bar->setDrawBase(false); /* Tree view... */ - QWidget* tree_widget = new QWidget(this); + QWidget *tree_widget = new QWidget(this); tree_view = new QTreeView(tree_widget); tree_view->setUniformRowHeights(true); tree_view->setAllColumnsShowFocus(false); @@ -594,7 +634,7 @@ for (unsigned int i = 0; i < sort_models.size(); i++) { tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + - QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); + QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); sort_models[i] = new AnimeListPageSortFilter(tree_view); sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i])); sort_models[i]->setSortRole(Qt::UserRole); @@ -615,7 +655,7 @@ tree_view->setColumnWidth(AnimeListPageModel::AL_UPDATED, 100); tree_view->setColumnWidth(AnimeListPageModel::AL_NOTES, 100); - QHBoxLayout* layout = new QHBoxLayout(tree_widget); + QHBoxLayout *layout = new QHBoxLayout(tree_widget); layout->addWidget(tree_view); layout->setContentsMargins(0, 0, 0, 0); @@ -625,10 +665,10 @@ /* Enter & return keys */ connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, - &AnimeListPage::ItemDoubleClicked); + &AnimeListPage::ItemDoubleClicked); connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, - &AnimeListPage::ItemDoubleClicked); + &AnimeListPage::ItemDoubleClicked); tree_view->header()->setStretchLastSection(false); tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu);