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);