Mercurial > minori
comparison src/gui/pages/anime_list.cc @ 258:862d0d8619f6
*: HUUUGE changes
animia has been renamed to animone, so instead of thinking of a
health condition, you think of a beautiful flower :)
I've also edited some of the code for animone, but I have no idea
if it even works or not because I don't have a mac or windows
machine lying around. whoops!
... anyway, all of the changes divergent from Anisthesia are now
licensed under BSD. it's possible that I could even rewrite most
of the code to where I don't even have to keep the MIT license,
but that's thinking too far into the future
I've been slacking off on implementing the anime seasons page,
mostly out of laziness. I think I'd have to create another db file
specifically for the seasons
anyway, this code is being pushed *primarily* because the hard drive
it's on is failing! yay :)
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Mon, 01 Apr 2024 02:43:44 -0400 |
parents | c130f47f6f48 |
children | f31305b9f60a |
comparison
equal
deleted
inserted
replaced
257:699a20c57dc8 | 258:862d0d8619f6 |
---|---|
23 #include <QHBoxLayout> | 23 #include <QHBoxLayout> |
24 #include <QHeaderView> | 24 #include <QHeaderView> |
25 #include <QMenu> | 25 #include <QMenu> |
26 #include <QProgressBar> | 26 #include <QProgressBar> |
27 #include <QShortcut> | 27 #include <QShortcut> |
28 #include <QTreeView> | |
29 #include <QStylePainter> | 28 #include <QStylePainter> |
30 #include <QStyledItemDelegate> | 29 #include <QStyledItemDelegate> |
31 #include <QThread> | 30 #include <QThread> |
31 #include <QTreeView> | |
32 | 32 |
33 #include <set> | 33 #include <set> |
34 | 34 |
35 AnimeListPageSortFilter::AnimeListPageSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { | 35 AnimeListPageSortFilter::AnimeListPageSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { |
36 } | 36 } |
109 case Qt::DisplayRole: | 109 case Qt::DisplayRole: |
110 switch (index.column()) { | 110 switch (index.column()) { |
111 case AL_TITLE: return Strings::ToQString(list[index.row()].GetUserPreferredTitle()); | 111 case AL_TITLE: return Strings::ToQString(list[index.row()].GetUserPreferredTitle()); |
112 case AL_PROGRESS: | 112 case AL_PROGRESS: |
113 return QString::number(list[index.row()].GetUserProgress()) + "/" + | 113 return QString::number(list[index.row()].GetUserProgress()) + "/" + |
114 QString::number(list[index.row()].GetEpisodes()); | 114 QString::number(list[index.row()].GetEpisodes()); |
115 case AL_EPISODES: return list[index.row()].GetEpisodes(); | 115 case AL_EPISODES: return list[index.row()].GetEpisodes(); |
116 case AL_SCORE: return Strings::ToQString(list[index.row()].GetUserPresentableScore()); | 116 case AL_SCORE: return Strings::ToQString(list[index.row()].GetUserPresentableScore()); |
117 case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat())); | 117 case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat())); |
118 case AL_SEASON: { | 118 case AL_SEASON: { |
119 std::optional<unsigned int> year = list[index.row()].GetAirDate().GetYear(); | 119 std::optional<unsigned int> year = list[index.row()].GetAirDate().GetYear(); |
120 if (!year) | 120 if (!year) |
121 return "Unknown Unknown"; | 121 return "Unknown Unknown"; |
122 return Strings::ToQString(Translate::ToLocalString(list[index.row()].GetSeason()) + " " + Strings::ToUtf8String(year.value())); | 122 return Strings::ToQString(Translate::ToLocalString(list[index.row()].GetSeason()) + " " + |
123 Strings::ToUtf8String(year.value())); | |
123 } | 124 } |
124 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%"; | 125 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%"; |
125 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate(); | 126 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate(); |
126 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate(); | 127 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate(); |
127 case AL_UPDATED: { | 128 case AL_UPDATED: { |
216 tree_view->setColumnHidden(AnimeListPageModel::AL_UPDATED, true); | 217 tree_view->setColumnHidden(AnimeListPageModel::AL_UPDATED, true); |
217 tree_view->setColumnHidden(AnimeListPageModel::AL_NOTES, true); | 218 tree_view->setColumnHidden(AnimeListPageModel::AL_NOTES, true); |
218 } | 219 } |
219 | 220 |
220 void AnimeListPage::UpdateAnime(int id) { | 221 void AnimeListPage::UpdateAnime(int id) { |
221 QThread* thread = QThread::create([this, id] { | 222 QThread* thread = QThread::create([this, id] { Services::UpdateAnimeEntry(id); }); |
222 Services::UpdateAnimeEntry(id); | |
223 }); | |
224 | 223 |
225 connect(thread, &QThread::finished, this, &AnimeListPage::Refresh); | 224 connect(thread, &QThread::finished, this, &AnimeListPage::Refresh); |
226 connect(thread, &QThread::finished, thread, &QThread::deleteLater); | 225 connect(thread, &QThread::finished, thread, &QThread::deleteLater); |
227 | 226 |
228 thread->start(); | 227 thread->start(); |
242 | 241 |
243 for (int i = 0; i < AnimeListPageModel::NB_COLUMNS; i++) { | 242 for (int i = 0; i < AnimeListPageModel::NB_COLUMNS; i++) { |
244 if (i == AnimeListPageModel::AL_TITLE) | 243 if (i == AnimeListPageModel::AL_TITLE) |
245 continue; | 244 continue; |
246 const auto column_name = | 245 const auto column_name = |
247 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); | 246 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); |
248 | 247 |
249 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { | 248 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { |
250 if (!checked && (VisibleColumnsCount() <= 1)) | 249 if (!checked && (VisibleColumnsCount() <= 1)) |
251 return; | 250 return; |
252 | 251 |
276 QMenu* menu = new QMenu(this); | 275 QMenu* menu = new QMenu(this); |
277 menu->setAttribute(Qt::WA_DeleteOnClose); | 276 menu->setAttribute(Qt::WA_DeleteOnClose); |
278 menu->setToolTipsVisible(true); | 277 menu->setToolTipsVisible(true); |
279 | 278 |
280 AnimeListPageModel* source_model = | 279 AnimeListPageModel* source_model = |
281 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); | 280 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); |
282 const QItemSelection selection = | 281 const QItemSelection selection = |
283 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); | 282 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); |
284 | 283 |
285 std::set<Anime::Anime*> animes; | 284 std::set<Anime::Anime*> animes; |
286 for (const auto& index : selection.indexes()) { | 285 for (const auto& index : selection.indexes()) { |
287 if (!index.isValid()) | 286 if (!index.isValid()) |
288 continue; | 287 continue; |
291 animes.insert(anime); | 290 animes.insert(anime); |
292 } | 291 } |
293 | 292 |
294 menu->addAction(tr("Information"), [this, animes] { | 293 menu->addAction(tr("Information"), [this, animes] { |
295 for (auto& anime : animes) { | 294 for (auto& anime : animes) { |
296 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] { | 295 InformationDialog* dialog = new InformationDialog( |
297 UpdateAnime(anime->GetId()); | 296 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); |
298 }, InformationDialog::PAGE_MAIN_INFO, this); | |
299 | 297 |
300 dialog->show(); | 298 dialog->show(); |
301 dialog->raise(); | 299 dialog->raise(); |
302 dialog->activateWindow(); | 300 dialog->activateWindow(); |
303 } | 301 } |
304 }); | 302 }); |
305 menu->addSeparator(); | 303 menu->addSeparator(); |
306 menu->addAction(tr("Edit"), [this, animes] { | 304 menu->addAction(tr("Edit"), [this, animes] { |
307 for (auto& anime : animes) { | 305 for (auto& anime : animes) { |
308 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] { | 306 InformationDialog* dialog = new InformationDialog( |
309 UpdateAnime(anime->GetId()); | 307 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MY_LIST, this); |
310 }, InformationDialog::PAGE_MY_LIST, this); | |
311 | 308 |
312 dialog->show(); | 309 dialog->show(); |
313 dialog->raise(); | 310 dialog->raise(); |
314 dialog->activateWindow(); | 311 dialog->activateWindow(); |
315 } | 312 } |
323 } | 320 } |
324 | 321 |
325 void AnimeListPage::ItemDoubleClicked() { | 322 void AnimeListPage::ItemDoubleClicked() { |
326 /* throw out any other garbage */ | 323 /* throw out any other garbage */ |
327 const QItemSelection selection = | 324 const QItemSelection selection = |
328 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); | 325 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); |
329 if (!selection.indexes().first().isValid()) { | 326 if (!selection.indexes().first().isValid()) { |
330 return; | 327 return; |
331 } | 328 } |
332 | 329 |
333 AnimeListPageModel* source_model = | 330 AnimeListPageModel* source_model = |
334 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); | 331 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); |
335 | 332 |
336 const QModelIndex index = source_model->index(selection.indexes().first().row()); | 333 const QModelIndex index = source_model->index(selection.indexes().first().row()); |
337 Anime::Anime* anime = source_model->GetAnimeFromIndex(index); | 334 Anime::Anime* anime = source_model->GetAnimeFromIndex(index); |
338 | 335 |
339 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] { | 336 InformationDialog* dialog = new InformationDialog( |
340 UpdateAnime(anime->GetId()); | 337 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, InformationDialog::PAGE_MAIN_INFO, this); |
341 }, InformationDialog::PAGE_MAIN_INFO, this); | |
342 | 338 |
343 dialog->show(); | 339 dialog->show(); |
344 dialog->raise(); | 340 dialog->raise(); |
345 dialog->activateWindow(); | 341 dialog->activateWindow(); |
346 } | 342 } |
351 } | 347 } |
352 | 348 |
353 void AnimeListPage::RefreshTabs() { | 349 void AnimeListPage::RefreshTabs() { |
354 for (unsigned int i = 0; i < sort_models.size(); i++) | 350 for (unsigned int i = 0; i < sort_models.size(); i++) |
355 tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + | 351 tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + |
356 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); | 352 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); |
357 } | 353 } |
358 | 354 |
359 void AnimeListPage::Refresh() { | 355 void AnimeListPage::Refresh() { |
360 RefreshList(); | 356 RefreshList(); |
361 RefreshTabs(); | 357 RefreshTabs(); |
447 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); | 443 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); |
448 tree_view->setFrameShape(QFrame::NoFrame); | 444 tree_view->setFrameShape(QFrame::NoFrame); |
449 | 445 |
450 for (unsigned int i = 0; i < sort_models.size(); i++) { | 446 for (unsigned int i = 0; i < sort_models.size(); i++) { |
451 tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + | 447 tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + |
452 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); | 448 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); |
453 sort_models[i] = new AnimeListPageSortFilter(tree_view); | 449 sort_models[i] = new AnimeListPageSortFilter(tree_view); |
454 sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i])); | 450 sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i])); |
455 sort_models[i]->setSortRole(Qt::UserRole); | 451 sort_models[i]->setSortRole(Qt::UserRole); |
456 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive); | 452 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive); |
457 } | 453 } |
478 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListPage::ItemDoubleClicked); | 474 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListPage::ItemDoubleClicked); |
479 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayListMenu); | 475 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayListMenu); |
480 | 476 |
481 /* Enter & return keys */ | 477 /* Enter & return keys */ |
482 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, | 478 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, |
483 &AnimeListPage::ItemDoubleClicked); | 479 &AnimeListPage::ItemDoubleClicked); |
484 | 480 |
485 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, | 481 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, |
486 &AnimeListPage::ItemDoubleClicked); | 482 &AnimeListPage::ItemDoubleClicked); |
487 | 483 |
488 tree_view->header()->setStretchLastSection(false); | 484 tree_view->header()->setStretchLastSection(false); |
489 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu); | 485 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu); |
490 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayColumnHeaderMenu); | 486 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayColumnHeaderMenu); |
491 | 487 |