Mercurial > minori
annotate src/anime.cpp @ 6:1d82f6e04d7d
Update: add first parts to the settings dialog
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 16 Aug 2023 00:49:17 -0400 |
parents | 190ded9438c0 |
children | 07a9095eaeed |
rev | line source |
---|---|
2 | 1 #include <chrono> |
2 #include <string> | |
3 #include <vector> | |
4 #include <cmath> | |
5 #include "window.h" | |
6 #include "anilist.h" | |
7 #include "config.h" | |
8 #include "anime.h" | |
9 #include "date.h" | |
10 #include "time_utils.h" | |
11 #include "information.h" | |
12 #include "ui_utils.h" | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
13 #include <iostream> |
2 | 14 |
15 std::map<enum AnimeWatchingStatus, std::string> AnimeWatchingToStringMap = { | |
16 {CURRENT, "Watching"}, | |
17 {PLANNING, "Planning"}, | |
18 {COMPLETED, "Completed"}, | |
19 {DROPPED, "Dropped"}, | |
20 {PAUSED, "On hold"}, | |
21 {REPEATING, "Rewatching"} | |
22 }; | |
23 | |
24 std::map<enum AnimeAiringStatus, std::string> AnimeAiringToStringMap = { | |
25 {FINISHED, "Finished"}, | |
26 {RELEASING, "Airing"}, | |
27 {NOT_YET_RELEASED, "Not aired yet"}, | |
28 {CANCELLED, "Cancelled"}, | |
29 {HIATUS, "On hiatus"} | |
30 }; | |
31 | |
32 std::map<enum AnimeSeason, std::string> AnimeSeasonToStringMap = { | |
33 {UNKNOWN, "Unknown"}, | |
34 {WINTER, "Winter"}, | |
35 {SPRING, "Spring"}, | |
36 {SUMMER, "Summer"}, | |
37 {FALL, "Fall"} | |
38 }; | |
39 | |
40 std::map<enum AnimeFormat, std::string> AnimeFormatToStringMap = { | |
41 {TV, "TV"}, | |
42 {TV_SHORT, "TV short"}, | |
43 {MOVIE, "Movie"}, | |
44 {SPECIAL, "Special"}, | |
45 {OVA, "OVA"}, | |
46 {ONA, "ONA"}, | |
47 {MUSIC, "Music video"}, | |
48 /* these should NEVER be in the list. naybe we should | |
49 remove them? */ | |
50 {MANGA, "Manga"}, | |
51 {NOVEL, "Novel"}, | |
52 {ONE_SHOT, "One-shot"} | |
53 }; | |
54 | |
55 Anime::Anime() {} | |
56 Anime::Anime(const Anime& a) { | |
57 status = a.status; | |
58 progress = a.progress; | |
59 score = a.score; | |
60 started = a.started; | |
61 completed = a.completed; | |
62 updated = a.updated; | |
63 notes = a.notes; | |
64 id = a.id; | |
65 title = a.title; | |
66 episodes = a.episodes; | |
67 airing = a.airing; | |
68 air_date = a.air_date; | |
69 genres = a.genres; | |
70 producers = a.producers; | |
71 type = a.type; | |
72 season = a.season; | |
73 audience_score = a.audience_score; | |
74 synopsis = a.synopsis; | |
75 duration = a.duration; | |
76 } | |
77 | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
78 std::string Anime::GetUserPreferredTitle() { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
79 if (title.english.empty()) |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
80 return title.romaji; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
81 return title.english; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
82 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
83 |
2 | 84 void AnimeList::Add(Anime& anime) { |
85 if (anime_id_to_anime.contains(anime.id)) | |
86 return; | |
87 anime_list.push_back(anime); | |
88 anime_id_to_anime.emplace(anime.id, &anime); | |
89 } | |
90 | |
91 void AnimeList::Insert(size_t pos, Anime& anime) { | |
92 if (anime_id_to_anime.contains(anime.id)) | |
93 return; | |
94 anime_list.insert(anime_list.begin()+pos, anime); | |
95 anime_id_to_anime.emplace(anime.id, &anime); | |
96 } | |
97 | |
98 void AnimeList::Delete(size_t index) { | |
99 anime_list.erase(anime_list.begin()+index); | |
100 } | |
101 | |
102 void AnimeList::Clear() { | |
103 anime_list.clear(); | |
104 } | |
105 | |
106 size_t AnimeList::Size() const { | |
107 return anime_list.size(); | |
108 } | |
109 | |
110 std::vector<Anime>::iterator AnimeList::begin() noexcept { | |
111 return anime_list.begin(); | |
112 } | |
113 | |
114 std::vector<Anime>::iterator AnimeList::end() noexcept { | |
115 return anime_list.end(); | |
116 } | |
117 | |
118 std::vector<Anime>::const_iterator AnimeList::cbegin() noexcept { | |
119 return anime_list.cbegin(); | |
120 } | |
121 | |
122 std::vector<Anime>::const_iterator AnimeList::cend() noexcept { | |
123 return anime_list.cend(); | |
124 } | |
125 | |
126 AnimeList::AnimeList() {} | |
127 AnimeList::AnimeList(const AnimeList& l) { | |
3 | 128 for (unsigned long long i = 0; i < l.Size(); i++) { |
2 | 129 anime_list.push_back(Anime(l[i])); |
130 } | |
131 name = l.name; | |
132 } | |
133 | |
134 AnimeList::~AnimeList() { | |
135 anime_list.clear(); | |
136 anime_list.shrink_to_fit(); | |
137 } | |
138 | |
139 Anime* AnimeList::AnimeById(int id) { | |
140 return anime_id_to_anime.contains(id) ? anime_id_to_anime[id] : nullptr; | |
141 } | |
142 | |
143 bool AnimeList::AnimeInList(int id) { | |
144 return anime_id_to_anime.contains(id); | |
145 } | |
146 | |
147 int AnimeList::GetAnimeIndex(Anime& anime) const { | |
3 | 148 for (unsigned long long i = 0; i < Size(); i++) { |
2 | 149 if (&anime_list.at(i) == &anime) { // lazy |
150 return i; | |
151 } | |
152 } | |
153 return -1; | |
154 } | |
155 | |
156 Anime& AnimeList::operator[](std::size_t index) { | |
157 return anime_list.at(index); | |
158 } | |
159 | |
160 const Anime& AnimeList::operator[](std::size_t index) const { | |
161 return anime_list.at(index); | |
162 } | |
163 | |
164 /* ------------------------------------------------------------------------- */ | |
165 | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
166 AnimeListWidgetDelegate::AnimeListWidgetDelegate(QObject* parent) |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
167 : QStyledItemDelegate (parent) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
168 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
169 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
170 QWidget *AnimeListWidgetDelegate::createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
171 { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
172 // LOL |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
173 return nullptr; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
174 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
175 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
176 void AnimeListWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
177 { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
178 switch (index.column()) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
179 case AnimeListWidgetModel::AL_PROGRESS: { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
180 const int progress = static_cast<int>(index.data(Qt::UserRole).toReal()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
181 const int episodes = static_cast<int>(index.siblingAtColumn(AnimeListWidgetModel::AL_EPISODES).data(Qt::UserRole).toReal()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
182 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
183 QStyleOptionViewItem customOption (option); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
184 customOption.state.setFlag(QStyle::State_Enabled, true); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
185 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
186 progress_bar.paint(painter, customOption, index.data().toString(), progress, episodes); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
187 break; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
188 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
189 default: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
190 QStyledItemDelegate::paint(painter, option, index); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
191 break; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
192 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
193 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
194 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
195 AnimeListWidgetSortFilter::AnimeListWidgetSortFilter(QObject *parent) |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
196 : QSortFilterProxyModel(parent) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
197 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
198 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
199 bool AnimeListWidgetSortFilter::lessThan(const QModelIndex &l, |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
200 const QModelIndex &r) const { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
201 QVariant left = sourceModel()->data(l, sortRole()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
202 QVariant right = sourceModel()->data(r, sortRole()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
203 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
204 switch (left.userType()) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
205 case QMetaType::Int: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
206 case QMetaType::UInt: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
207 case QMetaType::LongLong: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
208 case QMetaType::ULongLong: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
209 return left.toInt() < right.toInt(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
210 case QMetaType::QDate: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
211 return left.toDate() < right.toDate(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
212 case QMetaType::QString: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
213 default: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
214 return left.toString() < right.toString(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
215 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
216 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
217 |
2 | 218 /* Thank you qBittorrent for having a great example of a |
219 widget model. */ | |
220 AnimeListWidgetModel::AnimeListWidgetModel (QWidget* parent, AnimeList* alist) | |
221 : QAbstractListModel(parent) | |
222 , list(*alist) { | |
223 return; | |
224 } | |
225 | |
226 int AnimeListWidgetModel::rowCount(const QModelIndex& parent) const { | |
227 return list.Size(); | |
3 | 228 (void)(parent); |
2 | 229 } |
230 | |
231 int AnimeListWidgetModel::columnCount(const QModelIndex& parent) const { | |
232 return NB_COLUMNS; | |
3 | 233 (void)(parent); |
2 | 234 } |
235 | |
236 QVariant AnimeListWidgetModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { | |
237 if (role == Qt::DisplayRole) { | |
238 switch (section) { | |
239 case AL_TITLE: | |
240 return tr("Anime title"); | |
241 case AL_PROGRESS: | |
242 return tr("Progress"); | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
243 case AL_EPISODES: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
244 return tr("Episodes"); |
2 | 245 case AL_TYPE: |
246 return tr("Type"); | |
247 case AL_SCORE: | |
248 return tr("Score"); | |
249 case AL_SEASON: | |
250 return tr("Season"); | |
251 case AL_STARTED: | |
252 return tr("Date started"); | |
253 case AL_COMPLETED: | |
254 return tr("Date completed"); | |
255 case AL_NOTES: | |
256 return tr("Notes"); | |
257 case AL_AVG_SCORE: | |
258 return tr("Average score"); | |
259 case AL_UPDATED: | |
260 return tr("Last updated"); | |
261 default: | |
262 return {}; | |
263 } | |
264 } else if (role == Qt::TextAlignmentRole) { | |
265 switch (section) { | |
266 case AL_TITLE: | |
267 case AL_NOTES: | |
268 return QVariant(Qt::AlignLeft | Qt::AlignVCenter); | |
269 case AL_PROGRESS: | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
270 case AL_EPISODES: |
2 | 271 case AL_TYPE: |
272 case AL_SCORE: | |
273 case AL_AVG_SCORE: | |
274 return QVariant(Qt::AlignCenter | Qt::AlignVCenter); | |
275 case AL_SEASON: | |
276 case AL_STARTED: | |
277 case AL_COMPLETED: | |
278 case AL_UPDATED: | |
279 return QVariant(Qt::AlignRight | Qt::AlignVCenter); | |
280 default: | |
281 return QAbstractListModel::headerData(section, orientation, role); | |
282 } | |
283 } | |
284 return QAbstractListModel::headerData(section, orientation, role); | |
285 } | |
286 | |
287 Anime* AnimeListWidgetModel::GetAnimeFromIndex(const QModelIndex& index) { | |
288 return (index.isValid()) ? &(list[index.row()]) : nullptr; | |
289 } | |
290 | |
291 QVariant AnimeListWidgetModel::data(const QModelIndex& index, int role) const { | |
292 if (!index.isValid()) | |
293 return QVariant(); | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
294 switch (role) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
295 case Qt::DisplayRole: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
296 switch (index.column()) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
297 case AL_TITLE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
298 return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
299 case AL_PROGRESS: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
300 return QString::number(list[index.row()].progress) + "/" + QString::number(list[index.row()].episodes); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
301 case AL_EPISODES: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
302 return list[index.row()].episodes; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
303 case AL_SCORE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
304 return list[index.row()].score; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
305 case AL_TYPE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
306 return QString::fromStdString(AnimeFormatToStringMap[list[index.row()].type]); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
307 case AL_SEASON: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
308 return QString::fromStdString(AnimeSeasonToStringMap[list[index.row()].season]) + " " + QString::number(list[index.row()].air_date.GetYear()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
309 case AL_AVG_SCORE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
310 return QString::number(list[index.row()].audience_score) + "%"; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
311 case AL_STARTED: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
312 return list[index.row()].started.GetAsQDate(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
313 case AL_COMPLETED: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
314 return list[index.row()].completed.GetAsQDate(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
315 case AL_UPDATED: { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
316 if (list[index.row()].updated == 0) |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
317 return QString("-"); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
318 Time::Duration duration(Time::GetSystemTime() - list[index.row()].updated); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
319 return QString::fromUtf8(duration.AsRelativeString().c_str()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
320 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
321 case AL_NOTES: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
322 return QString::fromUtf8(list[index.row()].notes.c_str()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
323 default: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
324 return ""; |
2 | 325 } |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
326 break; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
327 case Qt::UserRole: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
328 switch (index.column()) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
329 case AL_PROGRESS: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
330 return list[index.row()].progress; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
331 case AL_TYPE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
332 return list[index.row()].type; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
333 case AL_SEASON: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
334 return list[index.row()].air_date.GetAsQDate(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
335 case AL_AVG_SCORE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
336 return list[index.row()].audience_score; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
337 case AL_UPDATED: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
338 return list[index.row()].updated; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
339 default: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
340 return data(index, Qt::DisplayRole); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
341 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
342 break; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
343 case Qt::TextAlignmentRole: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
344 switch (index.column()) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
345 case AL_TITLE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
346 case AL_NOTES: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
347 return QVariant(Qt::AlignLeft | Qt::AlignVCenter); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
348 case AL_PROGRESS: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
349 case AL_EPISODES: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
350 case AL_TYPE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
351 case AL_SCORE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
352 case AL_AVG_SCORE: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
353 return QVariant(Qt::AlignCenter | Qt::AlignVCenter); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
354 case AL_SEASON: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
355 case AL_STARTED: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
356 case AL_COMPLETED: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
357 case AL_UPDATED: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
358 return QVariant(Qt::AlignRight | Qt::AlignVCenter); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
359 default: |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
360 break; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
361 } |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
362 break; |
2 | 363 } |
364 return QVariant(); | |
365 } | |
366 | |
367 void AnimeListWidgetModel::UpdateAnime(Anime& anime) { | |
368 int i = list.GetAnimeIndex(anime); | |
369 emit dataChanged(index(i), index(i)); | |
370 } | |
371 | |
372 int AnimeListWidget::VisibleColumnsCount() const { | |
373 int count = 0; | |
374 | |
375 for (int i = 0, end = header()->count(); i < end; i++) | |
376 { | |
377 if (!isColumnHidden(i)) | |
378 count++; | |
379 } | |
380 | |
381 return count; | |
382 } | |
383 | |
384 void AnimeListWidget::SetColumnDefaults() { | |
385 setColumnHidden(AnimeListWidgetModel::AL_SEASON, false); | |
386 setColumnHidden(AnimeListWidgetModel::AL_TYPE, false); | |
387 setColumnHidden(AnimeListWidgetModel::AL_UPDATED, false); | |
388 setColumnHidden(AnimeListWidgetModel::AL_PROGRESS, false); | |
389 setColumnHidden(AnimeListWidgetModel::AL_SCORE, false); | |
390 setColumnHidden(AnimeListWidgetModel::AL_TITLE, false); | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
391 setColumnHidden(AnimeListWidgetModel::AL_EPISODES, true); |
2 | 392 setColumnHidden(AnimeListWidgetModel::AL_AVG_SCORE, true); |
393 setColumnHidden(AnimeListWidgetModel::AL_STARTED, true); | |
394 setColumnHidden(AnimeListWidgetModel::AL_COMPLETED, true); | |
395 setColumnHidden(AnimeListWidgetModel::AL_UPDATED, true); | |
396 setColumnHidden(AnimeListWidgetModel::AL_NOTES, true); | |
397 } | |
398 | |
399 void AnimeListWidget::DisplayColumnHeaderMenu() { | |
400 QMenu *menu = new QMenu(this); | |
401 menu->setAttribute(Qt::WA_DeleteOnClose); | |
402 menu->setTitle(tr("Column visibility")); | |
403 menu->setToolTipsVisible(true); | |
404 | |
3 | 405 for (int i = 0; i < AnimeListWidgetModel::NB_COLUMNS; i++) { |
2 | 406 if (i == AnimeListWidgetModel::AL_TITLE) |
407 continue; | |
408 const auto column_name = model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); | |
409 QAction *action = menu->addAction(column_name, this, [this, i](const bool checked) { | |
410 if (!checked && (VisibleColumnsCount() <= 1)) | |
411 return; | |
412 | |
413 setColumnHidden(i, !checked); | |
414 | |
415 if (checked && (columnWidth(i) <= 5)) | |
416 resizeColumnToContents(i); | |
417 | |
418 // SaveSettings(); | |
419 }); | |
420 action->setCheckable(true); | |
421 action->setChecked(!isColumnHidden(i)); | |
422 } | |
423 | |
424 menu->addSeparator(); | |
3 | 425 QAction *resetAction = menu->addAction(tr("Reset to defaults"), this, [this]() { |
2 | 426 for (int i = 0, count = header()->count(); i < count; ++i) |
427 { | |
428 SetColumnDefaults(); | |
429 } | |
430 // SaveSettings(); | |
431 }); | |
432 menu->popup(QCursor::pos()); | |
3 | 433 (void)(resetAction); |
2 | 434 } |
435 | |
436 void AnimeListWidget::DisplayListMenu() { | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
437 QMenu *menu = new QMenu(this); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
438 menu->setAttribute(Qt::WA_DeleteOnClose); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
439 menu->setTitle(tr("Column visibility")); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
440 menu->setToolTipsVisible(true); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
441 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
442 const QItemSelection selection = sort_model->mapSelectionToSource(selectionModel()->selection()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
443 if (!selection.indexes().first().isValid()) { |
2 | 444 return; |
3 | 445 } |
2 | 446 |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
447 QAction* action = menu->addAction("Information", [this, selection]{ |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
448 const QModelIndex index = model->index(selection.indexes().first().row()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
449 Anime* anime = model->GetAnimeFromIndex(index); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
450 if (!anime) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
451 return; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
452 } |
2 | 453 |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
454 InformationDialog* dialog = new InformationDialog(*anime, model, this); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
455 |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
456 dialog->show(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
457 dialog->raise(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
458 dialog->activateWindow(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
459 }); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
460 menu->popup(QCursor::pos()); |
2 | 461 } |
462 | |
463 void AnimeListWidget::ItemDoubleClicked() { | |
464 /* throw out any other garbage */ | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
465 const QItemSelection selection = sort_model->mapSelectionToSource(selectionModel()->selection()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
466 if (!selection.indexes().first().isValid()) { |
2 | 467 return; |
3 | 468 } |
2 | 469 |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
470 const QModelIndex index = model->index(selection.indexes().first().row()); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
471 const QString title = index.siblingAtColumn(AnimeListWidgetModel::AL_TITLE).data(Qt::UserRole).toString(); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
472 QMessageBox box; |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
473 box.setText(QString::number(title.size())); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
474 box.exec(); |
2 | 475 Anime* anime = model->GetAnimeFromIndex(index); |
3 | 476 if (!anime) { |
2 | 477 return; |
3 | 478 } |
2 | 479 |
480 InformationDialog* dialog = new InformationDialog(*anime, model, this); | |
481 | |
482 dialog->show(); | |
483 dialog->raise(); | |
484 dialog->activateWindow(); | |
485 } | |
486 | |
487 AnimeListWidget::AnimeListWidget(QWidget* parent, AnimeList* alist) | |
488 : QTreeView(parent) { | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
489 setItemDelegate(new AnimeListWidgetDelegate(this)); |
2 | 490 model = new AnimeListWidgetModel(parent, alist); |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
491 sort_model = new AnimeListWidgetSortFilter(this); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
492 sort_model->setSourceModel(model); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
493 sort_model->setSortRole(Qt::UserRole); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
494 setModel(sort_model); |
2 | 495 setObjectName("listwidget"); |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
496 setStyleSheet("QTreeView#listwidget{border:0px;}"); |
2 | 497 setUniformRowHeights(true); |
498 setAllColumnsShowFocus(false); | |
499 setSortingEnabled(true); | |
500 setSelectionMode(QAbstractItemView::ExtendedSelection); | |
501 setItemsExpandable(false); | |
502 setRootIsDecorated(false); | |
503 setContextMenuPolicy(Qt::CustomContextMenu); | |
3 | 504 connect(this, &QAbstractItemView::doubleClicked, this, &AnimeListWidget::ItemDoubleClicked); |
505 connect(this, &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayListMenu); | |
2 | 506 |
507 /* Enter & return keys */ | |
508 connect(new QShortcut(Qt::Key_Return, this, nullptr, nullptr, Qt::WidgetShortcut), | |
3 | 509 &QShortcut::activated, this, &AnimeListWidget::ItemDoubleClicked); |
2 | 510 |
511 connect(new QShortcut(Qt::Key_Enter, this, nullptr, nullptr, Qt::WidgetShortcut), | |
3 | 512 &QShortcut::activated, this, &AnimeListWidget::ItemDoubleClicked); |
2 | 513 |
514 header()->setStretchLastSection(false); | |
515 header()->setContextMenuPolicy(Qt::CustomContextMenu); | |
3 | 516 connect(header(), &QWidget::customContextMenuRequested, this, &AnimeListWidget::DisplayColumnHeaderMenu); |
2 | 517 // if(!session.config.anime_list.columns) { |
518 SetColumnDefaults(); | |
519 // } | |
520 } | |
521 | |
522 AnimeListPage::AnimeListPage(QWidget* parent) : QTabWidget (parent) { | |
523 setDocumentMode(false); | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
524 setObjectName("animepage"); |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
525 //setStyleSheet("QTabWidget#animepage{border-bottom:0px;border-left:0px;border-right:0px;}"); |
2 | 526 SyncAnimeList(); |
527 for (AnimeList& list : anime_lists) { | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
528 addTab(new AnimeListWidget(this, &list), QString::fromUtf8(list.name.c_str())); |
2 | 529 } |
530 } | |
531 | |
532 void AnimeListPage::SyncAnimeList() { | |
533 switch (session.config.service) { | |
534 case ANILIST: { | |
535 AniList anilist = AniList(); | |
536 session.config.anilist.user_id = anilist.GetUserId(session.config.anilist.username); | |
537 FreeAnimeList(); | |
538 anilist.UpdateAnimeList(&anime_lists, session.config.anilist.user_id); | |
539 break; | |
540 } | |
3 | 541 default: |
542 break; | |
2 | 543 } |
544 } | |
545 | |
546 void AnimeListPage::FreeAnimeList() { | |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
547 for (auto& list : anime_lists) { |
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
548 list.Clear(); |
2 | 549 } |
6
1d82f6e04d7d
Update: add first parts to the settings dialog
Paper <mrpapersonic@gmail.com>
parents:
3
diff
changeset
|
550 anime_lists.clear(); |
2 | 551 } |
552 | |
553 int AnimeListPage::GetTotalAnimeAmount() { | |
554 int total = 0; | |
555 for (auto& list : anime_lists) { | |
556 total += list.Size(); | |
557 } | |
558 return total; | |
559 } | |
560 | |
561 int AnimeListPage::GetTotalEpisodeAmount() { | |
562 /* FIXME: this also needs to take into account rewatches... */ | |
563 int total = 0; | |
564 for (auto& list : anime_lists) { | |
565 for (auto& anime : list) { | |
566 total += anime.progress; | |
567 } | |
568 } | |
569 return total; | |
570 } | |
571 | |
572 /* Returns the total watched amount in minutes. */ | |
573 int AnimeListPage::GetTotalWatchedAmount() { | |
574 int total = 0; | |
575 for (auto& list : anime_lists) { | |
576 for (auto& anime : list) { | |
577 total += anime.duration*anime.progress; | |
578 } | |
579 } | |
580 return total; | |
581 } | |
582 | |
583 /* Returns the total planned amount in minutes. | |
584 Note that we should probably limit progress to the | |
585 amount of episodes, as AniList will let you | |
586 set episode counts up to 32768. But that should | |
587 rather be handled elsewhere. */ | |
588 int AnimeListPage::GetTotalPlannedAmount() { | |
589 int total = 0; | |
590 for (auto& list : anime_lists) { | |
591 for (auto& anime : list) { | |
592 total += anime.duration*(anime.episodes-anime.progress); | |
593 } | |
594 } | |
595 return total; | |
596 } | |
597 | |
598 double AnimeListPage::GetAverageScore() { | |
599 double avg = 0; | |
600 int amt = 0; | |
601 for (auto& list : anime_lists) { | |
602 for (auto& anime : list) { | |
603 avg += anime.score; | |
604 if (anime.score != 0) | |
605 amt++; | |
606 } | |
607 } | |
608 return avg/amt; | |
609 } | |
610 | |
611 double AnimeListPage::GetScoreDeviation() { | |
612 double squares_sum = 0, avg = GetAverageScore(); | |
613 int amt = 0; | |
614 for (auto& list : anime_lists) { | |
615 for (auto& anime : list) { | |
616 if (anime.score != 0) { | |
617 squares_sum += std::pow((double)anime.score - avg, 2); | |
618 amt++; | |
619 } | |
620 } | |
621 } | |
622 return (amt > 0) ? std::sqrt(squares_sum / amt) : 0; | |
623 } | |
624 | |
625 #include "moc_anime.cpp" |