source: trunk/qt/torrent.cc @ 14225

Last change on this file since 14225 was 14225, checked in by jordan, 9 years ago

Licensing changes:

  1. add the option the code to be used under GPLv2 or GPLv3; previously only GPLv2 was allowed
  1. add the "proxy option" as described in GPLv3 so we can add future licenses without having to bulk-edit everything again :)
  1. remove the awkward "exception for MIT code in Mac client" clause; it was unnecessary and confusing.
  • Property svn:keywords set to Date Rev Author Id
File size: 22.9 KB
Line 
1/*
2 * This file Copyright (C) 2009-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU Public License v2 or v3 licenses,
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: torrent.cc 14225 2014-01-19 01:09:44Z jordan $
8 */
9
10#include <cassert>
11#include <iostream>
12
13#include <QApplication>
14#include <QFileIconProvider>
15#include <QFileInfo>
16#include <QSet>
17#include <QString>
18#include <QStyle>
19#include <QUrl>
20#include <QVariant>
21
22#include <libtransmission/transmission.h>
23#include <libtransmission/utils.h> /* tr_new0, tr_strdup */
24#include <libtransmission/variant.h>
25
26#include "app.h"
27#include "prefs.h"
28#include "torrent.h"
29#include "utils.h"
30
31
32Torrent :: Torrent (Prefs& prefs, int id):
33  magnetTorrent (false),
34  myPrefs (prefs)
35{
36#ifndef NDEBUG
37  for (int i=0; i<PROPERTY_COUNT; ++i)
38    assert (myProperties[i].id == i);
39#endif
40
41  setInt (ID, id);
42  setIcon (MIME_ICON, QApplication::style()->standardIcon (QStyle::SP_FileIcon));
43}
44
45Torrent :: ~Torrent ()
46{
47}
48
49/***
50****
51***/
52
53Torrent :: Property
54Torrent :: myProperties[] =
55{
56  { ID, TR_KEY_id, QVariant::Int, INFO, },
57  { UPLOAD_SPEED, TR_KEY_rateUpload, QVariant::ULongLong, STAT } /* Bps */,
58  { DOWNLOAD_SPEED, TR_KEY_rateDownload, QVariant::ULongLong, STAT }, /* Bps */
59  { DOWNLOAD_DIR, TR_KEY_downloadDir, QVariant::String, STAT },
60  { ACTIVITY, TR_KEY_status, QVariant::Int, STAT },
61  { NAME, TR_KEY_name, QVariant::String, INFO },
62  { ERROR, TR_KEY_error, QVariant::Int, STAT },
63  { ERROR_STRING, TR_KEY_errorString, QVariant::String, STAT },
64  { SIZE_WHEN_DONE, TR_KEY_sizeWhenDone, QVariant::ULongLong, STAT },
65  { LEFT_UNTIL_DONE, TR_KEY_leftUntilDone, QVariant::ULongLong, STAT },
66  { HAVE_UNCHECKED, TR_KEY_haveUnchecked, QVariant::ULongLong, STAT },
67  { HAVE_VERIFIED, TR_KEY_haveValid, QVariant::ULongLong, STAT },
68  { DESIRED_AVAILABLE, TR_KEY_desiredAvailable, QVariant::ULongLong, STAT },
69  { TOTAL_SIZE, TR_KEY_totalSize, QVariant::ULongLong, INFO },
70  { PIECE_SIZE, TR_KEY_pieceSize, QVariant::ULongLong, INFO },
71  { PIECE_COUNT, TR_KEY_pieceCount, QVariant::Int, INFO },
72  { PEERS_GETTING_FROM_US, TR_KEY_peersGettingFromUs, QVariant::Int, STAT },
73  { PEERS_SENDING_TO_US, TR_KEY_peersSendingToUs, QVariant::Int, STAT },
74  { WEBSEEDS_SENDING_TO_US, TR_KEY_webseedsSendingToUs, QVariant::Int, STAT_EXTRA },
75  { PERCENT_DONE, TR_KEY_percentDone, QVariant::Double, STAT },
76  { METADATA_PERCENT_DONE, TR_KEY_metadataPercentComplete, QVariant::Double, STAT },
77  { PERCENT_VERIFIED, TR_KEY_recheckProgress, QVariant::Double, STAT },
78  { DATE_ACTIVITY, TR_KEY_activityDate, QVariant::DateTime, STAT_EXTRA },
79  { DATE_ADDED, TR_KEY_addedDate, QVariant::DateTime, INFO },
80  { DATE_STARTED, TR_KEY_startDate, QVariant::DateTime, STAT_EXTRA },
81  { DATE_CREATED, TR_KEY_dateCreated, QVariant::DateTime, INFO },
82  { PEERS_CONNECTED, TR_KEY_peersConnected, QVariant::Int, STAT },
83  { ETA, TR_KEY_eta, QVariant::Int, STAT },
84  { RATIO, TR_KEY_uploadRatio, QVariant::Double, STAT },
85  { DOWNLOADED_EVER, TR_KEY_downloadedEver, QVariant::ULongLong, STAT },
86  { UPLOADED_EVER, TR_KEY_uploadedEver, QVariant::ULongLong, STAT },
87  { FAILED_EVER, TR_KEY_corruptEver, QVariant::ULongLong, STAT_EXTRA },
88  { TRACKERS, TR_KEY_trackers, QVariant::StringList, STAT },
89  { HOSTS, TR_KEY_NONE, QVariant::StringList, DERIVED },
90  { TRACKERSTATS, TR_KEY_trackerStats, TrTypes::TrackerStatsList, STAT_EXTRA },
91  { MIME_ICON, TR_KEY_NONE, QVariant::Icon, DERIVED },
92  { SEED_RATIO_LIMIT, TR_KEY_seedRatioLimit, QVariant::Double, STAT },
93  { SEED_RATIO_MODE, TR_KEY_seedRatioMode, QVariant::Int, STAT },
94  { SEED_IDLE_LIMIT, TR_KEY_seedIdleLimit, QVariant::Int, STAT_EXTRA },
95  { SEED_IDLE_MODE, TR_KEY_seedIdleMode, QVariant::Int, STAT_EXTRA },
96  { DOWN_LIMIT, TR_KEY_downloadLimit, QVariant::Int, STAT_EXTRA }, /* KB/s */
97  { DOWN_LIMITED, TR_KEY_downloadLimited, QVariant::Bool, STAT_EXTRA },
98  { UP_LIMIT, TR_KEY_uploadLimit, QVariant::Int, STAT_EXTRA }, /* KB/s */
99  { UP_LIMITED, TR_KEY_uploadLimited, QVariant::Bool, STAT_EXTRA },
100  { HONORS_SESSION_LIMITS, TR_KEY_honorsSessionLimits, QVariant::Bool, STAT_EXTRA },
101  { PEER_LIMIT, TR_KEY_peer_limit, QVariant::Int, STAT_EXTRA },
102  { HASH_STRING, TR_KEY_hashString, QVariant::String, INFO },
103  { IS_FINISHED, TR_KEY_isFinished, QVariant::Bool, STAT },
104  { IS_PRIVATE, TR_KEY_isPrivate, QVariant::Bool, INFO },
105  { IS_STALLED, TR_KEY_isStalled, QVariant::Bool, STAT },
106  { COMMENT, TR_KEY_comment, QVariant::String, INFO },
107  { CREATOR, TR_KEY_creator, QVariant::String, INFO },
108  { MANUAL_ANNOUNCE_TIME, TR_KEY_manualAnnounceTime, QVariant::DateTime, STAT_EXTRA },
109  { PEERS, TR_KEY_peers, TrTypes::PeerList, STAT_EXTRA },
110  { BANDWIDTH_PRIORITY, TR_KEY_bandwidthPriority, QVariant::Int, STAT_EXTRA },
111  { QUEUE_POSITION, TR_KEY_queuePosition, QVariant::Int, STAT },
112};
113
114Torrent :: KeyList
115Torrent :: buildKeyList (Group group)
116{
117  KeyList keys;
118
119  if (keys.empty())
120    for (int i=0; i<PROPERTY_COUNT; ++i)
121      if (myProperties[i].id==ID || myProperties[i].group==group)
122        keys << myProperties[i].key;
123
124  return keys;
125}
126
127const Torrent :: KeyList&
128Torrent :: getInfoKeys ()
129{
130  static KeyList keys;
131
132  if (keys.isEmpty())
133    keys << buildKeyList(INFO) << TR_KEY_files;
134
135  return keys;
136}
137
138const Torrent :: KeyList&
139Torrent :: getStatKeys ()
140{
141  static KeyList keys (buildKeyList(STAT));
142  return keys;
143}
144
145const Torrent :: KeyList&
146Torrent :: getExtraStatKeys()
147{
148  static KeyList keys;
149
150  if (keys.isEmpty())
151    keys << buildKeyList(STAT_EXTRA) << TR_KEY_fileStats;
152
153  return keys;
154}
155
156bool
157Torrent :: setInt (int i, int value)
158{
159  bool changed = false;
160
161  assert (0<=i && i<PROPERTY_COUNT);
162  assert (myProperties[i].type == QVariant::Int);
163
164  if (myValues[i].isNull() || myValues[i].toInt()!=value)
165    {
166      myValues[i].setValue (value);
167      changed = true;
168    }
169
170  return changed;
171}
172
173bool
174Torrent :: setBool (int i, bool value)
175{
176  bool changed = false;
177
178  assert (0<=i && i<PROPERTY_COUNT);
179  assert (myProperties[i].type == QVariant::Bool);
180
181  if (myValues[i].isNull() || myValues[i].toBool()!=value)
182    {
183      myValues[i].setValue (value);
184      changed = true;
185    }
186
187  return changed;
188}
189
190bool
191Torrent :: setDouble (int i, double value)
192{
193  bool changed = false;
194
195  assert (0<=i && i<PROPERTY_COUNT);
196  assert (myProperties[i].type == QVariant::Double);
197
198  if (myValues[i].isNull() || myValues[i].toDouble()!=value)
199    {
200      myValues[i].setValue (value);
201      changed = true;
202    }
203
204  return changed;
205}
206
207bool
208Torrent :: setDateTime (int i, const QDateTime& value)
209{
210  bool changed = false;
211
212  assert (0<=i && i<PROPERTY_COUNT);
213  assert (myProperties[i].type == QVariant::DateTime);
214
215  if (myValues[i].isNull() || myValues[i].toDateTime()!=value)
216    {
217      myValues[i].setValue (value);
218      changed = true;
219    }
220
221  return changed;
222}
223
224bool
225Torrent :: setSize (int i, qulonglong value)
226{
227  bool changed = false;
228
229  assert (0<=i && i<PROPERTY_COUNT);
230  assert (myProperties[i].type == QVariant::ULongLong);
231
232  if (myValues[i].isNull() || myValues[i].toULongLong()!=value)
233    {
234      myValues[i].setValue (value);
235      changed = true;
236    }
237
238  return changed;
239}
240
241bool
242Torrent :: setString (int i, const char * value)
243{
244  bool changed = false;
245
246  assert (0<=i && i<PROPERTY_COUNT);
247  assert (myProperties[i].type == QVariant::String);
248
249  if (myValues[i].isNull() || myValues[i].toString()!=value)
250    {
251      myValues[i].setValue (QString::fromUtf8 (value));
252      changed = true;
253    }
254
255  return changed;
256}
257
258bool
259Torrent :: setIcon (int i, const QIcon& value)
260{
261  assert (0<=i && i<PROPERTY_COUNT);
262  assert (myProperties[i].type == QVariant::Icon);
263
264  myValues[i].setValue (value);
265  return true;
266}
267
268int
269Torrent :: getInt (int i) const
270{
271  assert (0<=i && i<PROPERTY_COUNT);
272  assert (myProperties[i].type == QVariant::Int);
273
274  return myValues[i].toInt ();
275}
276
277QDateTime
278Torrent :: getDateTime (int i) const
279{
280  assert (0<=i && i<PROPERTY_COUNT);
281  assert (myProperties[i].type == QVariant::DateTime);
282
283  return myValues[i].toDateTime ();
284}
285
286bool
287Torrent :: getBool (int i) const
288{
289  assert (0<=i && i<PROPERTY_COUNT);
290  assert (myProperties[i].type == QVariant::Bool);
291
292  return myValues[i].toBool ();
293}
294
295qulonglong
296Torrent :: getSize (int i) const
297{
298    assert (0<=i && i<PROPERTY_COUNT);
299    assert (myProperties[i].type == QVariant::ULongLong);
300
301    return myValues[i].toULongLong ();
302}
303double
304Torrent :: getDouble (int i) const
305{
306  assert (0<=i && i<PROPERTY_COUNT);
307  assert (myProperties[i].type == QVariant::Double);
308
309  return myValues[i].toDouble ();
310}
311QString
312Torrent :: getString (int i) const
313{
314  assert (0<=i && i<PROPERTY_COUNT);
315  assert (myProperties[i].type == QVariant::String);
316
317  return myValues[i].toString ();
318}
319QIcon
320Torrent :: getIcon (int i) const
321{
322  assert (0<=i && i<PROPERTY_COUNT);
323  assert (myProperties[i].type == QVariant::Icon);
324
325  return myValues[i].value<QIcon>();
326}
327
328/***
329****
330***/
331
332bool
333Torrent :: getSeedRatio (double& ratio) const
334{
335  bool isLimited;
336
337  switch (seedRatioMode ())
338    {
339      case TR_RATIOLIMIT_SINGLE:
340        isLimited = true;
341        ratio = seedRatioLimit ();
342        break;
343
344      case TR_RATIOLIMIT_GLOBAL:
345        if ((isLimited = myPrefs.getBool (Prefs :: RATIO_ENABLED)))
346          ratio = myPrefs.getDouble (Prefs :: RATIO);
347        break;
348
349      default: // TR_RATIOLIMIT_UNLIMITED:
350        isLimited = false;
351        break;
352    }
353
354  return isLimited;
355}
356
357bool
358Torrent :: hasFileSubstring (const QString& substr) const
359{
360  foreach (const TrFile file, myFiles)
361    if (file.filename.contains (substr, Qt::CaseInsensitive))
362      return true;
363
364  return false;
365}
366
367bool
368Torrent :: hasTrackerSubstring (const QString& substr) const
369{
370  foreach (QString s, myValues[TRACKERS].toStringList())
371    if (s.contains (substr, Qt::CaseInsensitive))
372      return true;
373
374  return false;
375}
376
377int
378Torrent :: compareSeedRatio (const Torrent& that) const
379{
380  double a;
381  double b;
382  const bool has_a = getSeedRatio (a);
383  const bool has_b = that.getSeedRatio (b);
384  if (!has_a && !has_b) return 0;
385  if (!has_a || !has_b) return has_a ? -1 : 1;
386  if (a < b) return -1;
387  if (a > b) return 1;
388  return 0;
389}
390
391int
392Torrent :: compareRatio (const Torrent& that) const
393{
394  const double a = ratio ();
395  const double b = that.ratio ();
396  if ((int)a == TR_RATIO_INF && (int)b == TR_RATIO_INF) return 0;
397  if ((int)a == TR_RATIO_INF) return 1;
398  if ((int)b == TR_RATIO_INF) return -1;
399  if (a < b) return -1;
400  if (a > b) return 1;
401  return 0;
402}
403
404int
405Torrent :: compareETA (const Torrent& that) const
406{
407  const bool haveA (hasETA ());
408  const bool haveB (that.hasETA ());
409  if (haveA && haveB) return getETA() - that.getETA();
410  if (haveA) return 1;
411  if (haveB) return -1;
412  return 0;
413}
414
415int
416Torrent :: compareTracker (const Torrent& that) const
417{
418  Q_UNUSED (that);
419
420  // FIXME
421  return 0;
422}
423
424/***
425****
426***/
427
428void
429Torrent :: updateMimeIcon ()
430{
431  const FileList& files (myFiles);
432
433  QIcon icon;
434
435  if (files.size () > 1)
436    icon = QFileIconProvider().icon (QFileIconProvider::Folder);
437  else if (files.size () == 1)
438    icon = Utils :: guessMimeIcon (files.at(0).filename);
439  else
440    icon = QIcon ();
441
442  setIcon (MIME_ICON, icon);
443}
444
445/***
446****
447***/
448
449void
450Torrent :: notifyComplete () const
451{
452    // if someone wants to implement notification, here's the hook.
453}
454
455/***
456****
457***/
458
459void
460Torrent :: update (tr_variant * d)
461{
462  static bool lookup_initialized = false;
463  static int key_to_property_index[TR_N_KEYS];
464  bool changed = false;
465  const bool was_seed = isSeed ();
466  const uint64_t old_verified_size = haveVerified ();
467
468  if (!lookup_initialized)
469    {
470      lookup_initialized = true;
471      for (int i=0; i<TR_N_KEYS; ++i)
472        key_to_property_index[i] = -1;
473      for (int i=0; i<PROPERTY_COUNT; i++)
474        key_to_property_index[myProperties[i].key] = i;
475    }
476
477  tr_quark key;
478  tr_variant * child;
479  size_t pos = 0;
480  while (tr_variantDictChild (d, pos++, &key, &child))
481    {
482      const int property_index = key_to_property_index[key];
483      if (property_index == -1) // we're not interested in this one
484        continue;
485
486      assert (myProperties[property_index].key == key);
487
488      switch (myProperties[property_index].type)
489        {
490          case QVariant :: Int:
491            {
492              int64_t val;
493              if (tr_variantGetInt (child, &val))
494                changed |= setInt (property_index, val);
495              break;
496            }
497          case QVariant :: Bool:
498            {
499              bool val;
500              if (tr_variantGetBool (child, &val))
501                changed |= setBool (property_index, val);
502              break;
503            }
504          case QVariant :: String:
505            {
506              const char * val;
507              if (tr_variantGetStr(child, &val, NULL))
508                changed |= setString (property_index, val);
509              break;
510            }
511          case QVariant :: ULongLong:
512            {
513              int64_t val;
514              if (tr_variantGetInt (child, &val))
515                changed |= setSize (property_index, val);
516              break;
517            }
518          case QVariant :: Double:
519            {
520              double val;
521              if (tr_variantGetReal (child, &val))
522                changed |= setDouble (property_index, val);
523              break;
524            }
525          case QVariant :: DateTime:
526            {
527              int64_t val;
528              if (tr_variantGetInt (child, &val) && val)
529                changed |= setDateTime (property_index, QDateTime :: fromTime_t(val));
530              break;
531            }
532
533          case QVariant :: StringList:
534          case TrTypes :: PeerList:
535            // handled below
536            break;
537
538          default:
539            std::cerr << __FILE__ << ':' << __LINE__ << "unhandled type: " << tr_quark_get_string(key,NULL) << std::endl;
540            assert (0 && "unhandled type");
541        }
542    }
543
544  tr_variant * files;
545
546  if (tr_variantDictFindList (d, TR_KEY_files, &files))
547    {
548      const char * str;
549      int64_t intVal;
550      int i = 0;
551      tr_variant * child;
552
553      myFiles.clear ();
554      myFiles.reserve (tr_variantListSize (files));
555
556      while ((child = tr_variantListChild (files, i)))
557        {
558          TrFile file;
559          size_t len;
560          file.index = i++;
561
562          if (tr_variantDictFindStr(child, TR_KEY_name, &str, &len))
563            file.filename = QString::fromUtf8 (str, len);
564          if (tr_variantDictFindInt (child, TR_KEY_length, &intVal))
565            file.size = intVal;
566
567          myFiles.append (file);
568        }
569
570      updateMimeIcon ();
571      changed = true;
572    }
573
574  if (tr_variantDictFindList (d, TR_KEY_fileStats, &files))
575    {
576      const int n = tr_variantListSize (files);
577
578      for (int i=0; i<n && i<myFiles.size(); ++i)
579        {
580          int64_t intVal;
581          bool boolVal;
582          tr_variant * child = tr_variantListChild (files, i);
583          TrFile& file (myFiles[i]);
584
585          if (tr_variantDictFindInt (child, TR_KEY_bytesCompleted, &intVal))
586            file.have = intVal;
587          if (tr_variantDictFindBool (child, TR_KEY_wanted, &boolVal))
588            file.wanted = boolVal;
589          if (tr_variantDictFindInt (child, TR_KEY_priority, &intVal))
590            file.priority = intVal;
591        }
592        changed = true;
593    }
594
595  tr_variant * trackers;
596  if (tr_variantDictFindList (d, TR_KEY_trackers, &trackers))
597    {
598      size_t len;
599      const char * str;
600      int i = 0;
601      QStringList list;
602      tr_variant * child;
603
604      while ((child = tr_variantListChild (trackers, i++)))
605        {
606          if (tr_variantDictFindStr(child, TR_KEY_announce, &str, &len))
607            {
608              dynamic_cast<MyApp*>(QApplication::instance())->favicons.add (QUrl(QString::fromUtf8(str)));
609              list.append (QString::fromUtf8 (str, len));
610            }
611        }
612
613      if (myValues[TRACKERS] != list)
614        {
615          QStringList hosts;
616          foreach (QString tracker, list)
617            {
618              const QString host = Favicons::getHost (QUrl (tracker));
619              if (!host.isEmpty())
620                hosts.append (host);
621            }
622          hosts.removeDuplicates();
623
624          myValues[TRACKERS].setValue (list);
625          myValues[HOSTS].setValue (hosts);
626          changed = true;
627        }
628    }
629
630  tr_variant * trackerStats;
631  if (tr_variantDictFindList (d, TR_KEY_trackerStats, &trackerStats))
632    {
633      tr_variant * child;
634      TrackerStatsList  trackerStatsList;
635      int childNum = 0;
636
637      while ((child = tr_variantListChild (trackerStats, childNum++)))
638        {
639          bool b;
640          int64_t i;
641          size_t len;
642          const char * str;
643          TrackerStat trackerStat;
644
645          if (tr_variantDictFindStr(child, TR_KEY_announce, &str, &len))
646            {
647              trackerStat.announce = QString::fromUtf8 (str, len);
648              dynamic_cast<MyApp*>(QApplication::instance())->favicons.add (QUrl (trackerStat.announce));
649            }
650
651          if (tr_variantDictFindInt (child, TR_KEY_announceState, &i))
652            trackerStat.announceState = i;
653          if (tr_variantDictFindInt (child, TR_KEY_downloadCount, &i))
654            trackerStat.downloadCount = i;
655          if (tr_variantDictFindBool (child, TR_KEY_hasAnnounced, &b))
656            trackerStat.hasAnnounced = b;
657          if (tr_variantDictFindBool (child, TR_KEY_hasScraped, &b))
658            trackerStat.hasScraped = b;
659          if (tr_variantDictFindStr(child, TR_KEY_host, &str, &len))
660            trackerStat.host = QString::fromUtf8 (str, len);
661          if (tr_variantDictFindInt (child, TR_KEY_id, &i))
662            trackerStat.id = i;
663          if (tr_variantDictFindBool (child, TR_KEY_isBackup, &b))
664            trackerStat.isBackup = b;
665          if (tr_variantDictFindInt (child, TR_KEY_lastAnnouncePeerCount, &i))
666            trackerStat.lastAnnouncePeerCount = i;
667          if (tr_variantDictFindStr(child, TR_KEY_lastAnnounceResult, &str, &len))
668            trackerStat.lastAnnounceResult = QString::fromUtf8(str, len);
669          if (tr_variantDictFindInt (child, TR_KEY_lastAnnounceStartTime, &i))
670            trackerStat.lastAnnounceStartTime = i;
671          if (tr_variantDictFindBool (child, TR_KEY_lastAnnounceSucceeded, &b))
672            trackerStat.lastAnnounceSucceeded = b;
673          if (tr_variantDictFindInt (child, TR_KEY_lastAnnounceTime, &i))
674            trackerStat.lastAnnounceTime = i;
675          if (tr_variantDictFindBool (child, TR_KEY_lastAnnounceTimedOut, &b))
676            trackerStat.lastAnnounceTimedOut = b;
677          if (tr_variantDictFindStr(child, TR_KEY_lastScrapeResult, &str, &len))
678            trackerStat.lastScrapeResult = QString::fromUtf8 (str, len);
679          if (tr_variantDictFindInt (child, TR_KEY_lastScrapeStartTime, &i))
680            trackerStat.lastScrapeStartTime = i;
681          if (tr_variantDictFindBool (child, TR_KEY_lastScrapeSucceeded, &b))
682            trackerStat.lastScrapeSucceeded = b;
683          if (tr_variantDictFindInt (child, TR_KEY_lastScrapeTime, &i))
684            trackerStat.lastScrapeTime = i;
685          if (tr_variantDictFindBool (child, TR_KEY_lastScrapeTimedOut, &b))
686            trackerStat.lastScrapeTimedOut = b;
687          if (tr_variantDictFindInt (child, TR_KEY_leecherCount, &i))
688            trackerStat.leecherCount = i;
689          if (tr_variantDictFindInt (child, TR_KEY_nextAnnounceTime, &i))
690            trackerStat.nextAnnounceTime = i;
691          if (tr_variantDictFindInt (child, TR_KEY_nextScrapeTime, &i))
692            trackerStat.nextScrapeTime = i;
693          if (tr_variantDictFindInt (child, TR_KEY_scrapeState, &i))
694            trackerStat.scrapeState = i;
695          if (tr_variantDictFindInt (child, TR_KEY_seederCount, &i))
696            trackerStat.seederCount = i;
697          if (tr_variantDictFindInt (child, TR_KEY_tier, &i))
698            trackerStat.tier = i;
699
700          trackerStatsList << trackerStat;
701        }
702
703      myValues[TRACKERSTATS].setValue (trackerStatsList);
704      changed = true;
705    }
706
707  tr_variant * peers;
708  if (tr_variantDictFindList (d, TR_KEY_peers, &peers))
709    {
710      tr_variant * child;
711      PeerList peerList;
712      int childNum = 0;
713      while ((child = tr_variantListChild (peers, childNum++)))
714        {
715          double d;
716          bool b;
717          int64_t i;
718          size_t len;
719          const char * str;
720          Peer peer;
721
722          if (tr_variantDictFindStr(child, TR_KEY_address, &str, &len))
723            peer.address = QString::fromUtf8 (str, len);
724          if (tr_variantDictFindStr(child, TR_KEY_clientName, &str, &len))
725            peer.clientName = QString::fromUtf8 (str, len);
726          if (tr_variantDictFindBool (child, TR_KEY_clientIsChoked, &b))
727            peer.clientIsChoked = b;
728          if (tr_variantDictFindBool (child, TR_KEY_clientIsInterested, &b))
729            peer.clientIsInterested = b;
730          if (tr_variantDictFindStr(child, TR_KEY_flagStr, &str, &len))
731            peer.flagStr = QString::fromUtf8 (str, len);
732          if (tr_variantDictFindBool (child, TR_KEY_isDownloadingFrom, &b))
733            peer.isDownloadingFrom = b;
734          if (tr_variantDictFindBool (child, TR_KEY_isEncrypted, &b))
735            peer.isEncrypted = b;
736          if (tr_variantDictFindBool (child, TR_KEY_isIncoming, &b))
737            peer.isIncoming = b;
738          if (tr_variantDictFindBool (child, TR_KEY_isUploadingTo, &b))
739            peer.isUploadingTo = b;
740          if (tr_variantDictFindBool (child, TR_KEY_peerIsChoked, &b))
741            peer.peerIsChoked = b;
742          if (tr_variantDictFindBool (child, TR_KEY_peerIsInterested, &b))
743            peer.peerIsInterested = b;
744          if (tr_variantDictFindInt (child, TR_KEY_port, &i))
745            peer.port = i;
746          if (tr_variantDictFindReal (child, TR_KEY_progress, &d))
747            peer.progress = d;
748          if (tr_variantDictFindInt (child, TR_KEY_rateToClient, &i))
749            peer.rateToClient = Speed::fromBps (i);
750          if (tr_variantDictFindInt (child, TR_KEY_rateToPeer, &i))
751            peer.rateToPeer = Speed::fromBps (i);
752          peerList << peer;
753        }
754
755      myValues[PEERS].setValue (peerList);
756      changed = true;
757    }
758
759  if (changed)
760    emit torrentChanged (id ());
761
762  if (!was_seed && isSeed() && (old_verified_size>0))
763    emit torrentCompleted (id ());
764}
765
766QString
767Torrent :: activityString () const
768{
769  QString str;
770
771  switch (getActivity ())
772    {
773      case TR_STATUS_STOPPED:       str = isFinished() ? tr("Finished"): tr("Paused"); break;
774      case TR_STATUS_CHECK_WAIT:    str = tr("Queued for verification"); break;
775      case TR_STATUS_CHECK:         str = tr("Verifying local data"); break;
776      case TR_STATUS_DOWNLOAD_WAIT: str = tr("Queued for download"); break;
777      case TR_STATUS_DOWNLOAD:      str = tr("Downloading"); break;
778      case TR_STATUS_SEED_WAIT:     str = tr("Queued for seeding"); break;
779      case TR_STATUS_SEED:          str = tr("Seeding"); break;
780    }
781
782  return str;
783}
784
785QString
786Torrent :: getError () const
787{
788  QString s = getString (ERROR_STRING);
789
790  switch (getInt (ERROR))
791    {
792      case TR_STAT_TRACKER_WARNING: s = tr("Tracker gave a warning: %1").arg(s); break;
793      case TR_STAT_TRACKER_ERROR: s = tr("Tracker gave an error: %1").arg(s); break;
794      case TR_STAT_LOCAL_ERROR: s = tr("Error: %1").arg(s); break;
795      default: s.clear(); break;
796    }
797
798  return s;
799}
800
801QPixmap
802TrackerStat :: getFavicon () const
803{
804  MyApp * myApp = dynamic_cast<MyApp*>(QApplication::instance());
805  return myApp->favicons.find (QUrl (announce));
806}
807
Note: See TracBrowser for help on using the repository browser.