source: trunk/qt/Session.cc @ 14581

Last change on this file since 14581 was 14581, checked in by mikedld, 6 years ago

Remove unused session tag

  • Property svn:keywords set to Date Rev Author Id
File size: 27.0 KB
Line 
1/*
2 * This file Copyright (C) 2009-2015 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: Session.cc 14581 2015-10-18 18:39:14Z mikedld $
8 */
9
10#include <cassert>
11#include <iostream>
12
13#include <QApplication>
14#include <QByteArray>
15#include <QClipboard>
16#include <QCoreApplication>
17#include <QDebug>
18#include <QDesktopServices>
19#include <QFile>
20#include <QFileInfo>
21#include <QMessageBox>
22#include <QStyle>
23#include <QTextStream>
24
25#include <libtransmission/transmission.h>
26#include <libtransmission/utils.h> // tr_free
27#include <libtransmission/variant.h>
28
29#include "AddData.h"
30#include "Prefs.h"
31#include "Session.h"
32#include "SessionDialog.h"
33#include "Torrent.h"
34#include "Utils.h"
35
36namespace
37{
38  enum
39  {
40    TAG_SOME_TORRENTS,
41    TAG_ALL_TORRENTS,
42    TAG_SESSION_STATS,
43    TAG_SESSION_INFO,
44    TAG_BLOCKLIST_UPDATE,
45    TAG_ADD_TORRENT,
46    TAG_PORT_TEST,
47    TAG_MAGNET_LINK,
48    TAG_RENAME_PATH,
49
50    FIRST_UNIQUE_TAG
51  };
52}
53
54/***
55****
56***/
57
58namespace
59{
60  typedef Torrent::KeyList KeyList;
61  const KeyList& getInfoKeys () { return Torrent::getInfoKeys (); }
62  const KeyList& getStatKeys () { return Torrent::getStatKeys (); }
63  const KeyList& getExtraStatKeys () { return Torrent::getExtraStatKeys (); }
64
65  void
66  addList (tr_variant * list, const KeyList& keys)
67  {
68    tr_variantListReserve (list, keys.size ());
69    for (const tr_quark key: keys)
70      tr_variantListAddQuark (list, key);
71  }
72}
73
74/***
75****
76***/
77
78void
79FileAdded::executed (int64_t tag, const QString& result, tr_variant * arguments)
80{
81  if (tag != myTag)
82    return;
83
84  if (result == QLatin1String ("success"))
85    {
86      tr_variant * dup;
87      const char * str;
88      if (tr_variantDictFindDict (arguments, TR_KEY_torrent_duplicate, &dup) &&
89          tr_variantDictFindStr (dup, TR_KEY_name, &str, NULL))
90        {
91          const QString myFilename = QFileInfo (myName).fileName ();
92          const QString name = QString::fromUtf8 (str);
93          QMessageBox::warning (qApp->activeWindow (),
94                                tr ("Add Torrent"),
95                                tr ("<p><b>Unable to add \"%1\".</b></p><p>It is a duplicate of \"%2\" which is already added.</p>").arg (myFilename).arg (name));
96        }
97
98      if (!myDelFile.isEmpty ())
99        {
100          QFile file (myDelFile);
101          file.setPermissions (QFile::ReadOwner | QFile::WriteOwner);
102          file.remove ();
103        }
104    }
105  else
106    {
107      QString text = result;
108
109      for (int i=0, n=text.size (); i<n; ++i)
110        if (!i || text[i-1].isSpace ())
111          text[i] = text[i].toUpper ();
112
113      QMessageBox::warning (qApp->activeWindow (),
114                            tr ("Error Adding Torrent"),
115                            QString::fromLatin1 ("<p><b>%1</b></p><p>%2</p>").arg (text).arg (myName));
116    }
117
118  deleteLater ();
119}
120
121/***
122****
123***/
124
125void
126Session::sessionSet (const tr_quark key, const QVariant& value)
127{
128  tr_variant args;
129  tr_variantInitDict (&args, 1);
130  switch (value.type ())
131    {
132      case QVariant::Bool:   tr_variantDictAddBool (&args, key, value.toBool ()); break;
133      case QVariant::Int:    tr_variantDictAddInt (&args, key, value.toInt ()); break;
134      case QVariant::Double: tr_variantDictAddReal (&args, key, value.toDouble ()); break;
135      case QVariant::String: tr_variantDictAddStr (&args, key, value.toString ().toUtf8 ().constData ()); break;
136      default:               assert ("unknown type");
137    }
138
139  exec ("session-set", &args);
140}
141
142void
143Session::portTest ()
144{
145  exec ("port-test", nullptr, TAG_PORT_TEST);
146}
147
148void
149Session::copyMagnetLinkToClipboard (int torrentId)
150{
151  tr_variant args;
152  tr_variantInitDict (&args, 2);
153  tr_variantListAddInt (tr_variantDictAddList (&args, TR_KEY_ids, 1), torrentId);
154  tr_variantListAddStr (tr_variantDictAddList (&args, TR_KEY_fields, 1), "magnetLink");
155
156  exec (TR_KEY_torrent_get, &args, TAG_MAGNET_LINK);
157}
158
159void
160Session::updatePref (int key)
161{
162  if (myPrefs.isCore (key)) switch (key)
163    {
164      case Prefs::ALT_SPEED_LIMIT_DOWN:
165      case Prefs::ALT_SPEED_LIMIT_ENABLED:
166      case Prefs::ALT_SPEED_LIMIT_TIME_BEGIN:
167      case Prefs::ALT_SPEED_LIMIT_TIME_DAY:
168      case Prefs::ALT_SPEED_LIMIT_TIME_ENABLED:
169      case Prefs::ALT_SPEED_LIMIT_TIME_END:
170      case Prefs::ALT_SPEED_LIMIT_UP:
171      case Prefs::BLOCKLIST_DATE:
172      case Prefs::BLOCKLIST_ENABLED:
173      case Prefs::BLOCKLIST_URL:
174      case Prefs::DHT_ENABLED:
175      case Prefs::DOWNLOAD_QUEUE_ENABLED:
176      case Prefs::DOWNLOAD_QUEUE_SIZE:
177      case Prefs::DSPEED:
178      case Prefs::DSPEED_ENABLED:
179      case Prefs::IDLE_LIMIT:
180      case Prefs::IDLE_LIMIT_ENABLED:
181      case Prefs::INCOMPLETE_DIR:
182      case Prefs::INCOMPLETE_DIR_ENABLED:
183      case Prefs::LPD_ENABLED:
184      case Prefs::PEER_LIMIT_GLOBAL:
185      case Prefs::PEER_LIMIT_TORRENT:
186      case Prefs::PEER_PORT:
187      case Prefs::PEER_PORT_RANDOM_ON_START:
188      case Prefs::QUEUE_STALLED_MINUTES:
189      case Prefs::PEX_ENABLED:
190      case Prefs::PORT_FORWARDING:
191      case Prefs::RENAME_PARTIAL_FILES:
192      case Prefs::SCRIPT_TORRENT_DONE_ENABLED:
193      case Prefs::SCRIPT_TORRENT_DONE_FILENAME:
194      case Prefs::START:
195      case Prefs::TRASH_ORIGINAL:
196      case Prefs::USPEED:
197      case Prefs::USPEED_ENABLED:
198      case Prefs::UTP_ENABLED:
199        sessionSet (myPrefs.getKey (key), myPrefs.variant (key));
200        break;
201
202      case Prefs::DOWNLOAD_DIR:
203        sessionSet (myPrefs.getKey (key), myPrefs.variant (key));
204        /* this will change the 'freespace' argument, so refresh */
205        refreshSessionInfo ();
206        break;
207
208      case Prefs::RATIO:
209        sessionSet (TR_KEY_seedRatioLimit, myPrefs.variant (key));
210        break;
211      case Prefs::RATIO_ENABLED:
212        sessionSet (TR_KEY_seedRatioLimited, myPrefs.variant (key));
213        break;
214
215      case Prefs::ENCRYPTION:
216        {
217          const int i = myPrefs.variant (key).toInt ();
218          switch (i)
219            {
220              case 0:
221                sessionSet (myPrefs.getKey (key), QLatin1String ("tolerated"));
222                break;
223              case 1:
224                sessionSet (myPrefs.getKey (key), QLatin1String ("preferred"));
225                break;
226              case 2:
227                sessionSet (myPrefs.getKey (key), QLatin1String ("required"));
228                break;
229            }
230          break;
231        }
232
233      case Prefs::RPC_AUTH_REQUIRED:
234        if (mySession)
235          tr_sessionSetRPCPasswordEnabled (mySession, myPrefs.getBool (key));
236        break;
237
238      case Prefs::RPC_ENABLED:
239        if (mySession)
240          tr_sessionSetRPCEnabled (mySession, myPrefs.getBool (key));
241        break;
242
243      case Prefs::RPC_PASSWORD:
244        if (mySession)
245          tr_sessionSetRPCPassword (mySession, myPrefs.getString (key).toUtf8 ().constData ());
246        break;
247
248      case Prefs::RPC_PORT:
249        if (mySession)
250          tr_sessionSetRPCPort (mySession, myPrefs.getInt (key));
251        break;
252
253      case Prefs::RPC_USERNAME:
254        if (mySession)
255          tr_sessionSetRPCUsername (mySession, myPrefs.getString (key).toUtf8 ().constData ());
256        break;
257
258      case Prefs::RPC_WHITELIST_ENABLED:
259        if (mySession)
260          tr_sessionSetRPCWhitelistEnabled (mySession, myPrefs.getBool (key));
261        break;
262
263      case Prefs::RPC_WHITELIST:
264        if (mySession)
265          tr_sessionSetRPCWhitelist (mySession, myPrefs.getString (key).toUtf8 ().constData ());
266        break;
267
268      default:
269        std::cerr << "unhandled pref: " << key << std::endl;
270    }
271}
272
273/***
274****
275***/
276
277Session::Session (const QString& configDir, Prefs& prefs):
278  myConfigDir (configDir),
279  myPrefs (prefs),
280  nextUniqueTag (FIRST_UNIQUE_TAG),
281  myBlocklistSize (-1),
282  mySession (0)
283{
284  myStats.ratio = TR_RATIO_NA;
285  myStats.uploadedBytes = 0;
286  myStats.downloadedBytes = 0;
287  myStats.filesAdded = 0;
288  myStats.sessionCount = 0;
289  myStats.secondsActive = 0;
290  myCumulativeStats = myStats;
291
292  connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (updatePref (int)));
293
294  connect (&myRpc, SIGNAL (executed (int64_t, QString, tr_variant *)), this, SLOT (responseReceived (int64_t, QString, tr_variant *)));
295
296  connect (&myRpc, SIGNAL (httpAuthenticationRequired ()), this, SIGNAL (httpAuthenticationRequired ()));
297  connect (&myRpc, SIGNAL (dataReadProgress ()), this, SIGNAL (dataReadProgress ()));
298  connect (&myRpc, SIGNAL (dataSendProgress ()), this, SIGNAL (dataSendProgress ()));
299  connect (&myRpc, SIGNAL (error (QNetworkReply::NetworkError)), this, SIGNAL (error (QNetworkReply::NetworkError)));
300  connect (&myRpc, SIGNAL (errorMessage (QString)), this, SIGNAL (errorMessage (QString)));
301}
302
303Session::~Session ()
304{
305    stop ();
306}
307
308/***
309****
310***/
311
312void
313Session::stop ()
314{
315  myRpc.stop ();
316
317  if (mySession)
318    {
319      tr_sessionClose (mySession);
320      mySession = 0;
321    }
322}
323
324void
325Session::restart ()
326{
327  stop ();
328  start ();
329}
330
331void
332Session::start ()
333{
334  if (myPrefs.get<bool> (Prefs::SESSION_IS_REMOTE))
335    {
336      QUrl url;
337      url.setScheme (QLatin1String ("http"));
338      url.setHost (myPrefs.get<QString> (Prefs::SESSION_REMOTE_HOST));
339      url.setPort (myPrefs.get<int> (Prefs::SESSION_REMOTE_PORT));
340      url.setPath (QLatin1String ("/transmission/rpc"));
341      if (myPrefs.get<bool> (Prefs::SESSION_REMOTE_AUTH))
342        {
343          url.setUserName (myPrefs.get<QString> (Prefs::SESSION_REMOTE_USERNAME));
344          url.setPassword (myPrefs.get<QString> (Prefs::SESSION_REMOTE_PASSWORD));
345        }
346
347      myRpc.start (url);
348    }
349  else
350    {
351      tr_variant settings;
352      tr_variantInitDict (&settings, 0);
353      tr_sessionLoadSettings (&settings, myConfigDir.toUtf8 ().constData (), "qt");
354      mySession = tr_sessionInit (myConfigDir.toUtf8 ().constData (), true, &settings);
355      tr_variantFree (&settings);
356
357      myRpc.start (mySession);
358
359      tr_ctor * ctor = tr_ctorNew (mySession);
360      int torrentCount;
361      tr_torrent ** torrents = tr_sessionLoadTorrents (mySession, ctor, &torrentCount);
362      tr_free (torrents);
363      tr_ctorFree (ctor);
364    }
365
366  emit sourceChanged ();
367}
368
369bool
370Session::isServer () const
371{
372  return mySession != 0;
373}
374
375bool
376Session::isLocal () const
377{
378  return myRpc.isLocal ();
379}
380
381/***
382****
383***/
384
385namespace
386{
387  void
388  addOptionalIds (tr_variant * args, const QSet<int>& ids)
389  {
390    if (!ids.isEmpty ())
391      {
392        tr_variant * idList (tr_variantDictAddList (args, TR_KEY_ids, ids.size ()));
393        for (const int i: ids)
394          tr_variantListAddInt (idList, i);
395      }
396  }
397}
398
399void
400Session::torrentSet (const QSet<int>& ids, const tr_quark key, double value)
401{
402  tr_variant args;
403  tr_variantInitDict (&args, 2);
404  tr_variantDictAddReal (&args, key, value);
405  addOptionalIds (&args, ids);
406
407  exec (TR_KEY_torrent_set, &args);
408}
409
410void
411Session::torrentSet (const QSet<int>& ids, const tr_quark key, int value)
412{
413  tr_variant args;
414  tr_variantInitDict (&args, 2);
415  tr_variantDictAddInt (&args, key, value);
416  addOptionalIds (&args, ids);
417
418  exec (TR_KEY_torrent_set, &args);
419}
420
421void
422Session::torrentSet (const QSet<int>& ids, const tr_quark key, bool value)
423{
424  tr_variant args;
425  tr_variantInitDict (&args, 2);
426  tr_variantDictAddBool (&args, key, value);
427  addOptionalIds (&args, ids);
428
429  exec (TR_KEY_torrent_set, &args);
430}
431
432void
433Session::torrentSet (const QSet<int>& ids, const tr_quark key, const QStringList& value)
434{
435  tr_variant args;
436  tr_variantInitDict (&args, 2);
437  addOptionalIds (&args, ids);
438  tr_variant * list (tr_variantDictAddList (&args, key, value.size ()));
439  for (const QString& str: value)
440    tr_variantListAddStr (list, str.toUtf8 ().constData ());
441
442  exec(TR_KEY_torrent_set, &args);
443}
444
445void
446Session::torrentSet (const QSet<int>& ids, const tr_quark key, const QList<int>& value)
447{
448  tr_variant args;
449  tr_variantInitDict (&args, 2);
450  addOptionalIds (&args, ids);
451  tr_variant * list (tr_variantDictAddList (&args, key, value.size ()));
452  for (const int i: value)
453    tr_variantListAddInt (list, i);
454
455  exec (TR_KEY_torrent_set, &args);
456}
457
458void
459Session::torrentSet (const QSet<int>& ids, const tr_quark key, const QPair<int,QString>& value)
460{
461  tr_variant args;
462  tr_variantInitDict (&args, 2);
463  addOptionalIds (&args, ids);
464  tr_variant * list (tr_variantDictAddList (&args, key, 2));
465  tr_variantListAddInt (list, value.first);
466  tr_variantListAddStr (list, value.second.toUtf8 ().constData ());
467
468  exec (TR_KEY_torrent_set, &args);
469}
470
471void
472Session::torrentSetLocation (const QSet<int>& ids, const QString& location, bool doMove)
473{
474  tr_variant args;
475  tr_variantInitDict (&args, 3);
476  addOptionalIds (&args, ids);
477  tr_variantDictAddStr (&args, TR_KEY_location, location.toUtf8 ().constData ());
478  tr_variantDictAddBool (&args, TR_KEY_move, doMove);
479
480  exec (TR_KEY_torrent_set_location, &args);
481}
482
483void
484Session::torrentRenamePath (const QSet<int>& ids, const QString& oldpath, const QString& newname)
485{
486  tr_variant args;
487  tr_variantInitDict (&args, 2);
488  addOptionalIds (&args, ids);
489  tr_variantDictAddStr (&args, TR_KEY_path, oldpath.toUtf8 ().constData ());
490  tr_variantDictAddStr (&args, TR_KEY_name, newname.toUtf8 ().constData ());
491
492  exec ("torrent-rename-path", &args, TAG_RENAME_PATH);
493}
494
495void
496Session::refreshTorrents (const QSet<int>& ids)
497{
498  if (ids.empty ())
499    {
500      refreshAllTorrents ();
501    }
502  else
503    {
504      tr_variant args;
505      tr_variantInitDict (&args, 2);
506      addList (tr_variantDictAddList (&args, TR_KEY_fields, 0), getStatKeys ());
507      addOptionalIds (&args, ids);
508
509      exec (TR_KEY_torrent_get, &args, TAG_SOME_TORRENTS);
510    }
511}
512
513void
514Session::refreshExtraStats (const QSet<int>& ids)
515{
516  tr_variant args;
517  tr_variantInitDict (&args, 3);
518  addOptionalIds (&args, ids);
519  addList (tr_variantDictAddList (&args, TR_KEY_fields, 0), getStatKeys () + getExtraStatKeys ());
520
521  exec (TR_KEY_torrent_get, &args, TAG_SOME_TORRENTS);
522}
523
524void
525Session::sendTorrentRequest (const char * request, const QSet<int>& ids)
526{
527  tr_variant args;
528  tr_variantInitDict (&args, 1);
529  addOptionalIds (&args, ids);
530
531  exec (request, &args);
532
533  refreshTorrents (ids);
534}
535
536void Session::pauseTorrents    (const QSet<int>& ids) { sendTorrentRequest ("torrent-stop",      ids); }
537void Session::startTorrents    (const QSet<int>& ids) { sendTorrentRequest ("torrent-start",     ids); }
538void Session::startTorrentsNow (const QSet<int>& ids) { sendTorrentRequest ("torrent-start-now", ids); }
539void Session::queueMoveTop     (const QSet<int>& ids) { sendTorrentRequest ("queue-move-top",    ids); }
540void Session::queueMoveUp      (const QSet<int>& ids) { sendTorrentRequest ("queue-move-up",     ids); }
541void Session::queueMoveDown    (const QSet<int>& ids) { sendTorrentRequest ("queue-move-down",   ids); }
542void Session::queueMoveBottom  (const QSet<int>& ids) { sendTorrentRequest ("queue-move-bottom", ids); }
543
544void
545Session::refreshActiveTorrents ()
546{
547  tr_variant args;
548  tr_variantInitDict (&args, 2);
549  tr_variantDictAddStr (&args, TR_KEY_ids, "recently-active");
550  addList (tr_variantDictAddList (&args, TR_KEY_fields, 0), getStatKeys ());
551
552  exec (TR_KEY_torrent_get, &args, TAG_SOME_TORRENTS);
553}
554
555void
556Session::refreshAllTorrents ()
557{
558  tr_variant args;
559  tr_variantInitDict (&args, 1);
560  addList (tr_variantDictAddList (&args, TR_KEY_fields, 0), getStatKeys ());
561
562  exec (TR_KEY_torrent_get, &args, TAG_ALL_TORRENTS);
563}
564
565void
566Session::initTorrents (const QSet<int>& ids)
567{
568  tr_variant args;
569  tr_variantInitDict (&args, 2);
570  addOptionalIds (&args, ids);
571  addList (tr_variantDictAddList (&args, TR_KEY_fields, 0), getStatKeys ()+getInfoKeys ());
572
573  exec ("torrent-get", &args, ids.isEmpty () ? TAG_ALL_TORRENTS : TAG_SOME_TORRENTS);
574}
575
576void
577Session::refreshSessionStats ()
578{
579  exec ("session-stats", nullptr, TAG_SESSION_STATS);
580}
581
582void
583Session::refreshSessionInfo ()
584{
585  exec ("session-get", nullptr, TAG_SESSION_INFO);
586}
587
588void
589Session::updateBlocklist ()
590{
591  exec ("blocklist-update", nullptr, TAG_BLOCKLIST_UPDATE);
592}
593
594/***
595****
596***/
597
598void
599Session::exec (tr_quark method, tr_variant * args, int64_t tag)
600{
601  myRpc.exec (method, args, tag);
602}
603
604void
605Session::exec (const char* method, tr_variant * args, int64_t tag)
606{
607  myRpc.exec (method, args, tag);
608}
609
610void
611Session::responseReceived (int64_t tag, const QString& result, tr_variant * args)
612{
613  emit executed (tag, result, args);
614
615  if (tag < 0)
616    return;
617
618  switch (tag)
619    {
620      case TAG_SOME_TORRENTS:
621      case TAG_ALL_TORRENTS:
622        if (args != nullptr)
623          {
624            tr_variant * torrents;
625            if (tr_variantDictFindList (args, TR_KEY_torrents, &torrents))
626                emit torrentsUpdated (torrents, tag==TAG_ALL_TORRENTS);
627            if (tr_variantDictFindList (args, TR_KEY_removed, &torrents))
628                emit torrentsRemoved (torrents);
629          }
630        break;
631
632      case TAG_SESSION_STATS:
633        if (args != nullptr)
634          updateStats (args);
635        break;
636
637      case TAG_SESSION_INFO:
638        if (args != nullptr)
639          updateInfo (args);
640        break;
641
642      case TAG_BLOCKLIST_UPDATE:
643        {
644          int64_t intVal = 0;
645          if (args != nullptr)
646            {
647              if (tr_variantDictFindInt (args, TR_KEY_blocklist_size, &intVal))
648                setBlocklistSize (intVal);
649            }
650          break;
651        }
652
653      case TAG_RENAME_PATH:
654        {
655          int64_t id = 0;
656          if (result != QLatin1String ("success"))
657            {
658              const char * path = "";
659              const char * name = "";
660              tr_variantDictFindStr (args, TR_KEY_path, &path, 0);
661              tr_variantDictFindStr (args, TR_KEY_name, &name, 0);
662              const QString title = tr ("Error Renaming Path");
663              const QString text = tr ("<p><b>Unable to rename \"%1\" as \"%2\": %3.</b></p> <p>Please correct the errors and try again.</p>").arg (QString::fromUtf8 (path)).arg (QString::fromUtf8 (name)).arg (result);
664              QMessageBox * d = new QMessageBox (QMessageBox::Information, title, text,
665                                                 QMessageBox::Close,
666                                                 qApp->activeWindow ());
667              connect (d, SIGNAL (rejected ()), d, SLOT (deleteLater ()));
668              d->show ();
669            }
670          else if (tr_variantDictFindInt (args, TR_KEY_id, &id) && id)
671            {
672              tr_variant args;
673              tr_variantInitDict (&args, 2);
674              tr_variantDictAddInt (&args, TR_KEY_ids, id);
675              addList (tr_variantDictAddList (&args, TR_KEY_fields, 0),
676                       KeyList () << TR_KEY_fileStats << TR_KEY_files << TR_KEY_id << TR_KEY_name);
677              exec ("torrent-get", &args, TAG_SOME_TORRENTS);
678            }
679
680          break;
681      }
682
683      case TAG_PORT_TEST:
684        {
685          bool isOpen;
686          if (args == nullptr ||
687              !tr_variantDictFindBool (args, TR_KEY_port_is_open, &isOpen))
688            isOpen = false;
689          emit portTested (isOpen);
690          break;
691        }
692
693      case TAG_MAGNET_LINK:
694        {
695          tr_variant * torrents;
696          tr_variant * child;
697          const char * str;
698          if (args != nullptr
699              && tr_variantDictFindList (args, TR_KEY_torrents, &torrents)
700              && ( (child = tr_variantListChild (torrents, 0)))
701              && tr_variantDictFindStr (child, TR_KEY_magnetLink, &str, NULL))
702            qApp->clipboard ()->setText (QString::fromUtf8 (str));
703          break;
704        }
705
706      case TAG_ADD_TORRENT:
707        {
708          const char * str = "";
709          if (result != QLatin1String ("success"))
710            {
711              QMessageBox * d = new QMessageBox (QMessageBox::Information,
712                                                 tr ("Add Torrent"),
713                                                 QString::fromUtf8 (str),
714                                                 QMessageBox::Close,
715                                                 qApp->activeWindow ());
716              connect (d, SIGNAL (rejected ()), d, SLOT (deleteLater ()));
717              d->show ();
718            }
719          break;
720        }
721    }
722}
723
724void
725Session::updateStats (tr_variant * d, tr_session_stats * stats)
726{
727  int64_t i;
728
729  if (tr_variantDictFindInt (d, TR_KEY_uploadedBytes, &i))
730    stats->uploadedBytes = i;
731  if (tr_variantDictFindInt (d, TR_KEY_downloadedBytes, &i))
732    stats->downloadedBytes = i;
733  if (tr_variantDictFindInt (d, TR_KEY_filesAdded, &i))
734    stats->filesAdded = i;
735  if (tr_variantDictFindInt (d, TR_KEY_sessionCount, &i))
736    stats->sessionCount = i;
737  if (tr_variantDictFindInt (d, TR_KEY_secondsActive, &i))
738    stats->secondsActive = i;
739
740  stats->ratio = tr_getRatio (stats->uploadedBytes, stats->downloadedBytes);
741}
742
743void
744Session::updateStats (tr_variant * d)
745{
746  tr_variant * c;
747
748  if (tr_variantDictFindDict (d, TR_KEY_current_stats, &c))
749    updateStats (c, &myStats);
750
751  if (tr_variantDictFindDict (d, TR_KEY_cumulative_stats, &c))
752    updateStats (c, &myCumulativeStats);
753
754  emit statsUpdated ();
755}
756
757void
758Session::updateInfo (tr_variant * d)
759{
760  int64_t i;
761  const char * str;
762
763  disconnect (&myPrefs, SIGNAL (changed (int)), this, SLOT (updatePref (int)));
764
765  for (int i=Prefs::FIRST_CORE_PREF; i<=Prefs::LAST_CORE_PREF; ++i)
766    {
767      const tr_variant * b (tr_variantDictFind (d, myPrefs.getKey (i)));
768
769      if (!b)
770        continue;
771
772      if (i == Prefs::ENCRYPTION)
773        {
774          const char * val;
775          if (tr_variantGetStr (b, &val, NULL))
776            {
777              if (!qstrcmp (val , "required"))
778                myPrefs.set (i, 2);
779              else if (!qstrcmp (val , "preferred"))
780                myPrefs.set (i, 1);
781              else if (!qstrcmp (val , "tolerated"))
782                myPrefs.set (i, 0);
783            }
784          continue;
785        }
786
787      switch (myPrefs.type (i))
788        {
789          case QVariant::Int:
790            {
791              int64_t val;
792              if (tr_variantGetInt (b, &val))
793                myPrefs.set (i, static_cast<int>(val));
794              break;
795            }
796          case QVariant::Double:
797            {
798              double val;
799              if (tr_variantGetReal (b, &val))
800                myPrefs.set (i, val);
801              break;
802            }
803          case QVariant::Bool:
804            {
805              bool val;
806              if (tr_variantGetBool (b, &val))
807                myPrefs.set (i, val);
808              break;
809            }
810          case CustomVariantType::FilterModeType:
811          case CustomVariantType::SortModeType:
812          case QVariant::String:
813            {
814              const char * val;
815              if (tr_variantGetStr (b, &val, NULL))
816                myPrefs.set (i, QString::fromUtf8 (val));
817              break;
818            }
819          default:
820            break;
821        }
822    }
823
824  bool b;
825  double x;
826  if (tr_variantDictFindBool (d, TR_KEY_seedRatioLimited, &b))
827    myPrefs.set (Prefs::RATIO_ENABLED, b);
828  if (tr_variantDictFindReal (d, TR_KEY_seedRatioLimit, &x))
829    myPrefs.set (Prefs::RATIO, x);
830
831  /* Use the C API to get settings that, for security reasons, aren't supported by RPC */
832  if (mySession != 0)
833    {
834      myPrefs.set (Prefs::RPC_ENABLED,           tr_sessionIsRPCEnabled (mySession));
835      myPrefs.set (Prefs::RPC_AUTH_REQUIRED,     tr_sessionIsRPCPasswordEnabled (mySession));
836      myPrefs.set (Prefs::RPC_PASSWORD,          QString::fromUtf8 (tr_sessionGetRPCPassword (mySession)));
837      myPrefs.set (Prefs::RPC_PORT,              tr_sessionGetRPCPort (mySession));
838      myPrefs.set (Prefs::RPC_USERNAME,          QString::fromUtf8 (tr_sessionGetRPCUsername (mySession)));
839      myPrefs.set (Prefs::RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled (mySession));
840      myPrefs.set (Prefs::RPC_WHITELIST,         QString::fromUtf8 (tr_sessionGetRPCWhitelist (mySession)));
841    }
842
843  if (tr_variantDictFindInt (d, TR_KEY_blocklist_size, &i) && i!=blocklistSize ())
844    setBlocklistSize (i);
845
846  if (tr_variantDictFindStr (d, TR_KEY_version, &str, NULL) && (mySessionVersion != QString::fromUtf8 (str)))
847    mySessionVersion = QString::fromUtf8 (str);
848
849  //std::cerr << "Session::updateInfo end" << std::endl;
850  connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (updatePref (int)));
851
852  emit sessionUpdated ();
853}
854
855void
856Session::setBlocklistSize (int64_t i)
857{
858  myBlocklistSize = i;
859
860  emit blocklistUpdated (i);
861}
862
863void
864Session::addTorrent (const AddData& addMe, tr_variant * args, bool trashOriginal)
865{
866  assert (tr_variantDictFind (args, TR_KEY_filename) == nullptr);
867  assert (tr_variantDictFind (args, TR_KEY_metainfo) == nullptr);
868
869  if (tr_variantDictFind (args, TR_KEY_paused) == nullptr)
870    tr_variantDictAddBool (args, TR_KEY_paused, !myPrefs.getBool (Prefs::START));
871
872  switch (addMe.type)
873    {
874      case AddData::MAGNET:
875        tr_variantDictAddStr (args, TR_KEY_filename, addMe.magnet.toUtf8 ().constData ());
876        break;
877
878      case AddData::URL:
879        tr_variantDictAddStr (args, TR_KEY_filename, addMe.url.toString ().toUtf8 ().constData ());
880        break;
881
882      case AddData::FILENAME: /* fall-through */
883      case AddData::METAINFO:
884        {
885          const QByteArray b64 = addMe.toBase64 ();
886          tr_variantDictAddRaw (args, TR_KEY_metainfo, b64.constData (), b64.size ());
887          break;
888        }
889
890      default:
891        qWarning() << "Unhandled AddData type: " << addMe.type;
892        break;
893    }
894
895  const int64_t tag = getUniqueTag ();
896
897  // maybe delete the source .torrent
898  FileAdded * fileAdded = new FileAdded (tag, addMe.readableName ());
899  if (trashOriginal && addMe.type == AddData::FILENAME)
900    fileAdded->setFileToDelete (addMe.filename);
901  connect (this, SIGNAL (executed (int64_t, QString, tr_variant *)),
902           fileAdded, SLOT (executed (int64_t, QString, tr_variant *)));
903
904  exec ("torrent-add", args, tag);
905}
906
907void
908Session::addTorrent (const AddData& addMe)
909{
910  tr_variant args;
911  tr_variantInitDict (&args, 3);
912
913  addTorrent (addMe, &args, myPrefs.getBool (Prefs::TRASH_ORIGINAL));
914}
915
916void
917Session::addNewlyCreatedTorrent (const QString& filename, const QString& localPath)
918{
919  const QByteArray b64 = AddData (filename).toBase64 ();
920
921  tr_variant args;
922  tr_variantInitDict (&args, 3);
923  tr_variantDictAddStr (&args, TR_KEY_download_dir, localPath.toUtf8 ().constData ());
924  tr_variantDictAddBool (&args, TR_KEY_paused, !myPrefs.getBool (Prefs::START));
925  tr_variantDictAddRaw (&args, TR_KEY_metainfo, b64.constData (), b64.size ());
926
927  exec ("torrent-add", &args);
928}
929
930void
931Session::removeTorrents (const QSet<int>& ids, bool deleteFiles)
932{
933  if (!ids.isEmpty ())
934    {
935      tr_variant args;
936      tr_variantInitDict (&args, 2);
937      addOptionalIds (&args, ids);
938      tr_variantDictAddInt (&args, TR_KEY_delete_local_data, deleteFiles);
939
940      exec ("torrent-remove", &args);
941    }
942}
943
944void
945Session::verifyTorrents (const QSet<int>& ids)
946{
947  if (!ids.isEmpty ())
948    {
949      tr_variant args;
950      tr_variantInitDict (&args, 1);
951      addOptionalIds (&args, ids);
952
953      exec ("torrent-verify", &args);
954    }
955}
956
957void
958Session::reannounceTorrents (const QSet<int>& ids)
959{
960  if (!ids.isEmpty ())
961    {
962      tr_variant args;
963      tr_variantInitDict (&args, 1);
964      addOptionalIds (&args, ids);
965
966      exec ("torrent-reannounce", &args);
967    }
968}
969
970/***
971****
972***/
973
974void
975Session::launchWebInterface ()
976{
977  QUrl url;
978
979  if (!mySession) // remote session
980    {
981      url = myRpc.url ();
982      url.setPath (QLatin1String ("/transmission/web/"));
983    }
984  else // local session
985    {
986      url.setScheme (QLatin1String ("http"));
987      url.setHost (QLatin1String ("localhost"));
988      url.setPort (myPrefs.getInt (Prefs::RPC_PORT));
989    }
990
991  QDesktopServices::openUrl (url);
992}
Note: See TracBrowser for help on using the repository browser.