Mercurial > minori
comparison src/gui/pages/torrents.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 | dd211ff68b36 |
comparison
equal
deleted
inserted
replaced
| 257:699a20c57dc8 | 258:862d0d8619f6 |
|---|---|
| 1 #include "gui/pages/torrents.h" | 1 #include "gui/pages/torrents.h" |
| 2 #include "core/strings.h" | 2 #include "core/filesystem.h" |
| 3 #include "core/http.h" | 3 #include "core/http.h" |
| 4 #include "core/session.h" | 4 #include "core/session.h" |
| 5 #include "core/filesystem.h" | 5 #include "core/strings.h" |
| 6 #include "gui/widgets/text.h" | 6 #include "gui/widgets/text.h" |
| 7 #include "track/media.h" | 7 #include "track/media.h" |
| 8 | 8 |
| 9 #include <QByteArray> | |
| 10 #include <QDataStream> | |
| 11 #include <QDebug> | |
| 9 #include <QHeaderView> | 12 #include <QHeaderView> |
| 10 #include <QVBoxLayout> | 13 #include <QThread> |
| 11 #include <QToolBar> | 14 #include <QToolBar> |
| 12 #include <QTreeView> | 15 #include <QTreeView> |
| 13 #include <QByteArray> | 16 #include <QVBoxLayout> |
| 14 #include <QDataStream> | 17 |
| 15 #include <QThread> | 18 #include <algorithm> |
| 16 #include <QDebug> | 19 #include <fstream> |
| 17 | |
| 18 #include <iostream> | 20 #include <iostream> |
| 19 #include <sstream> | 21 #include <sstream> |
| 20 #include <fstream> | 22 |
| 21 #include <algorithm> | 23 #include "anitomy/anitomy.h" |
| 22 | |
| 23 #include "pugixml.hpp" | 24 #include "pugixml.hpp" |
| 24 #include "anitomy/anitomy.h" | |
| 25 | 25 |
| 26 /* This file is very, very similar to the anime list page. | 26 /* This file is very, very similar to the anime list page. |
| 27 * | 27 * |
| 28 * It differs from Taiga in that it uses tabs instead of | 28 * It differs from Taiga in that it uses tabs instead of |
| 29 * those "groups", but those are custom painted and a pain in the ass to | 29 * those "groups", but those are custom painted and a pain in the ass to |
| 30 * maintain over multiple platforms. | 30 * maintain over multiple platforms. |
| 31 */ | 31 */ |
| 32 | 32 |
| 33 TorrentsPageListSortFilter::TorrentsPageListSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { | 33 TorrentsPageListSortFilter::TorrentsPageListSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { |
| 34 } | 34 } |
| 35 | 35 |
| 36 bool TorrentsPageListSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { | 36 bool TorrentsPageListSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { |
| 84 return HTTP::Get(session.config.torrents.feed_link); | 84 return HTTP::Get(session.config.torrents.feed_link); |
| 85 } | 85 } |
| 86 | 86 |
| 87 void TorrentsPageListModel::ParseFeedDescription(const std::string& description, Torrent& torrent) { | 87 void TorrentsPageListModel::ParseFeedDescription(const std::string& description, Torrent& torrent) { |
| 88 /* Parse description... */ | 88 /* Parse description... */ |
| 89 enum class Keys { SIZE, AUTHORIZED, SUBMITTER, COMMENT }; | 89 enum class Keys { |
| 90 SIZE, | |
| 91 AUTHORIZED, | |
| 92 SUBMITTER, | |
| 93 COMMENT | |
| 94 }; | |
| 90 | 95 |
| 91 const std::unordered_map<std::string, Keys> KeyMap = { | 96 const std::unordered_map<std::string, Keys> KeyMap = { |
| 92 {"Size", Keys::SIZE}, | 97 {"Size", Keys::SIZE }, |
| 93 {"Authorized", Keys::AUTHORIZED}, | 98 {"Authorized", Keys::AUTHORIZED}, |
| 94 {"Submitter", Keys::SUBMITTER}, | 99 {"Submitter", Keys::SUBMITTER }, |
| 95 {"Comment", Keys::COMMENT} | 100 {"Comment", Keys::COMMENT } |
| 96 }; | 101 }; |
| 97 | 102 |
| 98 /* Parse size from description */ | 103 /* Parse size from description */ |
| 99 std::istringstream descstream(description); | 104 std::istringstream descstream(description); |
| 100 | 105 |
| 101 for (std::string line; std::getline(descstream, line);) { | 106 for (std::string line; std::getline(descstream, line);) { |
| 105 | 110 |
| 106 const std::string key = line.substr(0, pos); | 111 const std::string key = line.substr(0, pos); |
| 107 const std::string value = line.substr(line.find_first_not_of(": ", pos)); | 112 const std::string value = line.substr(line.find_first_not_of(": ", pos)); |
| 108 | 113 |
| 109 switch (KeyMap.at(key)) { | 114 switch (KeyMap.at(key)) { |
| 110 case Keys::COMMENT: | 115 case Keys::COMMENT: torrent.SetDescription(value); break; |
| 111 torrent.SetDescription(value); | 116 case Keys::SIZE: torrent.SetSize(Strings::HumanReadableSizeToBytes(value)); break; |
| 112 break; | |
| 113 case Keys::SIZE: | |
| 114 torrent.SetSize(Strings::HumanReadableSizeToBytes(value)); | |
| 115 break; | |
| 116 case Keys::AUTHORIZED: | 117 case Keys::AUTHORIZED: |
| 117 if (torrent.GetGroup().empty() && value != "N/A") | 118 if (torrent.GetGroup().empty() && value != "N/A") |
| 118 torrent.SetGroup(value); | 119 torrent.SetGroup(value); |
| 119 break; | 120 break; |
| 120 default: | 121 default: break; |
| 121 break; | |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| 126 void TorrentsPageListModel::ParseTorrentList(const QByteArray& ba) { | 126 void TorrentsPageListModel::ParseTorrentList(const QByteArray& ba) { |
| 149 | 149 |
| 150 const auto& elements = anitomy.elements(); | 150 const auto& elements = anitomy.elements(); |
| 151 | 151 |
| 152 /* todo: patch Anitomy so that it doesn't use wide strings */ | 152 /* todo: patch Anitomy so that it doesn't use wide strings */ |
| 153 torrent.SetTitle(Strings::ToUtf8String(elements.get(anitomy::kElementAnimeTitle))); | 153 torrent.SetTitle(Strings::ToUtf8String(elements.get(anitomy::kElementAnimeTitle))); |
| 154 torrent.SetEpisode(Strings::RemoveLeadingChars(Strings::ToUtf8String(elements.get(anitomy::kElementEpisodeNumber)), '0')); | 154 torrent.SetEpisode( |
| 155 Strings::RemoveLeadingChars(Strings::ToUtf8String(elements.get(anitomy::kElementEpisodeNumber)), '0')); | |
| 155 torrent.SetGroup(Strings::ToUtf8String(elements.get(anitomy::kElementReleaseGroup))); | 156 torrent.SetGroup(Strings::ToUtf8String(elements.get(anitomy::kElementReleaseGroup))); |
| 156 torrent.SetResolution(Strings::ToUtf8String(elements.get(anitomy::kElementVideoResolution))); | 157 torrent.SetResolution(Strings::ToUtf8String(elements.get(anitomy::kElementVideoResolution))); |
| 157 } | 158 } |
| 158 | 159 |
| 159 ParseFeedDescription(Strings::TextifySynopsis(item.child_value("description")), torrent); | 160 ParseFeedDescription(Strings::TextifySynopsis(item.child_value("description")), torrent); |
| 227 bool TorrentsPageListModel::setData(const QModelIndex& index, const QVariant& value, int role) { | 228 bool TorrentsPageListModel::setData(const QModelIndex& index, const QVariant& value, int role) { |
| 228 TorrentModelItem& item = list.at(index.row()); | 229 TorrentModelItem& item = list.at(index.row()); |
| 229 | 230 |
| 230 if (index.column() == 0) { | 231 if (index.column() == 0) { |
| 231 switch (role) { | 232 switch (role) { |
| 232 case Qt::EditRole: | 233 case Qt::EditRole: return false; |
| 233 return false; | |
| 234 case Qt::CheckStateRole: | 234 case Qt::CheckStateRole: |
| 235 item.SetChecked(value.toBool()); | 235 item.SetChecked(value.toBool()); |
| 236 emit dataChanged(index, index); | 236 emit dataChanged(index, index); |
| 237 return true; | 237 return true; |
| 238 } | 238 } |
| 267 case Qt::UserRole: | 267 case Qt::UserRole: |
| 268 switch (index.column()) { | 268 switch (index.column()) { |
| 269 case TL_EPISODE: return Strings::ToInt(item.GetEpisode(), -1); | 269 case TL_EPISODE: return Strings::ToInt(item.GetEpisode(), -1); |
| 270 /* We have to use this to work around some stupid | 270 /* We have to use this to work around some stupid |
| 271 * "conversion ambiguous" error on Linux | 271 * "conversion ambiguous" error on Linux |
| 272 */ | 272 */ |
| 273 case TL_SIZE: return QVariant::fromValue(item.GetSize()); | 273 case TL_SIZE: return QVariant::fromValue(item.GetSize()); |
| 274 default: return data(index, Qt::DisplayRole); | 274 default: return data(index, Qt::DisplayRole); |
| 275 } | 275 } |
| 276 break; | 276 break; |
| 277 case Qt::SizeHintRole: { | 277 case Qt::SizeHintRole: { |
| 329 toolbar->setMovable(false); | 329 toolbar->setMovable(false); |
| 330 | 330 |
| 331 { | 331 { |
| 332 /* this needs to be stored somewhere to replicate Taiga's | 332 /* this needs to be stored somewhere to replicate Taiga's |
| 333 "timer" feature */ | 333 "timer" feature */ |
| 334 toolbar->addAction(QIcon(":/icons/16x16/arrow-circle-315.png"), tr("&Check new torrents"), [this] { | 334 toolbar->addAction(QIcon(":/icons/16x16/arrow-circle-315.png"), tr("&Check new torrents"), |
| 335 Refresh(); | 335 [this] { Refresh(); }); |
| 336 }); | |
| 337 } | 336 } |
| 338 | 337 |
| 339 toolbar->addSeparator(); | 338 toolbar->addSeparator(); |
| 340 | 339 |
| 341 { | 340 { |
| 342 toolbar->addAction(QIcon(":/icons/16x16/navigation-270-button.png"), tr("Download &marked torrents"), [this] { | 341 toolbar->addAction(QIcon(":/icons/16x16/navigation-270-button.png"), tr("Download &marked torrents"), |
| 343 DownloadSelection(); | 342 [this] { DownloadSelection(); }); |
| 344 }); | 343 } |
| 345 } | 344 |
| 346 | 345 { toolbar->addAction(QIcon(":/icons/16x16/cross-button.png"), tr("&Discard all")); } |
| 347 { | |
| 348 toolbar->addAction(QIcon(":/icons/16x16/cross-button.png"), tr("&Discard all")); | |
| 349 } | |
| 350 | 346 |
| 351 toolbar->addSeparator(); | 347 toolbar->addSeparator(); |
| 352 | 348 |
| 353 { | 349 { toolbar->addAction(QIcon(":/icons/16x16/gear.png"), tr("&Settings")); } |
| 354 toolbar->addAction(QIcon(":/icons/16x16/gear.png"), tr("&Settings")); | |
| 355 } | |
| 356 | 350 |
| 357 layout->addWidget(toolbar); | 351 layout->addWidget(toolbar); |
| 358 } | 352 } |
| 359 | 353 |
| 360 { | 354 { |
| 385 sort_model->setSortCaseSensitivity(Qt::CaseInsensitive); | 379 sort_model->setSortCaseSensitivity(Qt::CaseInsensitive); |
| 386 treeview->setModel(sort_model); | 380 treeview->setModel(sort_model); |
| 387 } | 381 } |
| 388 | 382 |
| 389 // set column sizes | 383 // set column sizes |
| 390 treeview->setColumnWidth(TorrentsPageListModel::TL_TITLE, 240); | 384 treeview->setColumnWidth(TorrentsPageListModel::TL_TITLE, 240); |
| 391 treeview->setColumnWidth(TorrentsPageListModel::TL_EPISODE, 60); | 385 treeview->setColumnWidth(TorrentsPageListModel::TL_EPISODE, 60); |
| 392 treeview->setColumnWidth(TorrentsPageListModel::TL_GROUP, 100); | 386 treeview->setColumnWidth(TorrentsPageListModel::TL_GROUP, 100); |
| 393 treeview->setColumnWidth(TorrentsPageListModel::TL_SIZE, 70); | 387 treeview->setColumnWidth(TorrentsPageListModel::TL_SIZE, 70); |
| 394 treeview->setColumnWidth(TorrentsPageListModel::TL_RESOLUTION, 100); | 388 treeview->setColumnWidth(TorrentsPageListModel::TL_RESOLUTION, 100); |
| 395 treeview->setColumnWidth(TorrentsPageListModel::TL_SEEDERS, 20); | 389 treeview->setColumnWidth(TorrentsPageListModel::TL_SEEDERS, 20); |
| 396 treeview->setColumnWidth(TorrentsPageListModel::TL_LEECHERS, 20); | 390 treeview->setColumnWidth(TorrentsPageListModel::TL_LEECHERS, 20); |
| 397 treeview->setColumnWidth(TorrentsPageListModel::TL_DOWNLOADS, 20); | 391 treeview->setColumnWidth(TorrentsPageListModel::TL_DOWNLOADS, 20); |
| 398 treeview->setColumnWidth(TorrentsPageListModel::TL_DESCRIPTION, 200); | 392 treeview->setColumnWidth(TorrentsPageListModel::TL_DESCRIPTION, 200); |
| 399 treeview->setColumnWidth(TorrentsPageListModel::TL_FILENAME, 200); | 393 treeview->setColumnWidth(TorrentsPageListModel::TL_FILENAME, 200); |
| 400 treeview->setColumnWidth(TorrentsPageListModel::TL_RELEASEDATE, 190); | 394 treeview->setColumnWidth(TorrentsPageListModel::TL_RELEASEDATE, 190); |
| 401 | 395 |
| 402 treeview->header()->setStretchLastSection(false); | 396 treeview->header()->setStretchLastSection(false); |
| 403 | 397 |
| 404 layout->addWidget(treeview); | 398 layout->addWidget(treeview); |
| 421 HTTP::GetThread* thread = new HTTP::GetThread(session.config.torrents.feed_link); | 415 HTTP::GetThread* thread = new HTTP::GetThread(session.config.torrents.feed_link); |
| 422 | 416 |
| 423 connect(thread, &HTTP::GetThread::ReceivedData, this, [&](const QByteArray& ba) { | 417 connect(thread, &HTTP::GetThread::ReceivedData, this, [&](const QByteArray& ba) { |
| 424 /* This is to make sure we aren't in a different thread | 418 /* This is to make sure we aren't in a different thread |
| 425 * messing around with GUI stuff | 419 * messing around with GUI stuff |
| 426 */ | 420 */ |
| 427 treeview->setUpdatesEnabled(false); | 421 treeview->setUpdatesEnabled(false); |
| 428 model->ParseTorrentList(ba); | 422 model->ParseTorrentList(ba); |
| 429 treeview->setUpdatesEnabled(true); | 423 treeview->setUpdatesEnabled(true); |
| 430 }); | 424 }); |
| 431 connect(thread, &QThread::finished, thread, &QThread::deleteLater); | 425 connect(thread, &QThread::finished, thread, &QThread::deleteLater); |
