source: trunk/qt/Torrent.cc @ 14537

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

Use PascalCase? for Qt client filenames

Split FileTree?.{h,cc} and FilterBar?.{h,cc} files so that each class
is in its own file.

This breaks translations (some classes got renamed => context changed),
to be fixed by next commit (along with Tx sync).

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