Mercurial > minori
comparison src/gui/pages/anime_list.cpp @ 15:cde8f67a7c7d
*: update, megacommit :)
| author | Paper <mrpapersonic@gmail.com> |
|---|---|
| date | Tue, 19 Sep 2023 22:36:08 -0400 |
| parents | fc1bf97c528b |
| children | d05b1be2f3a6 |
comparison
equal
deleted
inserted
replaced
| 14:a29c9402faf0 | 15:cde8f67a7c7d |
|---|---|
| 14 #include "core/session.h" | 14 #include "core/session.h" |
| 15 #include "core/time.h" | 15 #include "core/time.h" |
| 16 #include "gui/dialog/information.h" | 16 #include "gui/dialog/information.h" |
| 17 #include "gui/translate/anime.h" | 17 #include "gui/translate/anime.h" |
| 18 #include "services/anilist.h" | 18 #include "services/anilist.h" |
| 19 #include <QDebug> | |
| 19 #include <QHBoxLayout> | 20 #include <QHBoxLayout> |
| 20 #include <QHeaderView> | 21 #include <QHeaderView> |
| 21 #include <QMenu> | 22 #include <QMenu> |
| 22 #include <QProgressBar> | 23 #include <QProgressBar> |
| 23 #include <QDebug> | |
| 24 #include <QShortcut> | 24 #include <QShortcut> |
| 25 #include <QStylePainter> | 25 #include <QStylePainter> |
| 26 #include <QStyledItemDelegate> | 26 #include <QStyledItemDelegate> |
| 27 #include <QAbstractItemModelTester> | |
| 28 #include <cmath> | 27 #include <cmath> |
| 29 | 28 |
| 30 AnimeListWidgetDelegate::AnimeListWidgetDelegate(QObject* parent) : QStyledItemDelegate(parent) { | 29 AnimeListWidgetDelegate::AnimeListWidgetDelegate(QObject* parent) : QStyledItemDelegate(parent) { |
| 31 } | 30 } |
| 32 | 31 |
| 34 // no edit 4 u | 33 // no edit 4 u |
| 35 return nullptr; | 34 return nullptr; |
| 36 } | 35 } |
| 37 | 36 |
| 38 void AnimeListWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, | 37 void AnimeListWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, |
| 39 const QModelIndex& index) const { | 38 const QModelIndex& index) const { |
| 40 switch (index.column()) { | 39 switch (index.column()) { |
| 41 /* | 40 #if 0 |
| 42 case AnimeListWidgetModel::AL_PROGRESS: { | 41 case AnimeListWidgetModel::AL_PROGRESS: { |
| 43 const int progress = static_cast<int>(index.data(Qt::UserRole).toReal()); | 42 const int progress = static_cast<int>(index.data(Qt::UserRole).toReal()); |
| 44 const int episodes = | 43 const int episodes = |
| 45 static_cast<int>(index.siblingAtColumn(AnimeListWidgetModel::AL_EPISODES).data(Qt::UserRole).toReal()); | 44 static_cast<int>(index.siblingAtColumn(AnimeListWidgetModel::AL_EPISODES).data(Qt::UserRole).toReal()); |
| 46 | 45 |
| 47 int text_width = 59; | 46 int text_width = 59; |
| 48 QRectF text_rect(option.rect.x() + text_width, option.rect.y(), text_width, option.decorationSize.height()); | 47 QRectF text_rect(option.rect.x() + text_width, option.rect.y(), text_width, option.decorationSize.height()); |
| 49 painter->save(); | 48 painter->save(); |
| 50 painter->drawText(text_rect, "/", QTextOption(Qt::AlignCenter | Qt::AlignVCenter)); | 49 painter->drawText(text_rect, "/", QTextOption(Qt::AlignCenter | Qt::AlignVCenter)); |
| 51 // drawText(const QRectF &rectangle, const QString &text, const QTextOption &option = QTextOption()) | 50 // drawText(const QRectF &rectangle, const QString &text, const QTextOption &option = |
| 52 painter->drawText(QRectF(text_rect.x(), text_rect.y(), text_width / 2 - 2, text_rect.height()), | 51 QTextOption()) painter->drawText(QRectF(text_rect.x(), text_rect.y(), text_width / 2 - 2, |
| 53 QString::number(progress), QTextOption(Qt::AlignRight | Qt::AlignVCenter)); | 52 text_rect.height()), QString::number(progress), QTextOption(Qt::AlignRight | Qt::AlignVCenter)); |
| 54 painter->drawText( | 53 painter->drawText( |
| 55 QRectF(text_rect.x() + text_width / 2 + 2, text_rect.y(), text_width / 2 - 2, text_rect.height()), | 54 QRectF(text_rect.x() + text_width / 2 + 2, text_rect.y(), text_width / 2 - 2, text_rect.height()), |
| 56 QString::number(episodes), QTextOption(Qt::AlignLeft | Qt::AlignVCenter)); | 55 QString::number(episodes), QTextOption(Qt::AlignLeft | Qt::AlignVCenter)); |
| 57 painter->restore(); | 56 painter->restore(); |
| 58 QStyledItemDelegate::paint(painter, option, index); | 57 QStyledItemDelegate::paint(painter, option, index); |
| 59 break; | 58 break; |
| 60 } | 59 } |
| 61 */ | 60 #endif |
| 62 default: QStyledItemDelegate::paint(painter, option, index); break; | 61 default: QStyledItemDelegate::paint(painter, option, index); break; |
| 63 } | 62 } |
| 64 } | 63 } |
| 65 | 64 |
| 66 AnimeListWidgetSortFilter::AnimeListWidgetSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { | 65 AnimeListWidgetSortFilter::AnimeListWidgetSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { |
| 97 } | 96 } |
| 98 | 97 |
| 99 QVariant AnimeListWidgetModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { | 98 QVariant AnimeListWidgetModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { |
| 100 if (role == Qt::DisplayRole) { | 99 if (role == Qt::DisplayRole) { |
| 101 switch (section) { | 100 switch (section) { |
| 102 case AL_TITLE: return tr("Anime title"); | 101 case AL_TITLE: return tr("Anime title"); |
| 103 case AL_PROGRESS: return tr("Progress"); | 102 case AL_PROGRESS: return tr("Progress"); |
| 104 case AL_EPISODES: return tr("Episodes"); | 103 case AL_EPISODES: return tr("Episodes"); |
| 105 case AL_TYPE: return tr("Type"); | 104 case AL_TYPE: return tr("Type"); |
| 106 case AL_SCORE: return tr("Score"); | 105 case AL_SCORE: return tr("Score"); |
| 107 case AL_SEASON: return tr("Season"); | 106 case AL_SEASON: return tr("Season"); |
| 108 case AL_STARTED: return tr("Date started"); | 107 case AL_STARTED: return tr("Date started"); |
| 109 case AL_COMPLETED: return tr("Date completed"); | 108 case AL_COMPLETED: return tr("Date completed"); |
| 110 case AL_NOTES: return tr("Notes"); | 109 case AL_NOTES: return tr("Notes"); |
| 111 case AL_AVG_SCORE: return tr("Average score"); | 110 case AL_AVG_SCORE: return tr("Average score"); |
| 112 case AL_UPDATED: return tr("Last updated"); | 111 case AL_UPDATED: return tr("Last updated"); |
| 113 default: return {}; | 112 default: return {}; |
| 114 } | 113 } |
| 115 } else if (role == Qt::TextAlignmentRole) { | 114 } else if (role == Qt::TextAlignmentRole) { |
| 116 switch (section) { | 115 switch (section) { |
| 117 case AL_TITLE: | 116 case AL_TITLE: |
| 118 case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); | 117 case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); |
| 119 case AL_PROGRESS: | 118 case AL_PROGRESS: |
| 120 case AL_EPISODES: | 119 case AL_EPISODES: |
| 121 case AL_TYPE: | 120 case AL_TYPE: |
| 122 case AL_SCORE: | 121 case AL_SCORE: |
| 123 case AL_AVG_SCORE: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); | 122 case AL_AVG_SCORE: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); |
| 124 case AL_SEASON: | 123 case AL_SEASON: |
| 125 case AL_STARTED: | 124 case AL_STARTED: |
| 126 case AL_COMPLETED: | 125 case AL_COMPLETED: |
| 127 case AL_UPDATED: return QVariant(Qt::AlignRight | Qt::AlignVCenter); | 126 case AL_UPDATED: return QVariant(Qt::AlignRight | Qt::AlignVCenter); |
| 128 default: return QAbstractListModel::headerData(section, orientation, role); | 127 default: return QAbstractListModel::headerData(section, orientation, role); |
| 129 } | 128 } |
| 130 } | 129 } |
| 131 return QAbstractListModel::headerData(section, orientation, role); | 130 return QAbstractListModel::headerData(section, orientation, role); |
| 132 } | 131 } |
| 133 | 132 |
| 134 QVariant AnimeListWidgetModel::data(const QModelIndex& index, int role) const { | 133 QVariant AnimeListWidgetModel::data(const QModelIndex& index, int role) const { |
| 135 if (!index.isValid()) | 134 if (!index.isValid()) |
| 136 return QVariant(); | 135 return QVariant(); |
| 137 switch (role) { | 136 switch (role) { |
| 138 case Qt::DisplayRole: | 137 case Qt::DisplayRole: |
| 139 switch (index.column()) { | 138 switch (index.column()) { |
| 140 case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); | 139 case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); |
| 141 case AL_PROGRESS: | 140 case AL_PROGRESS: |
| 142 return QString::number(list[index.row()].GetUserProgress()) + "/" + QString::number(list[index.row()].GetEpisodes()); | 141 return QString::number(list[index.row()].GetUserProgress()) + "/" + |
| 143 case AL_EPISODES: return list[index.row()].GetEpisodes(); | 142 QString::number(list[index.row()].GetEpisodes()); |
| 144 case AL_SCORE: return list[index.row()].GetUserScore(); | 143 case AL_EPISODES: return list[index.row()].GetEpisodes(); |
| 145 case AL_TYPE: return QString::fromStdString(Translate::TranslateSeriesFormat(list[index.row()].GetFormat())); | 144 case AL_SCORE: return list[index.row()].GetUserScore(); |
| 146 case AL_SEASON: | 145 case AL_TYPE: return QString::fromStdString(Translate::ToString(list[index.row()].GetFormat())); |
| 147 return QString::fromStdString(Translate::TranslateSeriesSeason(list[index.row()].GetSeason())) + " " + | 146 case AL_SEASON: |
| 148 QString::number(list[index.row()].GetAirDate().GetYear()); | 147 return QString::fromStdString(Translate::ToString(list[index.row()].GetSeason())) + " " + |
| 149 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%"; | 148 QString::number(list[index.row()].GetAirDate().GetYear()); |
| 150 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate(); | 149 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%"; |
| 151 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate(); | 150 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate(); |
| 152 case AL_UPDATED: { | 151 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate(); |
| 153 if (list[index.row()].GetUserTimeUpdated() == 0) | 152 case AL_UPDATED: { |
| 154 return QString("-"); | 153 if (list[index.row()].GetUserTimeUpdated() == 0) |
| 155 Time::Duration duration(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated()); | 154 return QString("-"); |
| 156 return QString::fromUtf8(duration.AsRelativeString().c_str()); | 155 Time::Duration duration(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated()); |
| 157 } | 156 return QString::fromUtf8(duration.AsRelativeString().c_str()); |
| 158 case AL_NOTES: return QString::fromUtf8(list[index.row()].GetUserNotes().c_str()); | 157 } |
| 159 default: return ""; | 158 case AL_NOTES: return QString::fromUtf8(list[index.row()].GetUserNotes().c_str()); |
| 160 } | 159 default: return ""; |
| 161 break; | 160 } |
| 161 break; | |
| 162 case Qt::UserRole: | 162 case Qt::UserRole: |
| 163 switch (index.column()) { | 163 switch (index.column()) { |
| 164 case AL_ID: return list[index.row()].GetId(); | 164 case AL_PROGRESS: return list[index.row()].GetUserProgress(); |
| 165 case AL_PROGRESS: return list[index.row()].GetUserProgress(); | 165 case AL_TYPE: return static_cast<int>(list[index.row()].GetFormat()); |
| 166 case AL_TYPE: return static_cast<int>(list[index.row()].GetFormat()); | 166 case AL_SEASON: return list[index.row()].GetAirDate().GetAsQDate(); |
| 167 case AL_SEASON: return list[index.row()].GetAirDate().GetAsQDate(); | 167 case AL_AVG_SCORE: return list[index.row()].GetAudienceScore(); |
| 168 case AL_AVG_SCORE: return list[index.row()].GetAudienceScore(); | 168 case AL_UPDATED: return list[index.row()].GetUserTimeUpdated(); |
| 169 case AL_UPDATED: return list[index.row()].GetUserTimeUpdated(); | 169 default: return data(index, Qt::DisplayRole); |
| 170 default: return data(index, Qt::DisplayRole); | 170 } |
| 171 } | 171 break; |
| 172 break; | |
| 173 case Qt::TextAlignmentRole: | 172 case Qt::TextAlignmentRole: |
| 174 switch (index.column()) { | 173 switch (index.column()) { |
| 175 case AL_TITLE: | 174 case AL_TITLE: |
| 176 case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); | 175 case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); |
| 177 case AL_PROGRESS: | 176 case AL_PROGRESS: |
| 178 case AL_EPISODES: | 177 case AL_EPISODES: |
| 179 case AL_TYPE: | 178 case AL_TYPE: |
| 180 case AL_SCORE: | 179 case AL_SCORE: |
| 181 case AL_AVG_SCORE: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); | 180 case AL_AVG_SCORE: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); |
| 182 case AL_SEASON: | 181 case AL_SEASON: |
| 183 case AL_STARTED: | 182 case AL_STARTED: |
| 184 case AL_COMPLETED: | 183 case AL_COMPLETED: |
| 185 case AL_UPDATED: return QVariant(Qt::AlignRight | Qt::AlignVCenter); | 184 case AL_UPDATED: return QVariant(Qt::AlignRight | Qt::AlignVCenter); |
| 186 default: break; | 185 default: break; |
| 187 } | 186 } |
| 188 break; | 187 break; |
| 189 } | 188 } |
| 190 return QVariant(); | 189 return QVariant(); |
| 191 } | 190 } |
| 192 | 191 |
| 193 void AnimeListWidgetModel::UpdateAnime(int id) { | 192 void AnimeListWidgetModel::UpdateAnime(int id) { |
| 194 /* meh... it might be better to just reinit the entire list */ | 193 /* meh... it might be better to just reinit the entire list */ |
| 195 int i = 0; | 194 int i = 0; |
| 196 for (const auto& a : Anime::db.items) { | 195 for (const auto& a : Anime::db.items) { |
| 197 if (a.second.IsInUserList() && a.first == id && a.second.GetUserStatus() == status) { | 196 if (a.second.IsInUserList() && a.first == id && a.second.GetUserStatus() == status) { |
| 198 emit dataChanged(index(i), index(i)); | 197 emit dataChanged(index(i), index(i)); |
| 199 } | 198 } |
| 200 i++; | 199 i++; |
| 201 } | 200 } |
| 202 } | 201 } |
| 203 | 202 |
| 205 return &list.at(index.row()); | 204 return &list.at(index.row()); |
| 206 } | 205 } |
| 207 | 206 |
| 208 void AnimeListWidgetModel::RefreshList() { | 207 void AnimeListWidgetModel::RefreshList() { |
| 209 bool has_children = !!rowCount(index(0)); | 208 bool has_children = !!rowCount(index(0)); |
| 210 if (has_children) beginResetModel(); | 209 if (has_children) |
| 210 beginResetModel(); | |
| 211 else { | |
| 212 int count = 0; | |
| 213 for (const auto& a : Anime::db.items) | |
| 214 if (a.second.IsInUserList() && a.second.GetUserStatus() == status) | |
| 215 count++; | |
| 216 beginInsertRows(index(0), 0, count - 1); | |
| 217 } | |
| 218 | |
| 211 list.clear(); | 219 list.clear(); |
| 212 | 220 |
| 213 for (const auto& a : Anime::db.items) { | 221 for (const auto& a : Anime::db.items) { |
| 214 if (a.second.IsInUserList() && a.second.GetUserStatus() == status) { | 222 if (a.second.IsInUserList() && a.second.GetUserStatus() == status) { |
| 215 list.push_back(a.second); | 223 list.push_back(a.second); |
| 216 } | 224 } |
| 217 } | 225 } |
| 218 if (has_children) endResetModel(); | 226 |
| 227 if (has_children) | |
| 228 endResetModel(); | |
| 229 else | |
| 230 endInsertRows(); | |
| 219 } | 231 } |
| 220 | 232 |
| 221 int AnimeListWidget::VisibleColumnsCount() const { | 233 int AnimeListWidget::VisibleColumnsCount() const { |
| 222 int count = 0; | 234 int count = 0; |
| 223 | 235 |
| 224 for (int i = 0, end = tree_view->header()->count(); i < end; i++) { | 236 for (int i = 0, end = tree_view->header()->count(); i < end; i++) { |
| 225 if (!tree_view->isColumnHidden(i)) | 237 if (!tree_view->isColumnHidden(i)) |
| 226 count++; | 238 count++; |
| 227 } | 239 } |
| 228 | 240 |
| 229 return count; | 241 return count; |
| 230 } | 242 } |
| 231 | 243 |
| 240 tree_view->setColumnHidden(AnimeListWidgetModel::AL_AVG_SCORE, true); | 252 tree_view->setColumnHidden(AnimeListWidgetModel::AL_AVG_SCORE, true); |
| 241 tree_view->setColumnHidden(AnimeListWidgetModel::AL_STARTED, true); | 253 tree_view->setColumnHidden(AnimeListWidgetModel::AL_STARTED, true); |
| 242 tree_view->setColumnHidden(AnimeListWidgetModel::AL_COMPLETED, true); | 254 tree_view->setColumnHidden(AnimeListWidgetModel::AL_COMPLETED, true); |
| 243 tree_view->setColumnHidden(AnimeListWidgetModel::AL_UPDATED, true); | 255 tree_view->setColumnHidden(AnimeListWidgetModel::AL_UPDATED, true); |
| 244 tree_view->setColumnHidden(AnimeListWidgetModel::AL_NOTES, true); | 256 tree_view->setColumnHidden(AnimeListWidgetModel::AL_NOTES, true); |
| 245 tree_view->setColumnHidden(AnimeListWidgetModel::AL_ID, true); | |
| 246 } | 257 } |
| 247 | 258 |
| 248 void AnimeListWidget::DisplayColumnHeaderMenu() { | 259 void AnimeListWidget::DisplayColumnHeaderMenu() { |
| 249 QMenu* menu = new QMenu(this); | 260 QMenu* menu = new QMenu(this); |
| 250 menu->setAttribute(Qt::WA_DeleteOnClose); | 261 menu->setAttribute(Qt::WA_DeleteOnClose); |
| 251 menu->setTitle(tr("Column visibility")); | 262 menu->setTitle(tr("Column visibility")); |
| 252 menu->setToolTipsVisible(true); | 263 menu->setToolTipsVisible(true); |
| 253 | 264 |
| 254 for (int i = 0; i < AnimeListWidgetModel::NB_COLUMNS; i++) { | 265 for (int i = 0; i < AnimeListWidgetModel::NB_COLUMNS; i++) { |
| 255 if (i == AnimeListWidgetModel::AL_TITLE || i == AnimeListWidgetModel::AL_ID) | 266 if (i == AnimeListWidgetModel::AL_TITLE) |
| 256 continue; | 267 continue; |
| 257 const auto column_name = | 268 const auto column_name = |
| 258 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); | 269 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); |
| 259 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { | 270 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { |
| 260 if (!checked && (VisibleColumnsCount() <= 1)) | 271 if (!checked && (VisibleColumnsCount() <= 1)) |
| 261 return; | 272 return; |
| 262 | 273 |
| 263 tree_view->setColumnHidden(i, !checked); | 274 tree_view->setColumnHidden(i, !checked); |
| 286 QMenu* menu = new QMenu(this); | 297 QMenu* menu = new QMenu(this); |
| 287 menu->setAttribute(Qt::WA_DeleteOnClose); | 298 menu->setAttribute(Qt::WA_DeleteOnClose); |
| 288 menu->setTitle(tr("Column visibility")); | 299 menu->setTitle(tr("Column visibility")); |
| 289 menu->setToolTipsVisible(true); | 300 menu->setToolTipsVisible(true); |
| 290 | 301 |
| 291 const QItemSelection selection = sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); | 302 const QItemSelection selection = |
| 303 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); | |
| 292 if (!selection.indexes().first().isValid()) { | 304 if (!selection.indexes().first().isValid()) { |
| 293 return; | 305 return; |
| 294 } | 306 } |
| 295 | 307 |
| 296 QAction* action = menu->addAction("Information", [this, selection] { | 308 QAction* action = menu->addAction("Information", [this, selection] { |
| 297 const QModelIndex index = ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel()) | 309 const QModelIndex index = ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel()) |
| 298 ->index(selection.indexes().first().row()); | 310 ->index(selection.indexes().first().row()); |
| 299 Anime::Anime* anime = | 311 Anime::Anime* anime = |
| 300 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index); | 312 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index); |
| 301 if (!anime) { | 313 if (!anime) { |
| 302 return; | 314 return; |
| 303 } | 315 } |
| 304 | 316 |
| 305 InformationDialog* dialog = new InformationDialog( | 317 InformationDialog* dialog = new InformationDialog( |
| 306 *anime, | 318 *anime, |
| 307 [this, anime] { | 319 [this, anime] { |
| 308 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->UpdateAnime(anime->GetId()); | 320 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel()) |
| 309 }, | 321 ->UpdateAnime(anime->GetId()); |
| 310 this); | 322 }, |
| 323 this); | |
| 311 | 324 |
| 312 dialog->show(); | 325 dialog->show(); |
| 313 dialog->raise(); | 326 dialog->raise(); |
| 314 dialog->activateWindow(); | 327 dialog->activateWindow(); |
| 315 }); | 328 }); |
| 317 } | 330 } |
| 318 | 331 |
| 319 void AnimeListWidget::ItemDoubleClicked() { | 332 void AnimeListWidget::ItemDoubleClicked() { |
| 320 /* throw out any other garbage */ | 333 /* throw out any other garbage */ |
| 321 const QItemSelection selection = | 334 const QItemSelection selection = |
| 322 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); | 335 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); |
| 323 if (!selection.indexes().first().isValid()) { | 336 if (!selection.indexes().first().isValid()) { |
| 324 return; | 337 return; |
| 325 } | 338 } |
| 326 | 339 |
| 327 const QModelIndex index = ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel()) | 340 const QModelIndex index = ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel()) |
| 328 ->index(selection.indexes().first().row()); | 341 ->index(selection.indexes().first().row()); |
| 329 Anime::Anime* anime = | 342 Anime::Anime* anime = |
| 330 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index); | 343 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->GetAnimeFromIndex(index); |
| 331 | 344 |
| 332 InformationDialog* dialog = new InformationDialog( | 345 InformationDialog* dialog = new InformationDialog( |
| 333 *anime, | 346 *anime, |
| 334 [this, anime] { | 347 [this, anime] { |
| 335 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->UpdateAnime(anime->GetId()); | 348 ((AnimeListWidgetModel*)sort_models[tab_bar->currentIndex()]->sourceModel())->UpdateAnime(anime->GetId()); |
| 336 }, | 349 }, |
| 337 this); | 350 this); |
| 338 | 351 |
| 339 dialog->show(); | 352 dialog->show(); |
| 340 dialog->raise(); | 353 dialog->raise(); |
| 341 dialog->activateWindow(); | 354 dialog->activateWindow(); |
| 342 } | 355 } |
| 422 tree_view->setRootIsDecorated(false); | 435 tree_view->setRootIsDecorated(false); |
| 423 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); | 436 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); |
| 424 tree_view->setFrameShape(QFrame::NoFrame); | 437 tree_view->setFrameShape(QFrame::NoFrame); |
| 425 | 438 |
| 426 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) { | 439 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) { |
| 427 tab_bar->addTab(QString::fromStdString(Translate::TranslateListStatus(Anime::ListStatuses[i])) + " (" + QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); | 440 tab_bar->addTab(QString::fromStdString(Translate::ToString(Anime::ListStatuses[i])) + " (" + |
| 441 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); | |
| 428 sort_models[i] = new AnimeListWidgetSortFilter(tree_view); | 442 sort_models[i] = new AnimeListWidgetSortFilter(tree_view); |
| 429 AnimeListWidgetModel* model = new AnimeListWidgetModel(this, Anime::ListStatuses[i]); | 443 sort_models[i]->setSourceModel(new AnimeListWidgetModel(this, Anime::ListStatuses[i])); |
| 430 new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Fatal, this); | |
| 431 sort_models[i]->setSourceModel(model); | |
| 432 sort_models[i]->setSortRole(Qt::UserRole); | 444 sort_models[i]->setSortRole(Qt::UserRole); |
| 433 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive); | 445 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive); |
| 434 } | 446 } |
| 447 tree_view->setModel(sort_models[0]); | |
| 435 | 448 |
| 436 QHBoxLayout* layout = new QHBoxLayout; | 449 QHBoxLayout* layout = new QHBoxLayout; |
| 437 layout->addWidget(tree_view); | 450 layout->addWidget(tree_view); |
| 438 layout->setMargin(0); | 451 layout->setMargin(0); |
| 439 tree_widget->setLayout(layout); | 452 tree_widget->setLayout(layout); |
| 441 /* Double click stuff */ | 454 /* Double click stuff */ |
| 442 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListWidget::ItemDoubleClicked); | 455 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListWidget::ItemDoubleClicked); |
| 443 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayListMenu); | 456 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayListMenu); |
| 444 | 457 |
| 445 /* Enter & return keys */ | 458 /* Enter & return keys */ |
| 446 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, | 459 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, |
| 447 this, &AnimeListWidget::ItemDoubleClicked); | 460 &AnimeListWidget::ItemDoubleClicked); |
| 448 | 461 |
| 449 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, | 462 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, |
| 450 this, &AnimeListWidget::ItemDoubleClicked); | 463 &AnimeListWidget::ItemDoubleClicked); |
| 451 | 464 |
| 452 tree_view->header()->setStretchLastSection(false); | 465 tree_view->header()->setStretchLastSection(false); |
| 453 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu); | 466 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu); |
| 454 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, | 467 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayColumnHeaderMenu); |
| 455 &AnimeListWidget::DisplayColumnHeaderMenu); | |
| 456 | 468 |
| 457 connect(tab_bar, &QTabBar::currentChanged, this, [this](int index) { | 469 connect(tab_bar, &QTabBar::currentChanged, this, [this](int index) { |
| 458 if (sort_models[index]) | 470 if (sort_models[index]) |
| 459 tree_view->setModel(sort_models[index]); | 471 tree_view->setModel(sort_models[index]); |
| 460 }); | 472 }); |
| 462 setFocusPolicy(Qt::TabFocus); | 474 setFocusPolicy(Qt::TabFocus); |
| 463 setFocusProxy(tab_bar); | 475 setFocusProxy(tab_bar); |
| 464 } | 476 } |
| 465 | 477 |
| 466 void AnimeListWidget::RefreshList() { | 478 void AnimeListWidget::RefreshList() { |
| 467 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) { | 479 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) |
| 468 ((AnimeListWidgetModel*)sort_models[i]->sourceModel())->RefreshList(); | 480 ((AnimeListWidgetModel*)sort_models[i]->sourceModel())->RefreshList(); |
| 469 } | 481 } |
| 470 } | 482 |
| 471 | 483 void AnimeListWidget::RefreshTabs() { |
| 484 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) | |
| 485 tab_bar->setTabText(i, QString::fromStdString(Translate::ToString(Anime::ListStatuses[i])) + " (" + | |
| 486 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); | |
| 487 } | |
| 488 | |
| 489 void AnimeListWidget::Refresh() { | |
| 490 RefreshList(); | |
| 491 RefreshTabs(); | |
| 492 } | |
| 493 | |
| 494 /* This function, really, really should not be called. | |
| 495 Ever. Why would you ever need to clear the anime list? | |
| 496 Also, this sucks. */ | |
| 472 void AnimeListWidget::Reset() { | 497 void AnimeListWidget::Reset() { |
| 473 while (tab_bar->count()) | 498 while (tab_bar->count()) |
| 474 tab_bar->removeTab(0); | 499 tab_bar->removeTab(0); |
| 475 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) | 500 for (unsigned int i = 0; i < ARRAYSIZE(sort_models); i++) |
| 476 delete sort_models[i]; | 501 delete sort_models[i]; |
