source: trunk/qt/torrent.cc @ 13810

Last change on this file since 13810 was 13810, checked in by jordan, 8 years ago

(trunk) #1220 'change top folder names' -- add file-renaming to the Qt client

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