qBittorrent
TrackerListWidget Class Reference

#include <trackerlistwidget.h>

Inheritance diagram for TrackerListWidget:
Collaboration diagram for TrackerListWidget:

Public Types

enum  TrackerListColumn {
  COL_TIER , COL_URL , COL_STATUS , COL_PEERS ,
  COL_SEEDS , COL_LEECHES , COL_DOWNLOADED , COL_MSG ,
  COL_COUNT
}
 

Public Slots

void setRowColor (int row, const QColor &color)
 
void moveSelectionUp ()
 
void moveSelectionDown ()
 
void clear ()
 
void loadStickyItems (const BitTorrent::Torrent *torrent)
 
void loadTrackers ()
 
void askForTrackers ()
 
void copyTrackerUrl ()
 
void reannounceSelected ()
 
void deleteSelectedTrackers ()
 
void editSelectedTracker ()
 
void showTrackerListMenu (const QPoint &)
 
void displayToggleColumnsMenu (const QPoint &)
 
void loadSettings ()
 
void saveSettings () const
 

Public Member Functions

 TrackerListWidget (PropertiesWidget *properties)
 
 ~TrackerListWidget ()
 
int visibleColumnsCount () const
 

Protected Member Functions

QVector< QTreeWidgetItem * > getSelectedTrackerItems () const
 

Static Private Member Functions

static QStringList headerLabels ()
 

Private Attributes

PropertiesWidgetm_properties
 
QHash< QString, QTreeWidgetItem * > m_trackerItems
 
QTreeWidgetItem * m_DHTItem
 
QTreeWidgetItem * m_PEXItem
 
QTreeWidgetItem * m_LSDItem
 

Detailed Description

Definition at line 41 of file trackerlistwidget.h.

Member Enumeration Documentation

◆ TrackerListColumn

Enumerator
COL_TIER 
COL_URL 
COL_STATUS 
COL_PEERS 
COL_SEEDS 
COL_LEECHES 
COL_DOWNLOADED 
COL_MSG 
COL_COUNT 

Definition at line 47 of file trackerlistwidget.h.

Constructor & Destructor Documentation

◆ TrackerListWidget()

TrackerListWidget::TrackerListWidget ( PropertiesWidget properties)
explicit

Definition at line 59 of file trackerlistwidget.cpp.

60  : QTreeWidget()
61  , m_properties(properties)
62 {
63  // Set header
64  // Must be set before calling loadSettings() otherwise the header is reset on restart
65  setHeaderLabels(headerLabels());
66  // Load settings
67  loadSettings();
68  // Graphical settings
69  setRootIsDecorated(false);
70  setAllColumnsShowFocus(true);
71  setItemsExpandable(false);
72  setSelectionMode(QAbstractItemView::ExtendedSelection);
73  header()->setStretchLastSection(false); // Must be set after loadSettings() in order to work
74  header()->setTextElideMode(Qt::ElideRight);
75  // Ensure that at least one column is visible at all times
76  if (visibleColumnsCount() == 0)
77  setColumnHidden(COL_URL, false);
78  // To also mitigate the above issue, we have to resize each column when
79  // its size is 0, because explicitly 'showing' the column isn't enough
80  // in the above scenario.
81  for (int i = 0; i < COL_COUNT; ++i)
82  if ((columnWidth(i) <= 0) && !isColumnHidden(i))
83  resizeColumnToContents(i);
84  // Context menu
85  setContextMenuPolicy(Qt::CustomContextMenu);
86  connect(this, &QWidget::customContextMenuRequested, this, &TrackerListWidget::showTrackerListMenu);
87  // Header
88  header()->setContextMenuPolicy(Qt::CustomContextMenu);
89  connect(header(), &QWidget::customContextMenuRequested, this, &TrackerListWidget::displayToggleColumnsMenu);
90  connect(header(), &QHeaderView::sectionMoved, this, &TrackerListWidget::saveSettings);
91  connect(header(), &QHeaderView::sectionResized, this, &TrackerListWidget::saveSettings);
92  connect(header(), &QHeaderView::sortIndicatorChanged, this, &TrackerListWidget::saveSettings);
93 
94  // Set DHT, PeX, LSD items
95  m_DHTItem = new QTreeWidgetItem({ "", "** [DHT] **", "", "0", "", "", "0" });
96  insertTopLevelItem(0, m_DHTItem);
97  setRowColor(0, QColor("grey"));
98  m_PEXItem = new QTreeWidgetItem({ "", "** [PeX] **", "", "0", "", "", "0" });
99  insertTopLevelItem(1, m_PEXItem);
100  setRowColor(1, QColor("grey"));
101  m_LSDItem = new QTreeWidgetItem({ "", "** [LSD] **", "", "0", "", "", "0" });
102  insertTopLevelItem(2, m_LSDItem);
103  setRowColor(2, QColor("grey"));
104 
105  // Set static items alignment
106  const Qt::Alignment alignment = (Qt::AlignRight | Qt::AlignVCenter);
107  m_DHTItem->setTextAlignment(COL_PEERS, alignment);
108  m_PEXItem->setTextAlignment(COL_PEERS, alignment);
109  m_LSDItem->setTextAlignment(COL_PEERS, alignment);
110  m_DHTItem->setTextAlignment(COL_SEEDS, alignment);
111  m_PEXItem->setTextAlignment(COL_SEEDS, alignment);
112  m_LSDItem->setTextAlignment(COL_SEEDS, alignment);
113  m_DHTItem->setTextAlignment(COL_LEECHES, alignment);
114  m_PEXItem->setTextAlignment(COL_LEECHES, alignment);
115  m_LSDItem->setTextAlignment(COL_LEECHES, alignment);
116  m_DHTItem->setTextAlignment(COL_DOWNLOADED, alignment);
117  m_PEXItem->setTextAlignment(COL_DOWNLOADED, alignment);
118  m_LSDItem->setTextAlignment(COL_DOWNLOADED, alignment);
119 
120  // Set header alignment
121  headerItem()->setTextAlignment(COL_TIER, alignment);
122  headerItem()->setTextAlignment(COL_PEERS, alignment);
123  headerItem()->setTextAlignment(COL_SEEDS, alignment);
124  headerItem()->setTextAlignment(COL_LEECHES, alignment);
125  headerItem()->setTextAlignment(COL_DOWNLOADED, alignment);
126 
127  // Set hotkeys
128  const auto *editHotkey = new QShortcut(Qt::Key_F2, this, nullptr, nullptr, Qt::WidgetShortcut);
129  connect(editHotkey, &QShortcut::activated, this, &TrackerListWidget::editSelectedTracker);
130  const auto *deleteHotkey = new QShortcut(QKeySequence::Delete, this, nullptr, nullptr, Qt::WidgetShortcut);
131  connect(deleteHotkey, &QShortcut::activated, this, &TrackerListWidget::deleteSelectedTrackers);
132  const auto *copyHotkey = new QShortcut(QKeySequence::Copy, this, nullptr, nullptr, Qt::WidgetShortcut);
133  connect(copyHotkey, &QShortcut::activated, this, &TrackerListWidget::copyTrackerUrl);
134 
135  connect(this, &QAbstractItemView::doubleClicked, this, &TrackerListWidget::editSelectedTracker);
136 
137  // This hack fixes reordering of first column with Qt5.
138  // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777
139  QTableView unused;
140  unused.setVerticalHeader(header());
141  header()->setParent(this);
142  unused.setVerticalHeader(new QHeaderView(Qt::Horizontal));
143 }
QTreeWidgetItem * m_PEXItem
static QStringList headerLabels()
void displayToggleColumnsMenu(const QPoint &)
PropertiesWidget * m_properties
void showTrackerListMenu(const QPoint &)
int visibleColumnsCount() const
void setRowColor(int row, const QColor &color)
QTreeWidgetItem * m_LSDItem
QTreeWidgetItem * m_DHTItem

References COL_COUNT, COL_DOWNLOADED, COL_LEECHES, COL_PEERS, COL_SEEDS, COL_TIER, COL_URL, copyTrackerUrl(), deleteSelectedTrackers(), displayToggleColumnsMenu(), editSelectedTracker(), headerLabels(), loadSettings(), m_DHTItem, m_LSDItem, m_PEXItem, saveSettings(), setRowColor(), showTrackerListMenu(), and visibleColumnsCount().

Here is the call graph for this function:

◆ ~TrackerListWidget()

TrackerListWidget::~TrackerListWidget ( )

Definition at line 145 of file trackerlistwidget.cpp.

146 {
147  saveSettings();
148 }

References saveSettings().

Here is the call graph for this function:

Member Function Documentation

◆ askForTrackers

void TrackerListWidget::askForTrackers ( )
slot

Definition at line 433 of file trackerlistwidget.cpp.

434 {
436  if (!torrent) return;
437 
438  QVector<BitTorrent::TrackerEntry> trackers;
439  for (const QString &tracker : asConst(TrackersAdditionDialog::askForTrackers(this, torrent)))
440  trackers.append({tracker});
441 
442  torrent->addTrackers(trackers);
443 }
virtual void addTrackers(const QVector< TrackerEntry > &trackers)=0
BitTorrent::Torrent * getCurrentTorrent() const
static QStringList askForTrackers(QWidget *parent, BitTorrent::Torrent *const torrent)
constexpr std::add_const_t< T > & asConst(T &t) noexcept
Definition: global.h:42

References BitTorrent::Torrent::addTrackers(), asConst(), TrackersAdditionDialog::askForTrackers(), PropertiesWidget::getCurrentTorrent(), and m_properties.

Referenced by showTrackerListMenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear

void TrackerListWidget::clear ( )
slot

Definition at line 261 of file trackerlistwidget.cpp.

262 {
263  qDeleteAll(m_trackerItems);
264  m_trackerItems.clear();
265 
266  m_DHTItem->setText(COL_STATUS, "");
267  m_DHTItem->setText(COL_SEEDS, "");
268  m_DHTItem->setText(COL_LEECHES, "");
269  m_DHTItem->setText(COL_MSG, "");
270  m_PEXItem->setText(COL_STATUS, "");
271  m_PEXItem->setText(COL_SEEDS, "");
272  m_PEXItem->setText(COL_LEECHES, "");
273  m_PEXItem->setText(COL_MSG, "");
274  m_LSDItem->setText(COL_STATUS, "");
275  m_LSDItem->setText(COL_SEEDS, "");
276  m_LSDItem->setText(COL_LEECHES, "");
277  m_LSDItem->setText(COL_MSG, "");
278 }
QHash< QString, QTreeWidgetItem * > m_trackerItems

References COL_LEECHES, COL_MSG, COL_SEEDS, COL_STATUS, m_DHTItem, m_LSDItem, m_PEXItem, and m_trackerItems.

Referenced by PropertiesWidget::clear(), deleteSelectedTrackers(), moveSelectionDown(), and moveSelectionUp().

Here is the caller graph for this function:

◆ copyTrackerUrl

void TrackerListWidget::copyTrackerUrl ( )
slot

Definition at line 445 of file trackerlistwidget.cpp.

446 {
447  const QVector<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
448  if (selectedTrackerItems.isEmpty()) return;
449 
450  QStringList urlsToCopy;
451  for (const QTreeWidgetItem *item : selectedTrackerItems)
452  {
453  QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
454  qDebug() << QString("Copy: ") + trackerURL;
455  urlsToCopy << trackerURL;
456  }
457  QApplication::clipboard()->setText(urlsToCopy.join('\n'));
458 }
QVector< QTreeWidgetItem * > getSelectedTrackerItems() const

References COL_URL, and getSelectedTrackerItems().

Referenced by showTrackerListMenu(), and TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ deleteSelectedTrackers

void TrackerListWidget::deleteSelectedTrackers ( )
slot

Definition at line 461 of file trackerlistwidget.cpp.

462 {
464  if (!torrent)
465  {
466  clear();
467  return;
468  }
469 
470  const QVector<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
471  if (selectedTrackerItems.isEmpty()) return;
472 
473  QStringList urlsToRemove;
474  for (const QTreeWidgetItem *item : selectedTrackerItems)
475  {
476  QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
477  urlsToRemove << trackerURL;
478  m_trackerItems.remove(trackerURL);
479  delete item;
480  }
481 
482  // Iterate over the trackers and remove the selected ones
483  const QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers();
484  QVector<BitTorrent::TrackerEntry> remainingTrackers;
485  remainingTrackers.reserve(trackers.size());
486 
487  for (const BitTorrent::TrackerEntry &entry : trackers)
488  {
489  if (!urlsToRemove.contains(entry.url))
490  remainingTrackers.push_back(entry);
491  }
492 
493  torrent->replaceTrackers(remainingTrackers);
494 
495  if (!torrent->isPaused())
496  torrent->forceReannounce();
497 }
virtual void forceReannounce(int index=-1)=0
virtual bool isPaused() const =0
virtual QVector< TrackerEntry > trackers() const =0
virtual void replaceTrackers(const QVector< TrackerEntry > &trackers)=0
Definition: trackerentry.h:38

References clear(), COL_URL, BitTorrent::Torrent::forceReannounce(), PropertiesWidget::getCurrentTorrent(), getSelectedTrackerItems(), BitTorrent::Torrent::isPaused(), m_properties, m_trackerItems, BitTorrent::Torrent::replaceTrackers(), and BitTorrent::Torrent::trackers().

Referenced by showTrackerListMenu(), and TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ displayToggleColumnsMenu

void TrackerListWidget::displayToggleColumnsMenu ( const QPoint &  )
slot

Definition at line 654 of file trackerlistwidget.cpp.

655 {
656  QMenu *menu = new QMenu(this);
657  menu->setAttribute(Qt::WA_DeleteOnClose);
658  menu->setTitle(tr("Column visibility"));
659 
660  for (int i = 0; i < COL_COUNT; ++i)
661  {
662  QAction *myAct = menu->addAction(headerLabels().at(i));
663  myAct->setCheckable(true);
664  myAct->setChecked(!isColumnHidden(i));
665  myAct->setData(i);
666  }
667 
668  connect(menu, &QMenu::triggered, this, [this](const QAction *action)
669  {
670  const int col = action->data().toInt();
671  Q_ASSERT(visibleColumnsCount() > 0);
672 
673  if (!isColumnHidden(col) && (visibleColumnsCount() == 1))
674  return;
675 
676  setColumnHidden(col, !isColumnHidden(col));
677 
678  if (!isColumnHidden(col) && (columnWidth(col) <= 5))
679  resizeColumnToContents(col);
680 
681  saveSettings();
682  });
683 
684  menu->popup(QCursor::pos());
685 }
action
Definition: tstool.py:143

References tstool::action, COL_COUNT, headerLabels(), saveSettings(), and visibleColumnsCount().

Referenced by TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ editSelectedTracker

void TrackerListWidget::editSelectedTracker ( )
slot

Definition at line 499 of file trackerlistwidget.cpp.

500 {
502  if (!torrent) return;
503 
504  const QVector<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
505  if (selectedTrackerItems.isEmpty()) return;
506 
507  // During multi-select only process item selected last
508  const QUrl trackerURL = selectedTrackerItems.last()->text(COL_URL);
509 
510  bool ok = false;
511  const QUrl newTrackerURL = AutoExpandableDialog::getText(this, tr("Tracker editing"), tr("Tracker URL:"),
512  QLineEdit::Normal, trackerURL.toString(), &ok).trimmed();
513  if (!ok) return;
514 
515  if (!newTrackerURL.isValid())
516  {
517  QMessageBox::warning(this, tr("Tracker editing failed"), tr("The tracker URL entered is invalid."));
518  return;
519  }
520  if (newTrackerURL == trackerURL) return;
521 
522  QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers();
523  bool match = false;
524  for (BitTorrent::TrackerEntry &entry : trackers)
525  {
526  if (newTrackerURL == QUrl(entry.url))
527  {
528  QMessageBox::warning(this, tr("Tracker editing failed"), tr("The tracker URL already exists."));
529  return;
530  }
531 
532  if (!match && (trackerURL == QUrl(entry.url)))
533  {
534  match = true;
535  entry.url = newTrackerURL.toString();
536  }
537  }
538 
539  torrent->replaceTrackers(trackers);
540 
541  if (!torrent->isPaused())
542  torrent->forceReannounce();
543 }
static QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode=QLineEdit::Normal, const QString &text={}, bool *ok=nullptr, bool excludeExtension=false, Qt::InputMethodHints inputMethodHints=Qt::ImhNone)

References COL_URL, BitTorrent::Torrent::forceReannounce(), PropertiesWidget::getCurrentTorrent(), getSelectedTrackerItems(), AutoExpandableDialog::getText(), BitTorrent::Torrent::isPaused(), m_properties, BitTorrent::Torrent::replaceTrackers(), and BitTorrent::Torrent::trackers().

Referenced by showTrackerListMenu(), and TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getSelectedTrackerItems()

QVector< QTreeWidgetItem * > TrackerListWidget::getSelectedTrackerItems ( ) const
protected

Definition at line 150 of file trackerlistwidget.cpp.

151 {
152  const QList<QTreeWidgetItem *> selectedTrackerItems = selectedItems();
153  QVector<QTreeWidgetItem *> selectedTrackers;
154  selectedTrackers.reserve(selectedTrackerItems.size());
155 
156  for (QTreeWidgetItem *item : selectedTrackerItems)
157  {
158  if (indexOfTopLevelItem(item) >= NB_STICKY_ITEM) // Ignore STICKY ITEMS
159  selectedTrackers << item;
160  }
161 
162  return selectedTrackers;
163 }
#define NB_STICKY_ITEM

References NB_STICKY_ITEM.

Referenced by copyTrackerUrl(), deleteSelectedTrackers(), editSelectedTracker(), moveSelectionDown(), moveSelectionUp(), and showTrackerListMenu().

Here is the caller graph for this function:

◆ headerLabels()

QStringList TrackerListWidget::headerLabels ( )
staticprivate

Definition at line 627 of file trackerlistwidget.cpp.

628 {
629  return
630  {
631  tr("Tier")
632  , tr("URL")
633  , tr("Status")
634  , tr("Peers")
635  , tr("Seeds")
636  , tr("Leeches")
637  , tr("Downloaded")
638  , tr("Message")
639  };
640 }

Referenced by displayToggleColumnsMenu(), and TrackerListWidget().

Here is the caller graph for this function:

◆ loadSettings

void TrackerListWidget::loadSettings ( )
slot

Definition at line 617 of file trackerlistwidget.cpp.

618 {
619  header()->restoreState(Preferences::instance()->getPropTrackerListState());
620 }
static Preferences * instance()

References Preferences::instance().

Referenced by TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ loadStickyItems

void TrackerListWidget::loadStickyItems ( const BitTorrent::Torrent torrent)
slot

Definition at line 280 of file trackerlistwidget.cpp.

281 {
282  const QString working {tr("Working")};
283  const QString disabled {tr("Disabled")};
284  const QString torrentDisabled {tr("Disabled for this torrent")};
285  const auto *session = BitTorrent::Session::instance();
286 
287  // load DHT information
288  if (torrent->isPrivate() || torrent->isDHTDisabled())
289  m_DHTItem->setText(COL_STATUS, torrentDisabled);
290  else if (!session->isDHTEnabled())
291  m_DHTItem->setText(COL_STATUS, disabled);
292  else
293  m_DHTItem->setText(COL_STATUS, working);
294 
295  // Load PeX Information
296  if (torrent->isPrivate() || torrent->isPEXDisabled())
297  m_PEXItem->setText(COL_STATUS, torrentDisabled);
298  else if (!session->isPeXEnabled())
299  m_PEXItem->setText(COL_STATUS, disabled);
300  else
301  m_PEXItem->setText(COL_STATUS, working);
302 
303  // Load LSD Information
304  if (torrent->isPrivate() || torrent->isLSDDisabled())
305  m_LSDItem->setText(COL_STATUS, torrentDisabled);
306  else if (!session->isLSDEnabled())
307  m_LSDItem->setText(COL_STATUS, disabled);
308  else
309  m_LSDItem->setText(COL_STATUS, working);
310 
311  if (torrent->isPrivate())
312  {
313  QString privateMsg = tr("This torrent is private");
314  m_DHTItem->setText(COL_MSG, privateMsg);
315  m_PEXItem->setText(COL_MSG, privateMsg);
316  m_LSDItem->setText(COL_MSG, privateMsg);
317  }
318 
319  // XXX: libtorrent should provide this info...
320  // Count peers from DHT, PeX, LSD
321  uint seedsDHT = 0, seedsPeX = 0, seedsLSD = 0, peersDHT = 0, peersPeX = 0, peersLSD = 0;
322  for (const BitTorrent::PeerInfo &peer : asConst(torrent->peers()))
323  {
324  if (peer.isConnecting()) continue;
325 
326  if (peer.fromDHT())
327  {
328  if (peer.isSeed())
329  ++seedsDHT;
330  else
331  ++peersDHT;
332  }
333  if (peer.fromPeX())
334  {
335  if (peer.isSeed())
336  ++seedsPeX;
337  else
338  ++peersPeX;
339  }
340  if (peer.fromLSD())
341  {
342  if (peer.isSeed())
343  ++seedsLSD;
344  else
345  ++peersLSD;
346  }
347  }
348 
349  m_DHTItem->setText(COL_SEEDS, QString::number(seedsDHT));
350  m_DHTItem->setText(COL_LEECHES, QString::number(peersDHT));
351  m_PEXItem->setText(COL_SEEDS, QString::number(seedsPeX));
352  m_PEXItem->setText(COL_LEECHES, QString::number(peersPeX));
353  m_LSDItem->setText(COL_SEEDS, QString::number(seedsLSD));
354  m_LSDItem->setText(COL_LEECHES, QString::number(peersLSD));
355 }
static Session * instance()
Definition: session.cpp:997
virtual QVector< PeerInfo > peers() const =0
virtual bool isDHTDisabled() const =0
virtual bool isPEXDisabled() const =0
virtual bool isLSDDisabled() const =0
virtual bool isPrivate() const =0

References asConst(), COL_LEECHES, COL_MSG, COL_SEEDS, COL_STATUS, BitTorrent::Session::instance(), BitTorrent::Torrent::isDHTDisabled(), BitTorrent::Torrent::isLSDDisabled(), BitTorrent::Torrent::isPEXDisabled(), BitTorrent::Torrent::isPrivate(), m_DHTItem, m_LSDItem, m_PEXItem, and BitTorrent::Torrent::peers().

Referenced by loadTrackers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ loadTrackers

void TrackerListWidget::loadTrackers ( )
slot

Definition at line 357 of file trackerlistwidget.cpp.

358 {
359  // Load trackers from torrent handle
361  if (!torrent) return;
362 
363  loadStickyItems(torrent);
364 
365  // Load actual trackers information
366  QStringList oldTrackerURLs = m_trackerItems.keys();
367 
368  for (const BitTorrent::TrackerEntry &entry : asConst(torrent->trackers()))
369  {
370  const QString trackerURL = entry.url;
371 
372  QTreeWidgetItem *item = m_trackerItems.value(trackerURL, nullptr);
373  if (!item)
374  {
375  item = new QTreeWidgetItem();
376  item->setText(COL_URL, trackerURL);
377  item->setToolTip(COL_URL, trackerURL);
378  addTopLevelItem(item);
379  m_trackerItems[trackerURL] = item;
380  }
381  else
382  {
383  oldTrackerURLs.removeOne(trackerURL);
384  }
385 
386  item->setText(COL_TIER, QString::number(entry.tier));
387 
388  switch (entry.status)
389  {
391  item->setText(COL_STATUS, tr("Working"));
392  break;
394  item->setText(COL_STATUS, tr("Updating..."));
395  break;
397  item->setText(COL_STATUS, tr("Not working"));
398  break;
400  item->setText(COL_STATUS, tr("Not contacted yet"));
401  break;
402  }
403 
404  item->setText(COL_MSG, entry.message);
405  item->setToolTip(COL_MSG, entry.message);
406  item->setText(COL_PEERS, ((entry.numPeers > -1)
407  ? QString::number(entry.numPeers)
408  : tr("N/A")));
409  item->setText(COL_SEEDS, ((entry.numSeeds > -1)
410  ? QString::number(entry.numSeeds)
411  : tr("N/A")));
412  item->setText(COL_LEECHES, ((entry.numLeeches > -1)
413  ? QString::number(entry.numLeeches)
414  : tr("N/A")));
415  item->setText(COL_DOWNLOADED, ((entry.numDownloaded > -1)
416  ? QString::number(entry.numDownloaded)
417  : tr("N/A")));
418 
419  const Qt::Alignment alignment = (Qt::AlignRight | Qt::AlignVCenter);
420  item->setTextAlignment(COL_TIER, alignment);
421  item->setTextAlignment(COL_PEERS, alignment);
422  item->setTextAlignment(COL_SEEDS, alignment);
423  item->setTextAlignment(COL_LEECHES, alignment);
424  item->setTextAlignment(COL_DOWNLOADED, alignment);
425  }
426 
427  // Remove old trackers
428  for (const QString &tracker : asConst(oldTrackerURLs))
429  delete m_trackerItems.take(tracker);
430 }
void loadStickyItems(const BitTorrent::Torrent *torrent)
@ Working
Definition: trackerentry.h:42
@ NotWorking
Definition: trackerentry.h:44
@ Updating
Definition: trackerentry.h:43
@ NotContacted
Definition: trackerentry.h:41

References asConst(), COL_DOWNLOADED, COL_LEECHES, COL_MSG, COL_PEERS, COL_SEEDS, COL_STATUS, COL_TIER, COL_URL, PropertiesWidget::getCurrentTorrent(), loadStickyItems(), m_properties, m_trackerItems, BitTorrent::TrackerEntry::NotContacted, BitTorrent::TrackerEntry::NotWorking, BitTorrent::Torrent::trackers(), BitTorrent::TrackerEntry::Updating, and BitTorrent::TrackerEntry::Working.

Referenced by PropertiesWidget::loadDynamicData(), PropertiesWidget::loadTrackers(), and reannounceSelected().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ moveSelectionDown

void TrackerListWidget::moveSelectionDown ( )
slot

Definition at line 217 of file trackerlistwidget.cpp.

218 {
220  if (!torrent)
221  {
222  clear();
223  return;
224  }
225  const QVector<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
226  if (selectedTrackerItems.isEmpty()) return;
227 
228  bool change = false;
229  for (int i = selectedItems().size() - 1; i >= 0; --i)
230  {
231  int index = indexOfTopLevelItem(selectedTrackerItems.at(i));
232  if (index < (topLevelItemCount() - 1))
233  {
234  insertTopLevelItem(index + 1, takeTopLevelItem(index));
235  change = true;
236  }
237  }
238  if (!change) return;
239 
240  // Restore selection
241  QItemSelectionModel *selection = selectionModel();
242  for (QTreeWidgetItem *item : selectedTrackerItems)
243  selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select));
244 
245  setSelectionModel(selection);
246  // Update torrent trackers
247  QVector<BitTorrent::TrackerEntry> trackers;
248  trackers.reserve(topLevelItemCount());
249  for (int i = NB_STICKY_ITEM; i < topLevelItemCount(); ++i)
250  {
251  const QString trackerURL = topLevelItem(i)->data(COL_URL, Qt::DisplayRole).toString();
252  trackers.append({trackerURL, (i - NB_STICKY_ITEM)});
253  }
254 
255  torrent->replaceTrackers(trackers);
256  // Reannounce
257  if (!torrent->isPaused())
258  torrent->forceReannounce();
259 }

References clear(), COL_URL, BitTorrent::Torrent::forceReannounce(), PropertiesWidget::getCurrentTorrent(), getSelectedTrackerItems(), BitTorrent::Torrent::isPaused(), m_properties, NB_STICKY_ITEM, and BitTorrent::Torrent::replaceTrackers().

Referenced by PropertiesWidget::PropertiesWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ moveSelectionUp

void TrackerListWidget::moveSelectionUp ( )
slot

Definition at line 173 of file trackerlistwidget.cpp.

174 {
176  if (!torrent)
177  {
178  clear();
179  return;
180  }
181  const QVector<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
182  if (selectedTrackerItems.isEmpty()) return;
183 
184  bool change = false;
185  for (QTreeWidgetItem *item : selectedTrackerItems)
186  {
187  int index = indexOfTopLevelItem(item);
188  if (index > NB_STICKY_ITEM)
189  {
190  insertTopLevelItem(index - 1, takeTopLevelItem(index));
191  change = true;
192  }
193  }
194  if (!change) return;
195 
196  // Restore selection
197  QItemSelectionModel *selection = selectionModel();
198  for (QTreeWidgetItem *item : selectedTrackerItems)
199  selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select));
200 
201  setSelectionModel(selection);
202  // Update torrent trackers
203  QVector<BitTorrent::TrackerEntry> trackers;
204  trackers.reserve(topLevelItemCount());
205  for (int i = NB_STICKY_ITEM; i < topLevelItemCount(); ++i)
206  {
207  const QString trackerURL = topLevelItem(i)->data(COL_URL, Qt::DisplayRole).toString();
208  trackers.append({trackerURL, (i - NB_STICKY_ITEM)});
209  }
210 
211  torrent->replaceTrackers(trackers);
212  // Reannounce
213  if (!torrent->isPaused())
214  torrent->forceReannounce();
215 }

References clear(), COL_URL, BitTorrent::Torrent::forceReannounce(), PropertiesWidget::getCurrentTorrent(), getSelectedTrackerItems(), BitTorrent::Torrent::isPaused(), m_properties, NB_STICKY_ITEM, and BitTorrent::Torrent::replaceTrackers().

Referenced by PropertiesWidget::PropertiesWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reannounceSelected

void TrackerListWidget::reannounceSelected ( )
slot

Definition at line 545 of file trackerlistwidget.cpp.

546 {
547  const QList<QTreeWidgetItem *> selItems = selectedItems();
548  if (selItems.isEmpty()) return;
549 
551  if (!torrent) return;
552 
553  const QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers();
554 
555  for (const QTreeWidgetItem *item : selItems)
556  {
557  // DHT case
558  if (item == m_DHTItem)
559  {
560  torrent->forceDHTAnnounce();
561  continue;
562  }
563 
564  // Trackers case
565  for (int i = 0; i < trackers.size(); ++i)
566  {
567  if (item->text(COL_URL) == trackers[i].url)
568  {
569  torrent->forceReannounce(i);
570  break;
571  }
572  }
573  }
574 
575  loadTrackers();
576 }
virtual void forceDHTAnnounce()=0

References COL_URL, BitTorrent::Torrent::forceDHTAnnounce(), BitTorrent::Torrent::forceReannounce(), PropertiesWidget::getCurrentTorrent(), loadTrackers(), m_DHTItem, m_properties, and BitTorrent::Torrent::trackers().

Referenced by showTrackerListMenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ saveSettings

void TrackerListWidget::saveSettings ( ) const
slot

Definition at line 622 of file trackerlistwidget.cpp.

623 {
624  Preferences::instance()->setPropTrackerListState(header()->saveState());
625 }
void setPropTrackerListState(const QByteArray &state)

References Preferences::instance(), and Preferences::setPropTrackerListState().

Referenced by displayToggleColumnsMenu(), TrackerListWidget(), and ~TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setRowColor

void TrackerListWidget::setRowColor ( int  row,
const QColor &  color 
)
slot

Definition at line 165 of file trackerlistwidget.cpp.

166 {
167  const int nbColumns = columnCount();
168  QTreeWidgetItem *item = topLevelItem(row);
169  for (int i = 0; i < nbColumns; ++i)
170  item->setData(i, Qt::ForegroundRole, color);
171 }

Referenced by TrackerListWidget().

Here is the caller graph for this function:

◆ showTrackerListMenu

void TrackerListWidget::showTrackerListMenu ( const QPoint &  )
slot

Definition at line 578 of file trackerlistwidget.cpp.

579 {
581  if (!torrent) return;
582 
583  QMenu *menu = new QMenu(this);
584  menu->setAttribute(Qt::WA_DeleteOnClose);
585 
586  // Add actions
587  menu->addAction(UIThemeManager::instance()->getIcon("list-add"), tr("Add a new tracker...")
589 
590  if (!getSelectedTrackerItems().isEmpty())
591  {
592  menu->addAction(UIThemeManager::instance()->getIcon("edit-rename"),tr("Edit tracker URL...")
594  menu->addAction(UIThemeManager::instance()->getIcon("list-remove"), tr("Remove tracker")
596  menu->addAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Copy tracker URL")
598  }
599 
600  if (!torrent->isPaused())
601  {
602  menu->addAction(UIThemeManager::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers")
604  menu->addSeparator();
605  menu->addAction(UIThemeManager::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers")
606  , this, [this]()
607  {
609  h->forceReannounce();
610  h->forceDHTAnnounce();
611  });
612  }
613 
614  menu->popup(QCursor::pos());
615 }
static UIThemeManager * instance()

References askForTrackers(), copyTrackerUrl(), deleteSelectedTrackers(), editSelectedTracker(), BitTorrent::Torrent::forceDHTAnnounce(), BitTorrent::Torrent::forceReannounce(), PropertiesWidget::getCurrentTorrent(), getSelectedTrackerItems(), UIThemeManager::instance(), BitTorrent::Torrent::isPaused(), m_properties, and reannounceSelected().

Referenced by TrackerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ visibleColumnsCount()

int TrackerListWidget::visibleColumnsCount ( ) const

Definition at line 642 of file trackerlistwidget.cpp.

643 {
644  int visibleCols = 0;
645  for (int i = 0; i < COL_COUNT; ++i)
646  {
647  if (!isColumnHidden(i))
648  ++visibleCols;
649  }
650 
651  return visibleCols;
652 }

References COL_COUNT.

Referenced by displayToggleColumnsMenu(), and TrackerListWidget().

Here is the caller graph for this function:

Member Data Documentation

◆ m_DHTItem

QTreeWidgetItem* TrackerListWidget::m_DHTItem
private

Definition at line 93 of file trackerlistwidget.h.

Referenced by clear(), loadStickyItems(), reannounceSelected(), and TrackerListWidget().

◆ m_LSDItem

QTreeWidgetItem* TrackerListWidget::m_LSDItem
private

Definition at line 95 of file trackerlistwidget.h.

Referenced by clear(), loadStickyItems(), and TrackerListWidget().

◆ m_PEXItem

QTreeWidgetItem* TrackerListWidget::m_PEXItem
private

Definition at line 94 of file trackerlistwidget.h.

Referenced by clear(), loadStickyItems(), and TrackerListWidget().

◆ m_properties

◆ m_trackerItems

QHash<QString, QTreeWidgetItem *> TrackerListWidget::m_trackerItems
private

Definition at line 92 of file trackerlistwidget.h.

Referenced by clear(), deleteSelectedTrackers(), and loadTrackers().


The documentation for this class was generated from the following files: