Mercurial > minori
annotate src/gui/pages/anime_list.cc @ 101:c537996cf67b
*: multitude of config changes
1. theme is now configurable from the settings menu
(but you have to restart for it to apply)
2. config is now stored in an INI file, with no method of
conversion from json (this repo is private-ish anyway)
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Fri, 03 Nov 2023 14:06:02 -0400 |
parents | c912128af0eb |
children | b315f3759c56 |
rev | line source |
---|---|
10 | 1 /** |
2 * anime_list.cpp: defines the anime list page | |
3 * and widgets. | |
4 * | |
5 * much of this file is based around | |
6 * Qt's original QTabWidget implementation, because | |
7 * I needed a somewhat native way to create a tabbed | |
8 * widget with only one subwidget that worked exactly | |
9 * like a native tabbed widget. | |
10 **/ | |
11 #include "gui/pages/anime_list.h" | |
12 #include "core/anime.h" | |
13 #include "core/anime_db.h" | |
14 #include "core/session.h" | |
76 | 15 #include "core/strings.h" |
10 | 16 #include "core/time.h" |
17 #include "gui/dialog/information.h" | |
18 #include "gui/translate/anime.h" | |
52
0c4138de2ea7
anime list: we are finally read-write
Paper <mrpapersonic@gmail.com>
parents:
51
diff
changeset
|
19 #include "services/services.h" |
15 | 20 #include <QDebug> |
10 | 21 #include <QHBoxLayout> |
22 #include <QHeaderView> | |
23 #include <QMenu> | |
24 #include <QProgressBar> | |
25 #include <QShortcut> | |
86 | 26 #include <QTreeView> |
10 | 27 #include <QStylePainter> |
28 #include <QStyledItemDelegate> | |
77 | 29 #include <QThreadPool> |
30 #include <set> | |
10 | 31 |
64 | 32 AnimeListPageDelegate::AnimeListPageDelegate(QObject* parent) : QStyledItemDelegate(parent) { |
10 | 33 } |
34 | |
64 | 35 QWidget* AnimeListPageDelegate::createEditor(QWidget*, const QStyleOptionViewItem&, const QModelIndex&) const { |
10 | 36 // no edit 4 u |
37 return nullptr; | |
38 } | |
39 | |
64 | 40 void AnimeListPageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, |
41 const QModelIndex& index) const { | |
10 | 42 switch (index.column()) { |
15 | 43 #if 0 |
64 | 44 case AnimeListPageModel::AL_PROGRESS: { |
10 | 45 const int progress = static_cast<int>(index.data(Qt::UserRole).toReal()); |
46 const int episodes = | |
64 | 47 static_cast<int>(index.siblingAtColumn(AnimeListPageModel::AL_EPISODES).data(Qt::UserRole).toReal()); |
10 | 48 |
49 int text_width = 59; | |
50 QRectF text_rect(option.rect.x() + text_width, option.rect.y(), text_width, option.decorationSize.height()); | |
51 painter->save(); | |
51 | 52 painter->drawText(text_rect, tr("/"), QTextOption(Qt::AlignCenter | Qt::AlignVCenter)); |
53 drawText(const QRectF &rectangle, const QString &text, const QTextOption &option = | |
15 | 54 QTextOption()) painter->drawText(QRectF(text_rect.x(), text_rect.y(), text_width / 2 - 2, |
55 text_rect.height()), QString::number(progress), QTextOption(Qt::AlignRight | Qt::AlignVCenter)); | |
56 painter->drawText( | |
57 QRectF(text_rect.x() + text_width / 2 + 2, text_rect.y(), text_width / 2 - 2, text_rect.height()), | |
58 QString::number(episodes), QTextOption(Qt::AlignLeft | Qt::AlignVCenter)); | |
59 painter->restore(); | |
60 QStyledItemDelegate::paint(painter, option, index); | |
61 break; | |
10 | 62 } |
15 | 63 #endif |
10 | 64 default: QStyledItemDelegate::paint(painter, option, index); break; |
65 } | |
66 } | |
67 | |
64 | 68 AnimeListPageSortFilter::AnimeListPageSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { |
10 | 69 } |
70 | |
64 | 71 bool AnimeListPageSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { |
10 | 72 QVariant left = sourceModel()->data(l, sortRole()); |
73 QVariant right = sourceModel()->data(r, sortRole()); | |
74 | |
75 switch (left.userType()) { | |
76 case QMetaType::Int: | |
77 case QMetaType::UInt: | |
78 case QMetaType::LongLong: | |
79 case QMetaType::ULongLong: return left.toInt() < right.toInt(); | |
80 case QMetaType::QDate: return left.toDate() < right.toDate(); | |
81 case QMetaType::QString: | |
82 default: return QString::compare(left.toString(), right.toString(), Qt::CaseInsensitive) < 0; | |
83 } | |
84 } | |
85 | |
64 | 86 AnimeListPageModel::AnimeListPageModel(QWidget* parent, Anime::ListStatus _status) : QAbstractListModel(parent) { |
10 | 87 status = _status; |
88 return; | |
89 } | |
90 | |
64 | 91 int AnimeListPageModel::rowCount(const QModelIndex& parent) const { |
10 | 92 return list.size(); |
93 (void)(parent); | |
94 } | |
95 | |
64 | 96 int AnimeListPageModel::columnCount(const QModelIndex& parent) const { |
10 | 97 return NB_COLUMNS; |
98 (void)(parent); | |
99 } | |
100 | |
64 | 101 QVariant AnimeListPageModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { |
10 | 102 if (role == Qt::DisplayRole) { |
103 switch (section) { | |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
104 case AL_TITLE: return tr("Anime title"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
105 case AL_PROGRESS: return tr("Progress"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
106 case AL_EPISODES: return tr("Episodes"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
107 case AL_TYPE: return tr("Type"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
108 case AL_SCORE: return tr("Score"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
109 case AL_SEASON: return tr("Season"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
110 case AL_STARTED: return tr("Date started"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
111 case AL_COMPLETED: return tr("Date completed"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
112 case AL_NOTES: return tr("Notes"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
113 case AL_AVG_SCORE: return tr("Average score"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
114 case AL_UPDATED: return tr("Last updated"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
115 default: return {}; |
10 | 116 } |
117 } else if (role == Qt::TextAlignmentRole) { | |
118 switch (section) { | |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
119 case AL_TITLE: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
120 case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
121 case AL_PROGRESS: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
122 case AL_EPISODES: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
123 case AL_TYPE: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
124 case AL_SCORE: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
125 case AL_AVG_SCORE: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
126 case AL_SEASON: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
127 case AL_STARTED: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
128 case AL_COMPLETED: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
129 case AL_UPDATED: return QVariant(Qt::AlignRight | Qt::AlignVCenter); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
130 default: return QAbstractListModel::headerData(section, orientation, role); |
10 | 131 } |
132 } | |
133 return QAbstractListModel::headerData(section, orientation, role); | |
134 } | |
135 | |
64 | 136 QVariant AnimeListPageModel::data(const QModelIndex& index, int role) const { |
10 | 137 if (!index.isValid()) |
138 return QVariant(); | |
139 switch (role) { | |
140 case Qt::DisplayRole: | |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
141 switch (index.column()) { |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
142 case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
143 case AL_PROGRESS: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
144 return QString::number(list[index.row()].GetUserProgress()) + "/" + |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
145 QString::number(list[index.row()].GetEpisodes()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
146 case AL_EPISODES: return list[index.row()].GetEpisodes(); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
147 case AL_SCORE: return list[index.row()].GetUserScore(); |
65
26721c28bf22
*: avoid usage of (to|from)StdString
Paper <mrpapersonic@gmail.com>
parents:
64
diff
changeset
|
148 case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat())); |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
149 case AL_SEASON: |
65
26721c28bf22
*: avoid usage of (to|from)StdString
Paper <mrpapersonic@gmail.com>
parents:
64
diff
changeset
|
150 return Strings::ToQString(Translate::ToString(list[index.row()].GetSeason())) + " " + |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
151 QString::number(list[index.row()].GetAirDate().GetYear()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
152 case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%"; |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
153 case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate(); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
154 case AL_COMPLETED: return list[index.row()].GetUserDateCompleted().GetAsQDate(); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
155 case AL_UPDATED: { |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
156 if (list[index.row()].GetUserTimeUpdated() == 0) |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
157 return QString("-"); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
158 Time::Duration duration(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
159 return QString::fromUtf8(duration.AsRelativeString().c_str()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
160 } |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
161 case AL_NOTES: return QString::fromUtf8(list[index.row()].GetUserNotes().c_str()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
162 default: return ""; |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
163 } |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
164 break; |
10 | 165 case Qt::UserRole: |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
166 switch (index.column()) { |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
167 case AL_PROGRESS: return list[index.row()].GetUserProgress(); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
168 case AL_TYPE: return static_cast<int>(list[index.row()].GetFormat()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
169 case AL_SEASON: return list[index.row()].GetAirDate().GetAsQDate(); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
170 case AL_AVG_SCORE: return list[index.row()].GetAudienceScore(); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
171 case AL_UPDATED: return QVariant::fromValue(list[index.row()].GetUserTimeUpdated()); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
172 default: return data(index, Qt::DisplayRole); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
173 } |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
174 break; |
10 | 175 case Qt::TextAlignmentRole: |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
176 switch (index.column()) { |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
177 case AL_TITLE: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
178 case AL_NOTES: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
179 case AL_PROGRESS: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
180 case AL_EPISODES: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
181 case AL_TYPE: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
182 case AL_SCORE: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
183 case AL_AVG_SCORE: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
184 case AL_SEASON: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
185 case AL_STARTED: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
186 case AL_COMPLETED: |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
187 case AL_UPDATED: return QVariant(Qt::AlignRight | Qt::AlignVCenter); |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
188 default: break; |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
189 } |
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
190 break; |
10 | 191 } |
192 return QVariant(); | |
193 } | |
194 | |
64 | 195 Anime::Anime* AnimeListPageModel::GetAnimeFromIndex(QModelIndex index) { |
10 | 196 return &list.at(index.row()); |
197 } | |
198 | |
64 | 199 void AnimeListPageModel::RefreshList() { |
10 | 200 bool has_children = !!rowCount(index(0)); |
77 | 201 if (!has_children) { |
202 beginInsertRows(QModelIndex(), 0, 0); | |
203 endInsertRows(); | |
15 | 204 } |
205 | |
77 | 206 beginResetModel(); |
207 | |
10 | 208 list.clear(); |
209 | |
11 | 210 for (const auto& a : Anime::db.items) { |
211 if (a.second.IsInUserList() && a.second.GetUserStatus() == status) { | |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
212 list.push_back(a.second); |
10 | 213 } |
214 } | |
15 | 215 |
77 | 216 endResetModel(); |
10 | 217 } |
218 | |
64 | 219 int AnimeListPage::VisibleColumnsCount() const { |
10 | 220 int count = 0; |
221 | |
222 for (int i = 0, end = tree_view->header()->count(); i < end; i++) { | |
223 if (!tree_view->isColumnHidden(i)) | |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
224 count++; |
10 | 225 } |
226 | |
227 return count; | |
228 } | |
229 | |
64 | 230 void AnimeListPage::SetColumnDefaults() { |
231 tree_view->setColumnHidden(AnimeListPageModel::AL_SEASON, false); | |
232 tree_view->setColumnHidden(AnimeListPageModel::AL_TYPE, false); | |
233 tree_view->setColumnHidden(AnimeListPageModel::AL_UPDATED, false); | |
234 tree_view->setColumnHidden(AnimeListPageModel::AL_PROGRESS, false); | |
235 tree_view->setColumnHidden(AnimeListPageModel::AL_SCORE, false); | |
236 tree_view->setColumnHidden(AnimeListPageModel::AL_TITLE, false); | |
237 tree_view->setColumnHidden(AnimeListPageModel::AL_EPISODES, true); | |
238 tree_view->setColumnHidden(AnimeListPageModel::AL_AVG_SCORE, true); | |
239 tree_view->setColumnHidden(AnimeListPageModel::AL_STARTED, true); | |
240 tree_view->setColumnHidden(AnimeListPageModel::AL_COMPLETED, true); | |
241 tree_view->setColumnHidden(AnimeListPageModel::AL_UPDATED, true); | |
242 tree_view->setColumnHidden(AnimeListPageModel::AL_NOTES, true); | |
10 | 243 } |
244 | |
77 | 245 void AnimeListPage::UpdateAnime(int id) { |
246 QThreadPool::globalInstance()->start([this, id] { | |
247 Services::UpdateAnimeEntry(id); | |
248 Refresh(); | |
249 }); | |
250 } | |
251 | |
252 void AnimeListPage::RemoveAnime(int id) { | |
253 Anime::Anime& anime = Anime::db.items[id]; | |
254 anime.RemoveFromUserList(); | |
255 Refresh(); | |
256 } | |
257 | |
64 | 258 void AnimeListPage::DisplayColumnHeaderMenu() { |
10 | 259 QMenu* menu = new QMenu(this); |
260 menu->setAttribute(Qt::WA_DeleteOnClose); | |
261 menu->setTitle(tr("Column visibility")); | |
262 menu->setToolTipsVisible(true); | |
263 | |
64 | 264 for (int i = 0; i < AnimeListPageModel::NB_COLUMNS; i++) { |
265 if (i == AnimeListPageModel::AL_TITLE) | |
47
d8eb763e6661
information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents:
46
diff
changeset
|
266 continue; |
10 | 267 const auto column_name = |
15 | 268 sort_models[tab_bar->currentIndex()]->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); |
10 | 269 QAction* action = menu->addAction(column_name, this, [this, i](const bool checked) { |
270 if (!checked && (VisibleColumnsCount() <= 1)) | |
271 return; | |
272 | |
273 tree_view->setColumnHidden(i, !checked); | |
274 | |
275 if (checked && (tree_view->columnWidth(i) <= 5)) | |
276 tree_view->resizeColumnToContents(i); | |
277 | |
278 // SaveSettings(); | |
279 }); | |
280 action->setCheckable(true); | |
281 action->setChecked(!tree_view->isColumnHidden(i)); | |
282 } | |
283 | |
284 menu->addSeparator(); | |
285 QAction* resetAction = menu->addAction(tr("Reset to defaults"), this, [this]() { | |
286 for (int i = 0, count = tree_view->header()->count(); i < count; ++i) { | |
287 SetColumnDefaults(); | |
288 } | |
289 // SaveSettings(); | |
290 }); | |
291 menu->popup(QCursor::pos()); | |
292 (void)(resetAction); | |
293 } | |
294 | |
64 | 295 void AnimeListPage::DisplayListMenu() { |
10 | 296 QMenu* menu = new QMenu(this); |
297 menu->setAttribute(Qt::WA_DeleteOnClose); | |
298 menu->setTitle(tr("Column visibility")); | |
299 menu->setToolTipsVisible(true); | |
300 | |
77 | 301 AnimeListPageModel* source_model = |
302 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); | |
15 | 303 const QItemSelection selection = |
304 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); | |
77 | 305 |
306 std::set<Anime::Anime*> animes; | |
307 for (const auto& index : selection.indexes()) { | |
308 if (!index.isValid()) | |
309 continue; | |
310 Anime::Anime* anime = source_model->GetAnimeFromIndex(index); | |
311 if (anime) | |
312 animes.insert(anime); | |
10 | 313 } |
314 | |
77 | 315 QAction* action = menu->addAction(tr("Information"), [this, animes] { |
316 for (auto& anime : animes) { | |
317 InformationDialog* dialog = new InformationDialog( | |
318 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, this); | |
10 | 319 |
77 | 320 dialog->show(); |
321 dialog->raise(); | |
322 dialog->activateWindow(); | |
323 } | |
324 }); | |
325 menu->addSeparator(); | |
326 action = menu->addAction(tr("Delete from list..."), [this, animes] { | |
327 for (auto& anime : animes) { | |
328 RemoveAnime(anime->GetId()); | |
329 } | |
10 | 330 }); |
331 menu->popup(QCursor::pos()); | |
332 } | |
333 | |
64 | 334 void AnimeListPage::ItemDoubleClicked() { |
10 | 335 /* throw out any other garbage */ |
336 const QItemSelection selection = | |
15 | 337 sort_models[tab_bar->currentIndex()]->mapSelectionToSource(tree_view->selectionModel()->selection()); |
10 | 338 if (!selection.indexes().first().isValid()) { |
339 return; | |
340 } | |
341 | |
64 | 342 AnimeListPageModel* source_model = |
343 reinterpret_cast<AnimeListPageModel*>(sort_models[tab_bar->currentIndex()]->sourceModel()); | |
344 | |
345 const QModelIndex index = source_model->index(selection.indexes().first().row()); | |
346 Anime::Anime* anime = source_model->GetAnimeFromIndex(index); | |
10 | 347 |
63 | 348 InformationDialog* dialog = new InformationDialog( |
77 | 349 *anime, [this, anime] { UpdateAnime(anime->GetId()); }, this); |
10 | 350 |
351 dialog->show(); | |
352 dialog->raise(); | |
353 dialog->activateWindow(); | |
354 } | |
355 | |
64 | 356 void AnimeListPage::paintEvent(QPaintEvent*) { |
10 | 357 QStylePainter p(this); |
358 | |
359 QStyleOptionTabWidgetFrame opt; | |
360 InitStyle(&opt); | |
361 opt.rect = panelRect; | |
362 p.drawPrimitive(QStyle::PE_FrameTabWidget, opt); | |
363 } | |
364 | |
64 | 365 void AnimeListPage::resizeEvent(QResizeEvent* e) { |
10 | 366 QWidget::resizeEvent(e); |
367 SetupLayout(); | |
368 } | |
369 | |
64 | 370 void AnimeListPage::showEvent(QShowEvent*) { |
10 | 371 SetupLayout(); |
372 } | |
373 | |
64 | 374 void AnimeListPage::InitBasicStyle(QStyleOptionTabWidgetFrame* option) const { |
10 | 375 if (!option) |
376 return; | |
377 | |
378 option->initFrom(this); | |
379 option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, this); | |
380 option->shape = QTabBar::RoundedNorth; | |
381 option->tabBarRect = tab_bar->geometry(); | |
382 } | |
383 | |
64 | 384 void AnimeListPage::InitStyle(QStyleOptionTabWidgetFrame* option) const { |
10 | 385 if (!option) |
386 return; | |
387 | |
388 InitBasicStyle(option); | |
389 | |
390 // int exth = style()->pixelMetric(QStyle::PM_TabBarBaseHeight, nullptr, this); | |
391 QSize t(0, tree_view->frameWidth()); | |
392 if (tab_bar->isVisibleTo(this)) { | |
393 t = tab_bar->sizeHint(); | |
394 t.setWidth(width()); | |
395 } | |
46 | 396 |
10 | 397 option->tabBarSize = t; |
398 | |
399 QRect selected_tab_rect = tab_bar->tabRect(tab_bar->currentIndex()); | |
400 selected_tab_rect.moveTopLeft(selected_tab_rect.topLeft() + option->tabBarRect.topLeft()); | |
401 option->selectedTabRect = selected_tab_rect; | |
402 | |
403 option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, this); | |
404 } | |
405 | |
64 | 406 void AnimeListPage::SetupLayout() { |
10 | 407 QStyleOptionTabWidgetFrame option; |
408 InitStyle(&option); | |
409 | |
410 QRect tabRect = style()->subElementRect(QStyle::SE_TabWidgetTabBar, &option, this); | |
411 tabRect.setLeft(tabRect.left() + 1); | |
412 panelRect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option, this); | |
413 QRect contentsRect = style()->subElementRect(QStyle::SE_TabWidgetTabContents, &option, this); | |
414 | |
415 tab_bar->setGeometry(tabRect); | |
416 tree_view->parentWidget()->setGeometry(contentsRect); | |
417 } | |
418 | |
64 | 419 AnimeListPage::AnimeListPage(QWidget* parent) : QWidget(parent) { |
10 | 420 /* Tab bar */ |
421 tab_bar = new QTabBar(this); | |
422 tab_bar->setExpanding(false); | |
423 tab_bar->setDrawBase(false); | |
424 | |
425 /* Tree view... */ | |
426 QWidget* tree_widget = new QWidget(this); | |
427 tree_view = new QTreeView(tree_widget); | |
64 | 428 tree_view->setItemDelegate(new AnimeListPageDelegate(tree_view)); |
10 | 429 tree_view->setUniformRowHeights(true); |
430 tree_view->setAllColumnsShowFocus(false); | |
431 tree_view->setAlternatingRowColors(true); | |
432 tree_view->setSortingEnabled(true); | |
433 tree_view->setSelectionMode(QAbstractItemView::ExtendedSelection); | |
434 tree_view->setItemsExpandable(false); | |
435 tree_view->setRootIsDecorated(false); | |
436 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); | |
437 tree_view->setFrameShape(QFrame::NoFrame); | |
438 | |
83 | 439 for (unsigned int i = 0; i < sort_models.size(); i++) { |
65
26721c28bf22
*: avoid usage of (to|from)StdString
Paper <mrpapersonic@gmail.com>
parents:
64
diff
changeset
|
440 tab_bar->addTab(Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + |
15 | 441 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); |
64 | 442 sort_models[i] = new AnimeListPageSortFilter(tree_view); |
443 sort_models[i]->setSourceModel(new AnimeListPageModel(this, Anime::ListStatuses[i])); | |
10 | 444 sort_models[i]->setSortRole(Qt::UserRole); |
445 sort_models[i]->setSortCaseSensitivity(Qt::CaseInsensitive); | |
446 } | |
15 | 447 tree_view->setModel(sort_models[0]); |
10 | 448 |
68
2417121d894e
*: normalize usage of layouts
Paper <mrpapersonic@gmail.com>
parents:
65
diff
changeset
|
449 QHBoxLayout* layout = new QHBoxLayout(tree_widget); |
10 | 450 layout->addWidget(tree_view); |
62 | 451 layout->setContentsMargins(0, 0, 0, 0); |
10 | 452 |
453 /* Double click stuff */ | |
64 | 454 connect(tree_view, &QAbstractItemView::doubleClicked, this, &AnimeListPage::ItemDoubleClicked); |
455 connect(tree_view, &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayListMenu); | |
10 | 456 |
457 /* Enter & return keys */ | |
15 | 458 connect(new QShortcut(Qt::Key_Return, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, |
64 | 459 &AnimeListPage::ItemDoubleClicked); |
10 | 460 |
15 | 461 connect(new QShortcut(Qt::Key_Enter, tree_view, nullptr, nullptr, Qt::WidgetShortcut), &QShortcut::activated, this, |
64 | 462 &AnimeListPage::ItemDoubleClicked); |
10 | 463 |
464 tree_view->header()->setStretchLastSection(false); | |
465 tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu); | |
64 | 466 connect(tree_view->header(), &QWidget::customContextMenuRequested, this, &AnimeListPage::DisplayColumnHeaderMenu); |
10 | 467 |
468 connect(tab_bar, &QTabBar::currentChanged, this, [this](int index) { | |
469 if (sort_models[index]) | |
470 tree_view->setModel(sort_models[index]); | |
471 }); | |
472 | |
69 | 473 SetColumnDefaults(); |
10 | 474 setFocusPolicy(Qt::TabFocus); |
475 setFocusProxy(tab_bar); | |
476 } | |
477 | |
64 | 478 void AnimeListPage::RefreshList() { |
83 | 479 for (unsigned int i = 0; i < sort_models.size(); i++) |
64 | 480 reinterpret_cast<AnimeListPageModel*>(sort_models[i]->sourceModel())->RefreshList(); |
10 | 481 } |
482 | |
64 | 483 void AnimeListPage::RefreshTabs() { |
83 | 484 for (unsigned int i = 0; i < sort_models.size(); i++) |
65
26721c28bf22
*: avoid usage of (to|from)StdString
Paper <mrpapersonic@gmail.com>
parents:
64
diff
changeset
|
485 tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" + |
15 | 486 QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"); |
487 } | |
488 | |
64 | 489 void AnimeListPage::Refresh() { |
15 | 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. */ | |
64 | 497 void AnimeListPage::Reset() { |
10 | 498 while (tab_bar->count()) |
499 tab_bar->removeTab(0); | |
83 | 500 for (unsigned int i = 0; i < sort_models.size(); i++) |
10 | 501 delete sort_models[i]; |
502 } | |
503 | |
504 #include "gui/pages/moc_anime_list.cpp" |