Mercurial > minori
comparison src/gui/pages/search.cc @ 258:862d0d8619f6
*: HUUUGE changes
animia has been renamed to animone, so instead of thinking of a
health condition, you think of a beautiful flower :)
I've also edited some of the code for animone, but I have no idea
if it even works or not because I don't have a mac or windows
machine lying around. whoops!
... anyway, all of the changes divergent from Anisthesia are now
licensed under BSD. it's possible that I could even rewrite most
of the code to where I don't even have to keep the MIT license,
but that's thinking too far into the future
I've been slacking off on implementing the anime seasons page,
mostly out of laziness. I think I'd have to create another db file
specifically for the seasons
anyway, this code is being pushed *primarily* because the hard drive
it's on is failing! yay :)
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Mon, 01 Apr 2024 02:43:44 -0400 |
| parents | c130f47f6f48 |
| children | f31305b9f60a |
comparison
equal
deleted
inserted
replaced
| 257:699a20c57dc8 | 258:862d0d8619f6 |
|---|---|
| 1 #include "gui/pages/search.h" | 1 #include "gui/pages/search.h" |
| 2 #include "core/anime.h" | 2 #include "core/anime.h" |
| 3 #include "core/anime_db.h" | 3 #include "core/anime_db.h" |
| 4 #include "core/strings.h" | 4 #include "core/filesystem.h" |
| 5 #include "core/http.h" | 5 #include "core/http.h" |
| 6 #include "core/session.h" | 6 #include "core/session.h" |
| 7 #include "core/filesystem.h" | 7 #include "core/strings.h" |
| 8 #include "gui/dialog/information.h" | |
| 9 #include "gui/translate/anime.h" | |
| 8 #include "gui/widgets/text.h" | 10 #include "gui/widgets/text.h" |
| 9 #include "gui/dialog/information.h" | 11 #include "services/services.h" |
| 10 #include "track/media.h" | 12 #include "track/media.h" |
| 11 #include "gui/translate/anime.h" | 13 |
| 12 #include "services/services.h" | 14 #include <QDate> |
| 13 | |
| 14 #include <QHeaderView> | 15 #include <QHeaderView> |
| 15 #include <QVBoxLayout> | 16 #include <QMenu> |
| 16 #include <QToolBar> | 17 #include <QToolBar> |
| 17 #include <QTreeView> | 18 #include <QTreeView> |
| 18 #include <QDate> | 19 #include <QVBoxLayout> |
| 19 #include <QMenu> | 20 |
| 20 | 21 #include <algorithm> |
| 22 #include <fstream> | |
| 21 #include <iostream> | 23 #include <iostream> |
| 22 #include <sstream> | 24 #include <sstream> |
| 23 #include <fstream> | 25 |
| 24 #include <algorithm> | 26 #include "anitomy/anitomy.h" |
| 25 | |
| 26 #include "pugixml.hpp" | 27 #include "pugixml.hpp" |
| 27 #include "anitomy/anitomy.h" | |
| 28 | 28 |
| 29 SearchPageListSortFilter::SearchPageListSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { | 29 SearchPageListSortFilter::SearchPageListSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { |
| 30 } | 30 } |
| 31 | 31 |
| 32 bool SearchPageListSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { | 32 bool SearchPageListSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { |
| 35 | 35 |
| 36 switch (left.userType()) { | 36 switch (left.userType()) { |
| 37 case QMetaType::Int: | 37 case QMetaType::Int: |
| 38 case QMetaType::UInt: | 38 case QMetaType::UInt: |
| 39 case QMetaType::LongLong: | 39 case QMetaType::LongLong: |
| 40 case QMetaType::ULongLong: | 40 case QMetaType::ULongLong: return left.toInt() < right.toInt(); |
| 41 return left.toInt() < right.toInt(); | 41 case QMetaType::QDate: return left.toDate() < right.toDate(); |
| 42 case QMetaType::QDate: | |
| 43 return left.toDate() < right.toDate(); | |
| 44 case QMetaType::QString: | 42 case QMetaType::QString: |
| 45 default: // meh | 43 default: // meh |
| 46 return QString::compare(left.toString(), right.toString(), Qt::CaseInsensitive) < 0; | 44 return QString::compare(left.toString(), right.toString(), Qt::CaseInsensitive) < 0; |
| 47 } | 45 } |
| 48 } | 46 } |
| 115 switch (index.column()) { | 113 switch (index.column()) { |
| 116 case SR_TITLE: return Strings::ToQString(anime.GetUserPreferredTitle()); | 114 case SR_TITLE: return Strings::ToQString(anime.GetUserPreferredTitle()); |
| 117 case SR_TYPE: return Strings::ToQString(Translate::ToLocalString(anime.GetFormat())); | 115 case SR_TYPE: return Strings::ToQString(Translate::ToLocalString(anime.GetFormat())); |
| 118 case SR_EPISODES: return anime.GetEpisodes(); | 116 case SR_EPISODES: return anime.GetEpisodes(); |
| 119 case SR_SCORE: return QString::number(anime.GetAudienceScore()) + "%"; | 117 case SR_SCORE: return QString::number(anime.GetAudienceScore()) + "%"; |
| 120 case SR_SEASON: return Strings::ToQString(Translate::ToLocalString(anime.GetSeason())) + " " + QString::number(anime.GetAirDate().GetYear().value_or(2000)); | 118 case SR_SEASON: |
| 119 return Strings::ToQString(Translate::ToLocalString(anime.GetSeason())) + " " + | |
| 120 QString::number(anime.GetAirDate().GetYear().value_or(2000)); | |
| 121 default: return {}; | 121 default: return {}; |
| 122 } | 122 } |
| 123 break; | 123 break; |
| 124 case Qt::UserRole: | 124 case Qt::UserRole: |
| 125 switch (index.column()) { | 125 switch (index.column()) { |
| 126 case SR_SCORE: return anime.GetAudienceScore(); | 126 case SR_SCORE: return anime.GetAudienceScore(); |
| 127 case SR_EPISODES: return anime.GetEpisodes(); | 127 case SR_EPISODES: return anime.GetEpisodes(); |
| 128 case SR_SEASON: return anime.GetAirDate().GetAsQDate(); | 128 case SR_SEASON: return anime.GetAirDate().GetAsQDate(); |
| 129 /* We have to use this to work around some stupid | 129 /* We have to use this to work around some stupid |
| 130 * "conversion ambiguous" error on Linux | 130 * "conversion ambiguous" error on Linux |
| 131 */ | 131 */ |
| 132 default: return data(index, Qt::DisplayRole); | 132 default: return data(index, Qt::DisplayRole); |
| 133 } | 133 } |
| 134 break; | 134 break; |
| 135 case Qt::SizeHintRole: { | 135 case Qt::SizeHintRole: { |
| 136 switch (index.column()) { | 136 switch (index.column()) { |
| 142 return QSize(std::max(metric.horizontalAdvance(d), 100), metric.height()); | 142 return QSize(std::max(metric.horizontalAdvance(d), 100), metric.height()); |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 break; | 145 break; |
| 146 } | 146 } |
| 147 case Qt::TextAlignmentRole: | 147 case Qt::TextAlignmentRole: return headerData(index.column(), Qt::Horizontal, Qt::TextAlignmentRole); |
| 148 return headerData(index.column(), Qt::Horizontal, Qt::TextAlignmentRole); | |
| 149 } | 148 } |
| 150 return QVariant(); | 149 return QVariant(); |
| 151 } | 150 } |
| 152 | 151 |
| 153 Qt::ItemFlags SearchPageListModel::flags(const QModelIndex& index) const { | 152 Qt::ItemFlags SearchPageListModel::flags(const QModelIndex& index) const { |
| 183 } | 182 } |
| 184 } | 183 } |
| 185 | 184 |
| 186 menu->addAction(tr("Information"), [this, animes] { | 185 menu->addAction(tr("Information"), [this, animes] { |
| 187 for (auto& anime : animes) { | 186 for (auto& anime : animes) { |
| 188 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] { | 187 InformationDialog* dialog = new InformationDialog( |
| 189 //UpdateAnime(anime->GetId()); | 188 *anime, |
| 190 }, InformationDialog::PAGE_MAIN_INFO, this); | 189 [this, anime] { |
| 190 // UpdateAnime(anime->GetId()); | |
| 191 }, | |
| 192 InformationDialog::PAGE_MAIN_INFO, this); | |
| 191 | 193 |
| 192 dialog->show(); | 194 dialog->show(); |
| 193 dialog->raise(); | 195 dialog->raise(); |
| 194 dialog->activateWindow(); | 196 dialog->activateWindow(); |
| 195 } | 197 } |
| 196 }); | 198 }); |
| 197 menu->addSeparator(); | 199 menu->addSeparator(); |
| 198 { | 200 { |
| 199 QMenu* submenu = menu->addMenu(tr("Add to list...")); | 201 QMenu* submenu = menu->addMenu(tr("Add to list...")); |
| 200 submenu->addAction(tr("Currently watching"), [animes]{ | 202 submenu->addAction(tr("Currently watching"), [animes] { |
| 201 for (auto& anime : animes) { | 203 for (auto& anime : animes) { |
| 202 if (!anime->IsInUserList()) | 204 if (!anime->IsInUserList()) |
| 203 anime->AddToUserList(); | 205 anime->AddToUserList(); |
| 204 anime->SetUserStatus(Anime::ListStatus::CURRENT); | 206 anime->SetUserStatus(Anime::ListStatus::CURRENT); |
| 205 Services::UpdateAnimeEntry(anime->GetId()); | 207 Services::UpdateAnimeEntry(anime->GetId()); |
| 206 } | 208 } |
| 207 }); | 209 }); |
| 208 submenu->addAction(tr("Completed"), [animes]{ | 210 submenu->addAction(tr("Completed"), [animes] { |
| 209 for (auto& anime : animes) { | 211 for (auto& anime : animes) { |
| 210 if (!anime->IsInUserList()) | 212 if (!anime->IsInUserList()) |
| 211 anime->AddToUserList(); | 213 anime->AddToUserList(); |
| 212 anime->SetUserStatus(Anime::ListStatus::COMPLETED); | 214 anime->SetUserStatus(Anime::ListStatus::COMPLETED); |
| 213 Services::UpdateAnimeEntry(anime->GetId()); | 215 Services::UpdateAnimeEntry(anime->GetId()); |
| 214 } | 216 } |
| 215 }); | 217 }); |
| 216 submenu->addAction(tr("On hold"), [animes]{ | 218 submenu->addAction(tr("On hold"), [animes] { |
| 217 for (auto& anime : animes) { | 219 for (auto& anime : animes) { |
| 218 if (!anime->IsInUserList()) | 220 if (!anime->IsInUserList()) |
| 219 anime->AddToUserList(); | 221 anime->AddToUserList(); |
| 220 anime->SetUserStatus(Anime::ListStatus::PAUSED); | 222 anime->SetUserStatus(Anime::ListStatus::PAUSED); |
| 221 Services::UpdateAnimeEntry(anime->GetId()); | 223 Services::UpdateAnimeEntry(anime->GetId()); |
| 222 } | 224 } |
| 223 }); | 225 }); |
| 224 submenu->addAction(tr("Dropped"), [animes]{ | 226 submenu->addAction(tr("Dropped"), [animes] { |
| 225 for (auto& anime : animes) { | 227 for (auto& anime : animes) { |
| 226 if (!anime->IsInUserList()) | 228 if (!anime->IsInUserList()) |
| 227 anime->AddToUserList(); | 229 anime->AddToUserList(); |
| 228 anime->SetUserStatus(Anime::ListStatus::DROPPED); | 230 anime->SetUserStatus(Anime::ListStatus::DROPPED); |
| 229 Services::UpdateAnimeEntry(anime->GetId()); | 231 Services::UpdateAnimeEntry(anime->GetId()); |
| 230 } | 232 } |
| 231 }); | 233 }); |
| 232 submenu->addAction(tr("Plan to watch"), [animes]{ | 234 submenu->addAction(tr("Plan to watch"), [animes] { |
| 233 for (auto& anime : animes) { | 235 for (auto& anime : animes) { |
| 234 if (!anime->IsInUserList()) | 236 if (!anime->IsInUserList()) |
| 235 anime->AddToUserList(); | 237 anime->AddToUserList(); |
| 236 anime->SetUserStatus(Anime::ListStatus::PLANNING); | 238 anime->SetUserStatus(Anime::ListStatus::PLANNING); |
| 237 Services::UpdateAnimeEntry(anime->GetId()); | 239 Services::UpdateAnimeEntry(anime->GetId()); |
| 249 return; | 251 return; |
| 250 | 252 |
| 251 const QModelIndex index = model->index(selection.indexes().first().row()); | 253 const QModelIndex index = model->index(selection.indexes().first().row()); |
| 252 Anime::Anime* anime = model->GetAnimeFromIndex(index); | 254 Anime::Anime* anime = model->GetAnimeFromIndex(index); |
| 253 | 255 |
| 254 InformationDialog* dialog = new InformationDialog(*anime, [this, anime] { | 256 InformationDialog* dialog = new InformationDialog( |
| 255 //UpdateAnime(anime->GetId()); | 257 *anime, |
| 256 }, InformationDialog::PAGE_MAIN_INFO, this); | 258 [this, anime] { |
| 259 // UpdateAnime(anime->GetId()); | |
| 260 }, | |
| 261 InformationDialog::PAGE_MAIN_INFO, this); | |
| 257 | 262 |
| 258 dialog->show(); | 263 dialog->show(); |
| 259 dialog->raise(); | 264 dialog->raise(); |
| 260 dialog->activateWindow(); | 265 dialog->activateWindow(); |
| 261 } | 266 } |
| 273 QToolBar* toolbar = new QToolBar(this); | 278 QToolBar* toolbar = new QToolBar(this); |
| 274 toolbar->setMovable(false); | 279 toolbar->setMovable(false); |
| 275 | 280 |
| 276 { | 281 { |
| 277 QLineEdit* line_edit = new QLineEdit("", toolbar); | 282 QLineEdit* line_edit = new QLineEdit("", toolbar); |
| 278 connect(line_edit, &QLineEdit::returnPressed, this, [this, line_edit]{ | 283 connect(line_edit, &QLineEdit::returnPressed, this, [this, line_edit] { |
| 279 /* static thread here. */ | 284 /* static thread here. */ |
| 280 static QThread* thread = nullptr; | 285 static QThread* thread = nullptr; |
| 281 | 286 |
| 282 if (thread) | 287 if (thread) |
| 283 return; | 288 return; |
| 284 | 289 |
| 285 thread = QThread::create([this, line_edit]{ | 290 thread = QThread::create([this, line_edit] { |
| 286 model->ParseSearch(Services::Search(Strings::ToUtf8String(line_edit->text()))); | 291 model->ParseSearch(Services::Search(Strings::ToUtf8String(line_edit->text()))); |
| 287 }); | 292 }); |
| 288 | 293 |
| 289 connect(thread, &QThread::finished, this, []{ | 294 connect(thread, &QThread::finished, this, [] { |
| 290 thread->deleteLater(); | 295 thread->deleteLater(); |
| 291 thread = nullptr; | 296 thread = nullptr; |
| 292 }); | 297 }); |
| 293 | 298 |
| 294 thread->start(); | 299 thread->start(); |
| 327 sort_model->setSortCaseSensitivity(Qt::CaseInsensitive); | 332 sort_model->setSortCaseSensitivity(Qt::CaseInsensitive); |
| 328 treeview->setModel(sort_model); | 333 treeview->setModel(sort_model); |
| 329 } | 334 } |
| 330 | 335 |
| 331 // set column sizes | 336 // set column sizes |
| 332 treeview->setColumnWidth(SearchPageListModel::SR_TITLE, 400); | 337 treeview->setColumnWidth(SearchPageListModel::SR_TITLE, 400); |
| 333 treeview->setColumnWidth(SearchPageListModel::SR_TYPE, 60); | 338 treeview->setColumnWidth(SearchPageListModel::SR_TYPE, 60); |
| 334 treeview->setColumnWidth(SearchPageListModel::SR_EPISODES, 60); | 339 treeview->setColumnWidth(SearchPageListModel::SR_EPISODES, 60); |
| 335 treeview->setColumnWidth(SearchPageListModel::SR_SCORE, 60); | 340 treeview->setColumnWidth(SearchPageListModel::SR_SCORE, 60); |
| 336 treeview->setColumnWidth(SearchPageListModel::SR_SEASON, 100); | 341 treeview->setColumnWidth(SearchPageListModel::SR_SEASON, 100); |
| 337 | 342 |
| 338 treeview->header()->setStretchLastSection(false); | 343 treeview->header()->setStretchLastSection(false); |
| 339 | 344 |
| 340 /* Double click stuff */ | 345 /* Double click stuff */ |
| 341 connect(treeview, &QAbstractItemView::doubleClicked, this, &SearchPage::ItemDoubleClicked); | 346 connect(treeview, &QAbstractItemView::doubleClicked, this, &SearchPage::ItemDoubleClicked); |
