comparison src/gui/pages/anime_list.cc @ 118:39521c47c7a3

*: another huge megacommit, SORRY The torrents page works a lot better now Added the edit option to the anime list right click menu Vectorized currently playing files Available player and extensions are now loaded at runtime from files in (dotpath)/players.json and (dotpath)/extensions.json These paths are not permanent and will likely be moved to (dotpath)/recognition ... ... ...
author Paper <mrpapersonic@gmail.com>
date Tue, 07 Nov 2023 23:40:54 -0500
parents ab191e28e69d
children bc8d2ccff09c
comparison
equal deleted inserted replaced
117:2c1b6782e1d0 118:39521c47c7a3
106 case Qt::DisplayRole: 106 case Qt::DisplayRole:
107 switch (index.column()) { 107 switch (index.column()) {
108 case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); 108 case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str());
109 case AL_PROGRESS: 109 case AL_PROGRESS:
110 return QString::number(list[index.row()].GetUserProgress()) + "/" + 110 return QString::number(list[index.row()].GetUserProgress()) + "/" +
111 QString::number(list[index.row()].GetEpisodes()); 111 QString::number(list[index.row()].GetEpisodes());
112 case AL_EPISODES: return list[index.row()].GetEpisodes(); 112 case AL_EPISODES: return list[index.row()].GetEpisodes();
113 case AL_SCORE: return list[index.row()].GetUserScore(); 113 case AL_SCORE: return list[index.row()].GetUserScore();
114 case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat())); 114 case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat()));
115 case AL_SEASON: 115 case AL_SEASON:
116 return Strings::ToQString(Translate::ToString(list[index.row()].GetSeason())) + " " + 116 return Strings::ToQString(Translate::ToString(list[index.row()].GetSeason())) + " " +
117 QString::number(list[index.row()].GetAirDate().GetYear()); 117 QString::number(list[index.row()].GetAirDate().GetYear());
118 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%"; 118 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%";
119 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate(); 119 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate();
120 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate(); 120 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate();
121 case AL_UPDATED: { 121 case AL_UPDATED: {
122 if (list[index.row()].GetUserTimeUpdated() == 0) 122 if (list[index.row()].GetUserTimeUpdated() == 0)
161 Anime::Anime* AnimeListPageModel::GetAnimeFromIndex(QModelIndex index) { 161 Anime::Anime* AnimeListPageModel::GetAnimeFromIndex(QModelIndex index) {
162 return &list.at(index.row()); 162 return &list.at(index.row());
163 } 163 }
164 164
165 void AnimeListPageModel::RefreshList() { 165 void AnimeListPageModel::RefreshList() {
166 bool has_children = !!rowCount(index(0)); 166 /* equivalent to hasChildren()... */
167 if (!has_children) { 167 if (!rowCount(index(0))) {
168 beginInsertRows(QModelIndex(), 0, 0); 168 beginInsertRows(QModelIndex(), 0, 0);
169 endInsertRows(); 169 endInsertRows();
170 } 170 }
171 171
172 beginResetModel(); 172 beginResetModel();
231 231
232 for (int i = 0; i < AnimeListPageModel::NB_COLUMNS; i++) { 232 for (int i = 0; i < AnimeListPageModel::NB_COLUMNS; i++) {
233 if (i == AnimeListPageModel::AL_TITLE) 233 if (i == AnimeListPageModel::AL_TITLE)
234 continue; 234 continue;
235 const auto column_name = 235 const auto column_name =
236 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); 236 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
237
237 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { 238 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) {
238 if (!checked && (VisibleColumnsCount() <= 1)) 239 if (!checked && (VisibleColumnsCount() <= 1))
239 return; 240 return;
240 241
241 tree_view->setColumnHidden(i, !checked); 242 tree_view->setColumnHidden(i, !checked);
243 if (checked && (tree_view->columnWidth(i) <= 5)) 244 if (checked && (tree_view->columnWidth(i) <= 5))
244 tree_view->resizeColumnToContents(i); 245 tree_view->resizeColumnToContents(i);
245 246
246 // SaveSettings(); 247 // SaveSettings();
247 }); 248 });
249
248 action->setCheckable(true); 250 action->setCheckable(true);
249 action->setChecked(!tree_view->isColumnHidden(i)); 251 action->setChecked(!tree_view->isColumnHidden(i));
250 } 252 }
251 253
252 menu->addSeparator(); 254 menu->addSeparator();
264 menu->setAttribute(Qt::WA_DeleteOnClose); 266 menu->setAttribute(Qt::WA_DeleteOnClose);
265 menu->setTitle(tr("Column visibility")); 267 menu->setTitle(tr("Column visibility"));
266 menu->setToolTipsVisible(true); 268 menu->setToolTipsVisible(true);
267 269
268 AnimeListPageModel* source_model = 270 AnimeListPageModel* source_model =
269 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); 271 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel());
270 const QItemSelection selection = 272 const QItemSelection selection =
271 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); 273 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
272 274
273 std::set<Anime::Anime*> animes; 275 std::set<Anime::Anime*> animes;
274 for (const auto& index : selection.indexes()) { 276 for (const auto& index : selection.indexes()) {
275 if (!index.isValid()) 277 if (!index.isValid())
276 continue; 278 continue;
279 animes.insert(anime); 281 animes.insert(anime);
280 } 282 }
281 283
282 menu->addAction(tr("Information"), [this, animes] { 284 menu->addAction(tr("Information"), [this, animes] {
283 for (auto& anime : animes) { 285 for (auto& anime : animes) {
284 InformationDialog* dialog = new InformationDialog( 286 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] {
285 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, this); 287 UpdateAnime(anime->GetId());
288 }, InformationDialog::PAGE_MAIN_INFO, this);
286 289
287 dialog->show(); 290 dialog->show();
288 dialog->raise(); 291 dialog->raise();
289 dialog->activateWindow(); 292 dialog->activateWindow();
290 } 293 }
291 }); 294 });
292 menu->addSeparator(); 295 menu->addSeparator();
296 menu->addAction(tr("Edit"), [this, animes] {
297 for (auto& anime : animes) {
298 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] {
299 UpdateAnime(anime->GetId());
300 }, InformationDialog::PAGE_MY_LIST, this);
301
302 dialog->show();
303 dialog->raise();
304 dialog->activateWindow();
305 }
306 });
293 menu->addAction(tr("Delete from list..."), [this, animes] { 307 menu->addAction(tr("Delete from list..."), [this, animes] {
294 for (auto& anime : animes) { 308 for (auto& anime : animes) {
295 RemoveAnime(anime->GetId()); 309 RemoveAnime(anime->GetId());
296 } 310 }
297 }); 311 });
299 } 313 }
300 314
301 void AnimeListPage::ItemDoubleClicked() { 315 void AnimeListPage::ItemDoubleClicked() {
302 /* throw out any other garbage */ 316 /* throw out any other garbage */
303 const QItemSelection selection = 317 const QItemSelection selection =
304 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); 318 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection());
305 if (!selection.indexes().first().isValid()) { 319 if (!selection.indexes().first().isValid()) {
306 return; 320 return;
307 } 321 }
308 322
309 AnimeListPageModel* source_model = 323 AnimeListPageModel* source_model =
310 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); 324 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel());
311 325
312 const QModelIndex index = source_model->index(selection.indexes().first().row()); 326 const QModelIndex index = source_model->index(selection.indexes().first().row());
313 Anime::Anime* anime = source_model->GetAnimeFromIndex(index); 327 Anime::Anime* anime = source_model->GetAnimeFromIndex(index);
314 328
315 InformationDialog* dialog = new InformationDialog( 329 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] {
316 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, this); 330 UpdateAnime(anime->GetId());
331 }, InformationDialog::PAGE_MAIN_INFO, this);
317 332
318 dialog->show(); 333 dialog->show();
319 dialog->raise(); 334 dialog->raise();
320 dialog->activateWindow(); 335 dialog->activateWindow();
321 } 336 }
326 } 341 }
327 342
328 void AnimeListPage::RefreshTabs() { 343 void AnimeListPage::RefreshTabs() {
329 for (unsigned int i = 0; i < sort_models.size(); i++) 344 for (unsigned int i = 0; i < sort_models.size(); i++)
330 tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + 345 tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
331 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); 346 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
332 } 347 }
333 348
334 void AnimeListPage::Refresh() { 349 void AnimeListPage::Refresh() {
335 RefreshList(); 350 RefreshList();
336 RefreshTabs(); 351 RefreshTabs();
421 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); 436 tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
422 tree_view->setFrameShape(QFrame::NoFrame); 437 tree_view->setFrameShape(QFrame::NoFrame);
423 438
424 for (unsigned int i = 0; i < sort_models.size(); i++) { 439 for (unsigned int i = 0; i < sort_models.size(); i++) {
425 tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + 440 tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
426 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); 441 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
427 sort_models[i] = new AnimeListPageSortFilter(tree_view); 442 sort_models[i] = new AnimeListPageSortFilter(tree_view);
428 sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i])); 443 sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i]));
429 sort_models[i]->setSortRole(Qt::UserRole); 444 sort_models[i]->setSortRole(Qt::UserRole);
430 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive); 445 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive);
431 } 446 }
439 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListPage::ItemDoubleClicked); 454 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListPage::ItemDoubleClicked);
440 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayListMenu); 455 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayListMenu);
441 456
442 /* Enter & return keys */ 457 /* Enter & return keys */
443 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, 458 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this,
444 &AnimeListPage::ItemDoubleClicked); 459 &AnimeListPage::ItemDoubleClicked);
445 460
446 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, 461 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this,
447 &AnimeListPage::ItemDoubleClicked); 462 &AnimeListPage::ItemDoubleClicked);
448 463
449 tree_view->header()->setStretchLastSection(false); 464 tree_view->header()->setStretchLastSection(false);
450 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu); 465 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu);
451 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayColumnHeaderMenu); 466 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayColumnHeaderMenu);
452 467