comparison src/gui/pages/torrents.cc @ 230:2f5a9247e501

torrents: implement download button erg
author Paper <paper@paper.us.eu.org>
date Sat, 13 Jan 2024 09:42:02 -0500
parents 53211cb1e7f5
children 4d461ef7d424
comparison
equal deleted inserted replaced
229:adc20fa321c1 230:2f5a9247e501
1 #include "gui/pages/torrents.h" 1 #include "gui/pages/torrents.h"
2 #include "core/strings.h" 2 #include "core/strings.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 "gui/widgets/text.h" 6 #include "gui/widgets/text.h"
6 #include "track/media.h" 7 #include "track/media.h"
7 8
8 #include <QVBoxLayout> 9 #include <QVBoxLayout>
9 #include <QToolBar> 10 #include <QToolBar>
10 #include <QTreeView> 11 #include <QTreeView>
11 #include <QMainWindow> 12 #include <QMainWindow>
12 #include <QByteArray> 13 #include <QByteArray>
13 #include <QDataStream> 14 #include <QDataStream>
14 #include <QThreadPool> 15 #include <QThread>
15 #include <QDebug> 16 #include <QDebug>
16 17
17 #include <iostream> 18 #include <iostream>
18 #include <sstream> 19 #include <sstream>
20 #include <fstream>
19 #include <algorithm> 21 #include <algorithm>
20 22
21 #include "pugixml.hpp" 23 #include "pugixml.hpp"
22 #include "anitomy/anitomy.h" 24 #include "anitomy/anitomy.h"
23 25
46 } 48 }
47 49
48 /* -------------------------------------------- */ 50 /* -------------------------------------------- */
49 51
50 TorrentsPageListModel::TorrentsPageListModel(QObject* parent) : QAbstractListModel(parent) { 52 TorrentsPageListModel::TorrentsPageListModel(QObject* parent) : QAbstractListModel(parent) {
53 }
54
55 void TorrentsPageListModel::DownloadTorrents(QItemSelection selection) {
56 const auto indexes = selection.indexes();
57
58 for (const auto& index : indexes) {
59 /* a torrent file IS literally text... */
60 const std::string link = list.at(index.row()).GetLink();
61 const std::string filename = list.at(index.row()).GetFilename() + ".torrent";
62
63 const std::filesystem::path torrents_dir = Filesystem::GetTorrentsPath();
64 std::filesystem::create_directories(torrents_dir);
65
66 std::ofstream file(torrents_dir / filename, std::ofstream::out | std::ofstream::trunc);
67 if (!file)
68 return; // wat
69
70 const QByteArray data = HTTP::Get(link);
71 file.write(data.data(), data.size());
72
73 file.close();
74 }
51 } 75 }
52 76
53 QByteArray TorrentsPageListModel::DownloadTorrentList() { 77 QByteArray TorrentsPageListModel::DownloadTorrentList() {
54 return HTTP::Get(session.config.torrents.feed_link); 78 return HTTP::Get(session.config.torrents.feed_link);
55 } 79 }
229 case TL_LEECHERS: return item.GetLeechers(); 253 case TL_LEECHERS: return item.GetLeechers();
230 case TL_DOWNLOADERS: return item.GetDownloaders(); 254 case TL_DOWNLOADERS: return item.GetDownloaders();
231 case TL_DESCRIPTION: return Strings::ToQString(item.GetDescription()); 255 case TL_DESCRIPTION: return Strings::ToQString(item.GetDescription());
232 case TL_FILENAME: return Strings::ToQString(item.GetFilename()); 256 case TL_FILENAME: return Strings::ToQString(item.GetFilename());
233 case TL_RELEASEDATE: return item.GetDate(); 257 case TL_RELEASEDATE: return item.GetDate();
234 default: return ""; 258 default: return {};
235 } 259 }
236 break; 260 break;
237 case Qt::UserRole: 261 case Qt::UserRole:
238 switch (index.column()) { 262 switch (index.column()) {
239 case TL_EPISODE: return Strings::ToInt(item.GetEpisode(), -1); 263 case TL_EPISODE: return Strings::ToInt(item.GetEpisode(), -1);
240 /* We have to use this to work around some stupid 264 /* We have to use this to work around some stupid
241 "conversion ambiguous" error on Linux */ 265 * "conversion ambiguous" error on Linux
266 */
242 case TL_SIZE: return QVariant::fromValue(item.GetSize()); 267 case TL_SIZE: return QVariant::fromValue(item.GetSize());
243 default: return data(index, Qt::DisplayRole); 268 default: return data(index, Qt::DisplayRole);
244 } 269 }
245 break; 270 break;
246 case Qt::SizeHintRole: { 271 case Qt::SizeHintRole: {
298 toolbar->setMovable(false); 323 toolbar->setMovable(false);
299 324
300 { 325 {
301 /* this needs to be stored somewhere to replicate Taiga's 326 /* this needs to be stored somewhere to replicate Taiga's
302 "timer" feature */ 327 "timer" feature */
303 toolbar->addAction(QIcon(":/icons/16x16/arrow-circle-315.png"), tr("&Check new torrents"), [this]{ 328 toolbar->addAction(QIcon(":/icons/16x16/arrow-circle-315.png"), tr("&Check new torrents"), [this] {
304 QThreadPool::globalInstance()->start([this] { 329 Refresh();
305 Refresh();
306 });
307 }); 330 });
308 } 331 }
309 332
310 toolbar->addSeparator(); 333 toolbar->addSeparator();
311 334
312 { 335 {
313 toolbar->addAction(QIcon(":/icons/16x16/navigation-270-button.png"), tr("Download &marked torrents")); 336 toolbar->addAction(QIcon(":/icons/16x16/navigation-270-button.png"), tr("Download &marked torrents"), [this] {
337 DownloadSelection();
338 });
314 } 339 }
315 340
316 { 341 {
317 toolbar->addAction(QIcon(":/icons/16x16/cross-button.png"), tr("&Discard all")); 342 toolbar->addAction(QIcon(":/icons/16x16/cross-button.png"), tr("&Discard all"));
318 } 343 }
333 line->setLineWidth(1); 358 line->setLineWidth(1);
334 layout->addWidget(line); 359 layout->addWidget(line);
335 } 360 }
336 361
337 { 362 {
338 QTreeView* treeview = new QTreeView(this); 363 treeview = new QTreeView(this);
339 treeview->setUniformRowHeights(true); 364 treeview->setUniformRowHeights(true);
340 treeview->setAllColumnsShowFocus(false); 365 treeview->setAllColumnsShowFocus(false);
341 treeview->setAlternatingRowColors(true); 366 treeview->setAlternatingRowColors(true);
342 treeview->setSortingEnabled(true); 367 treeview->setSortingEnabled(true);
343 treeview->setSelectionMode(QAbstractItemView::ExtendedSelection); 368 treeview->setSelectionMode(QAbstractItemView::ExtendedSelection);
357 382
358 layout->addWidget(treeview); 383 layout->addWidget(treeview);
359 } 384 }
360 } 385 }
361 386
387 void TorrentsPage::DownloadSelection() {
388 /* we only want one of these at a time, because if we don't
389 * we have the possibility of going into Multithreading Hell
390 */
391 static QThread* thread = nullptr;
392
393 if (!model || thread)
394 return;
395
396 const QItemSelection selection = sort_model->mapSelectionToSource(treeview->selectionModel()->selection());
397
398 thread = QThread::create([this, selection] {
399 model->DownloadTorrents(selection);
400 });
401
402 connect(thread, &QThread::finished, thread, &QThread::deleteLater);
403 connect(thread, &QThread::finished, this, [&] { thread = nullptr; });
404
405 thread->start();
406 }
407
362 void TorrentsPage::Refresh() { 408 void TorrentsPage::Refresh() {
363 if (!model) 409 if (!model)
364 return; 410 return;
365 model->RefreshTorrentList(); 411
412 HTTP::GetThread* thread = new HTTP::GetThread(session.config.torrents.feed_link);
413
414 connect(thread, &HTTP::GetThread::ReceivedData, this, [&](const QByteArray& ba) {
415 /* This is to make sure we aren't in a different thread
416 * messing around with GUI stuff
417 */
418 treeview->setUpdatesEnabled(false);
419 model->ParseTorrentList(ba);
420 treeview->setUpdatesEnabled(true);
421 });
422 connect(thread, &QThread::finished, thread, &QThread::deleteLater);
423
424 thread->start();
366 } 425 }
367 426
368 #include "gui/pages/moc_torrents.cpp" 427 #include "gui/pages/moc_torrents.cpp"