mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-16 02:03:07 -07:00
- New tracker list (displays tracker status and error/warning messages)
This commit is contained in:
parent
8ada8d33c8
commit
ccdb2a82c3
10 changed files with 235 additions and 439 deletions
|
@ -14,6 +14,7 @@
|
||||||
- FEATURE: Support peer manual ban
|
- FEATURE: Support peer manual ban
|
||||||
- FEATURE: Display total amounts transferred in status bar
|
- FEATURE: Display total amounts transferred in status bar
|
||||||
- FEATURE: Announce to all trackers specified for a torrent (µTorrent behavior)
|
- FEATURE: Announce to all trackers specified for a torrent (µTorrent behavior)
|
||||||
|
- FEATURE: Display trackers status as well as error/warning messages
|
||||||
- FEATURE: Dropped Qt 4.3 support (Qt >= 4.4 is now required)
|
- FEATURE: Dropped Qt 4.3 support (Qt >= 4.4 is now required)
|
||||||
- FEATURE: Added per-torrent super seeding mode (libtorrent >= v0.15 only)
|
- FEATURE: Added per-torrent super seeding mode (libtorrent >= v0.15 only)
|
||||||
- FEATURE: Support for storing symbolic links in .torrent files (libtorrent >= v0.15 only)
|
- FEATURE: Support for storing symbolic links in .torrent files (libtorrent >= v0.15 only)
|
||||||
|
|
|
@ -223,13 +223,6 @@ public:
|
||||||
return qBtPath;
|
return qBtPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fixTrackersTiers(std::vector<announce_entry> trackers) {
|
|
||||||
unsigned int nbTrackers = trackers.size();
|
|
||||||
for(unsigned int i=0; i<nbTrackers; ++i) {
|
|
||||||
trackers[i].tier = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insertion sort, used instead of bubble sort because it is
|
// Insertion sort, used instead of bubble sort because it is
|
||||||
// approx. 5 times faster.
|
// approx. 5 times faster.
|
||||||
template <class T> static void insertSort(QList<QPair<int, T> > &list, const QPair<int, T>& value, Qt::SortOrder sortOrder) {
|
template <class T> static void insertSort(QList<QPair<int, T> > &list, const QPair<int, T>& value, Qt::SortOrder sortOrder) {
|
||||||
|
|
|
@ -479,255 +479,8 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_2">
|
<widget class="QWidget" name="page_trackers">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
<layout class="QVBoxLayout" name="verticalLayout_trackers"/>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="_20">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="_21">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="trackersURLS">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="selectionMode">
|
|
||||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="_22">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="removeTracker_button">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="icons.qrc">
|
|
||||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="addTracker_button">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="icons.qrc">
|
|
||||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="_23">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="riseTracker_button">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="icons.qrc">
|
|
||||||
<normaloff>:/Icons/uparrow.png</normaloff>:/Icons/uparrow.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="lowerTracker_button">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="icons.qrc">
|
|
||||||
<normaloff>:/Icons/downarrow.png</normaloff>:/Icons/downarrow.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="_24">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Current tracker:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="trackerURL">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_5">
|
<widget class="QWidget" name="page_5">
|
||||||
<layout class="QVBoxLayout" name="peerpage_layout"/>
|
<layout class="QVBoxLayout" name="peerpage_layout"/>
|
||||||
|
|
|
@ -45,9 +45,9 @@
|
||||||
#include "realprogressbarthread.h"
|
#include "realprogressbarthread.h"
|
||||||
#include "bittorrent.h"
|
#include "bittorrent.h"
|
||||||
#include "PropListDelegate.h"
|
#include "PropListDelegate.h"
|
||||||
#include "TrackersAdditionDlg.h"
|
|
||||||
#include "TorrentFilesModel.h"
|
#include "TorrentFilesModel.h"
|
||||||
#include "peerlistwidget.h"
|
#include "peerlistwidget.h"
|
||||||
|
#include "trackerlist.h"
|
||||||
|
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
#define DEFAULT_BUTTON_CSS ""
|
#define DEFAULT_BUTTON_CSS ""
|
||||||
|
@ -86,10 +86,6 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, TransferListWidget *transfer
|
||||||
connect(collapseAllButton, SIGNAL(clicked()), filesList, SLOT(collapseAll()));
|
connect(collapseAllButton, SIGNAL(clicked()), filesList, SLOT(collapseAll()));
|
||||||
connect(expandAllButton, SIGNAL(clicked()), filesList, SLOT(expandAll()));
|
connect(expandAllButton, SIGNAL(clicked()), filesList, SLOT(expandAll()));
|
||||||
connect(filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&)));
|
connect(filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&)));
|
||||||
connect(addTracker_button, SIGNAL(clicked()), this, SLOT(askForTracker()));
|
|
||||||
connect(removeTracker_button, SIGNAL(clicked()), this, SLOT(deleteSelectedTrackers()));
|
|
||||||
connect(riseTracker_button, SIGNAL(clicked()), this, SLOT(riseSelectedTracker()));
|
|
||||||
connect(lowerTracker_button, SIGNAL(clicked()), this, SLOT(lowerSelectedTracker()));
|
|
||||||
connect(actionIgnored, SIGNAL(triggered()), this, SLOT(ignoreSelection()));
|
connect(actionIgnored, SIGNAL(triggered()), this, SLOT(ignoreSelection()));
|
||||||
connect(actionNormal, SIGNAL(triggered()), this, SLOT(normalSelection()));
|
connect(actionNormal, SIGNAL(triggered()), this, SLOT(normalSelection()));
|
||||||
connect(actionHigh, SIGNAL(triggered()), this, SLOT(highSelection()));
|
connect(actionHigh, SIGNAL(triggered()), this, SLOT(highSelection()));
|
||||||
|
@ -105,6 +101,9 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, TransferListWidget *transfer
|
||||||
progressBar = new RealProgressBar(this);
|
progressBar = new RealProgressBar(this);
|
||||||
progressBar->setForegroundColor(Qt::blue);
|
progressBar->setForegroundColor(Qt::blue);
|
||||||
ProgressHLayout->insertWidget(1, progressBar);
|
ProgressHLayout->insertWidget(1, progressBar);
|
||||||
|
// Tracker list
|
||||||
|
trackerList = new TrackerList(this);
|
||||||
|
verticalLayout_trackers->addWidget(trackerList);
|
||||||
// Peers list
|
// Peers list
|
||||||
peersList = new PeerListWidget(this);
|
peersList = new PeerListWidget(this);
|
||||||
peerpage_layout->addWidget(peersList);
|
peerpage_layout->addWidget(peersList);
|
||||||
|
@ -113,7 +112,7 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, TransferListWidget *transfer
|
||||||
// Dynamic data refresher
|
// Dynamic data refresher
|
||||||
refreshTimer = new QTimer(this);
|
refreshTimer = new QTimer(this);
|
||||||
connect(refreshTimer, SIGNAL(timeout()), this, SLOT(loadDynamicData()));
|
connect(refreshTimer, SIGNAL(timeout()), this, SLOT(loadDynamicData()));
|
||||||
refreshTimer->start(10000); // 10sec
|
refreshTimer->start(3000); // 3sec
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertiesWidget::~PropertiesWidget() {
|
PropertiesWidget::~PropertiesWidget() {
|
||||||
|
@ -121,6 +120,7 @@ PropertiesWidget::~PropertiesWidget() {
|
||||||
delete refreshTimer;
|
delete refreshTimer;
|
||||||
if(progressBarUpdater)
|
if(progressBarUpdater)
|
||||||
delete progressBarUpdater;
|
delete progressBarUpdater;
|
||||||
|
delete trackerList;
|
||||||
delete peersList;
|
delete peersList;
|
||||||
delete progressBar;
|
delete progressBar;
|
||||||
delete PropListModel;
|
delete PropListModel;
|
||||||
|
@ -166,8 +166,7 @@ void PropertiesWidget::clear() {
|
||||||
hash_lbl->clear();
|
hash_lbl->clear();
|
||||||
comment_lbl->clear();
|
comment_lbl->clear();
|
||||||
incrementalDownload->setChecked(false);
|
incrementalDownload->setChecked(false);
|
||||||
trackersURLS->clear();
|
trackerList->clear();
|
||||||
trackerURL->clear();
|
|
||||||
progressBar->setProgress(QRealArray());
|
progressBar->setProgress(QRealArray());
|
||||||
wasted->clear();
|
wasted->clear();
|
||||||
upTotal->clear();
|
upTotal->clear();
|
||||||
|
@ -214,8 +213,6 @@ void PropertiesWidget::loadTorrentInfos(QTorrentHandle &_h) {
|
||||||
comment_lbl->setText(h.comment());
|
comment_lbl->setText(h.comment());
|
||||||
// Sequential download
|
// Sequential download
|
||||||
incrementalDownload->setChecked(TorrentPersistentData::isSequentialDownload(h.hash()));
|
incrementalDownload->setChecked(TorrentPersistentData::isSequentialDownload(h.hash()));
|
||||||
// Trackers
|
|
||||||
loadTrackers();
|
|
||||||
// URL seeds
|
// URL seeds
|
||||||
loadUrlSeeds();
|
loadUrlSeeds();
|
||||||
// downloaded pieces updater
|
// downloaded pieces updater
|
||||||
|
@ -328,6 +325,11 @@ void PropertiesWidget::loadDynamicData() {
|
||||||
progress_lbl->setText(QString::number(h.progress()*100., 'f', 1)+"%");
|
progress_lbl->setText(QString::number(h.progress()*100., 'f', 1)+"%");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(stackedProperties->currentIndex() == TRACKERS_TAB) {
|
||||||
|
// Trackers
|
||||||
|
trackerList->loadTrackers();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(stackedProperties->currentIndex() == PEERS_TAB) {
|
if(stackedProperties->currentIndex() == PEERS_TAB) {
|
||||||
// Load peers
|
// Load peers
|
||||||
peersList->loadPeers(h);
|
peersList->loadPeers(h);
|
||||||
|
@ -348,41 +350,6 @@ void PropertiesWidget::setIncrementalDownload(int checkboxState) {
|
||||||
TorrentPersistentData::saveSequentialStatus(h);
|
TorrentPersistentData::saveSequentialStatus(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::loadTrackers() {
|
|
||||||
if(!h.is_valid()) return;
|
|
||||||
//Trackers
|
|
||||||
std::vector<announce_entry> trackers = h.trackers();
|
|
||||||
trackersURLS->clear();
|
|
||||||
QHash<QString, QString> errors = BTSession->getTrackersErrors(h.hash());
|
|
||||||
unsigned int nbTrackers = trackers.size();
|
|
||||||
for(unsigned int i=0; i<nbTrackers; ++i){
|
|
||||||
QString current_tracker = misc::toQString(trackers[i].url);
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(current_tracker, trackersURLS);
|
|
||||||
// IsThere any errors ?
|
|
||||||
if(errors.contains(current_tracker)) {
|
|
||||||
item->setForeground(QBrush(QColor("red")));
|
|
||||||
// Set tooltip
|
|
||||||
QString msg="";
|
|
||||||
unsigned int i=0;
|
|
||||||
foreach(QString word, errors[current_tracker].split(" ")) {
|
|
||||||
if(i > 0 && i%5!=1) msg += " ";
|
|
||||||
msg += word;
|
|
||||||
if(i> 0 && i%5==0) msg += "\n";
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
item->setToolTip(msg);
|
|
||||||
} else {
|
|
||||||
item->setForeground(QBrush(QColor("green")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QString tracker = h.current_tracker().trimmed();
|
|
||||||
if(!tracker.isEmpty()){
|
|
||||||
trackerURL->setText(tracker);
|
|
||||||
}else{
|
|
||||||
trackerURL->setText(tr("None - Unreachable?"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertiesWidget::loadUrlSeeds(){
|
void PropertiesWidget::loadUrlSeeds(){
|
||||||
QStringList already_added;
|
QStringList already_added;
|
||||||
listWebSeeds->clear();
|
listWebSeeds->clear();
|
||||||
|
@ -578,30 +545,6 @@ void PropertiesWidget::askWebSeed(){
|
||||||
loadUrlSeeds();
|
loadUrlSeeds();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the user for a new tracker
|
|
||||||
// and add it to the download list
|
|
||||||
// if it is not already in it
|
|
||||||
void PropertiesWidget::askForTracker(){
|
|
||||||
TrackersAddDlg *dlg = new TrackersAddDlg(this);
|
|
||||||
connect(dlg, SIGNAL(TrackersToAdd(QStringList)), this, SLOT(addTrackerList(QStringList)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertiesWidget::addTrackerList(QStringList myTrackers) {
|
|
||||||
// Add the trackers to the list
|
|
||||||
std::vector<announce_entry> trackers = h.trackers();
|
|
||||||
foreach(const QString& tracker, myTrackers) {
|
|
||||||
announce_entry new_tracker(misc::toString(tracker.trimmed().toLocal8Bit().data()));
|
|
||||||
new_tracker.tier = 0; // Will be fixed a bit later
|
|
||||||
trackers.push_back(new_tracker);
|
|
||||||
misc::fixTrackersTiers(trackers);
|
|
||||||
}
|
|
||||||
h.replace_trackers(trackers);
|
|
||||||
h.force_reannounce();
|
|
||||||
// Reload Trackers
|
|
||||||
loadTrackers();
|
|
||||||
BTSession->saveTrackerFile(h.hash());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertiesWidget::deleteSelectedUrlSeeds(){
|
void PropertiesWidget::deleteSelectedUrlSeeds(){
|
||||||
QList<QListWidgetItem *> selectedItems = listWebSeeds->selectedItems();
|
QList<QListWidgetItem *> selectedItems = listWebSeeds->selectedItems();
|
||||||
bool change = false;
|
bool change = false;
|
||||||
|
@ -618,99 +561,6 @@ void PropertiesWidget::deleteSelectedUrlSeeds(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::deleteSelectedTrackers(){
|
|
||||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
|
||||||
if(!selectedItems.size()) return;
|
|
||||||
std::vector<announce_entry> trackers = h.trackers();
|
|
||||||
unsigned int nbTrackers = trackers.size();
|
|
||||||
if(nbTrackers == (unsigned int) selectedItems.size()){
|
|
||||||
QMessageBox::warning(this, tr("qBittorrent"),
|
|
||||||
tr("Trackers list can't be empty."),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
foreach(QListWidgetItem *item, selectedItems){
|
|
||||||
QString url = item->text();
|
|
||||||
for(unsigned int i=0; i<nbTrackers; ++i){
|
|
||||||
if(misc::toQString(trackers.at(i).url) == url){
|
|
||||||
trackers.erase(trackers.begin()+i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.replace_trackers(trackers);
|
|
||||||
h.force_reannounce();
|
|
||||||
// Reload Trackers
|
|
||||||
loadTrackers();
|
|
||||||
BTSession->saveTrackerFile(h.hash());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertiesWidget::riseSelectedTracker(){
|
|
||||||
unsigned int i = 0;
|
|
||||||
std::vector<announce_entry> trackers = h.trackers();
|
|
||||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
|
||||||
bool change = false;
|
|
||||||
unsigned int nbTrackers = trackers.size();
|
|
||||||
foreach(QListWidgetItem *item, selectedItems){
|
|
||||||
QString url = item->text();
|
|
||||||
for(i=0; i<nbTrackers; ++i){
|
|
||||||
if(misc::toQString(trackers.at(i).url) == url){
|
|
||||||
qDebug("Asked to rise %s", trackers.at(i).url.c_str());
|
|
||||||
qDebug("its tier was %d and will become %d", trackers[i].tier, trackers[i].tier-1);
|
|
||||||
if(i > 0){
|
|
||||||
announce_entry tmp = trackers[i];
|
|
||||||
trackers[i] = trackers[i-1];
|
|
||||||
trackers[i-1] = tmp;
|
|
||||||
change = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(change){
|
|
||||||
misc::fixTrackersTiers(trackers);
|
|
||||||
h.replace_trackers(trackers);
|
|
||||||
h.force_reannounce();
|
|
||||||
// Reload Trackers
|
|
||||||
loadTrackers();
|
|
||||||
trackersURLS->item(i-1)->setSelected(true);
|
|
||||||
BTSession->saveTrackerFile(h.hash());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertiesWidget::lowerSelectedTracker(){
|
|
||||||
unsigned int i = 0;
|
|
||||||
std::vector<announce_entry> trackers = h.trackers();
|
|
||||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
|
||||||
bool change = false;
|
|
||||||
unsigned int nbTrackers = trackers.size();
|
|
||||||
foreach(QListWidgetItem *item, selectedItems){
|
|
||||||
QString url = item->text();
|
|
||||||
for(i=0; i<nbTrackers; ++i){
|
|
||||||
if(misc::toQString(trackers.at(i).url) == url){
|
|
||||||
qDebug("Asked to lower %s", trackers.at(i).url.c_str());
|
|
||||||
qDebug("its tier was %d and will become %d", trackers[i].tier, trackers[i].tier+1);
|
|
||||||
if(i < nbTrackers-1){
|
|
||||||
announce_entry tmp = trackers[i];
|
|
||||||
trackers[i] = trackers[i+1];
|
|
||||||
trackers[i+1] = tmp;
|
|
||||||
change = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(change){
|
|
||||||
misc::fixTrackersTiers(trackers);
|
|
||||||
h.replace_trackers(trackers);
|
|
||||||
h.force_reannounce();
|
|
||||||
// Reload Trackers
|
|
||||||
loadTrackers();
|
|
||||||
trackersURLS->item(i+1)->setSelected(true);
|
|
||||||
BTSession->saveTrackerFile(h.hash());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PropertiesWidget::savePiecesPriorities() {
|
bool PropertiesWidget::savePiecesPriorities() {
|
||||||
qDebug("Saving pieces priorities");
|
qDebug("Saving pieces priorities");
|
||||||
std::vector<int> priorities = PropListModel->getFilesPriorities(h.get_torrent_info().num_files());
|
std::vector<int> priorities = PropListModel->getFilesPriorities(h.get_torrent_info().num_files());
|
||||||
|
|
|
@ -46,6 +46,7 @@ class PropListDelegate;
|
||||||
class QAction;
|
class QAction;
|
||||||
class torrent_file;
|
class torrent_file;
|
||||||
class PeerListWidget;
|
class PeerListWidget;
|
||||||
|
class TrackerList;
|
||||||
|
|
||||||
enum Tab {MAIN_TAB, TRACKERS_TAB, PEERS_TAB, URLSEEDS_TAB, FILES_TAB};
|
enum Tab {MAIN_TAB, TRACKERS_TAB, PEERS_TAB, URLSEEDS_TAB, FILES_TAB};
|
||||||
enum SlideState {REDUCED, VISIBLE};
|
enum SlideState {REDUCED, VISIBLE};
|
||||||
|
@ -64,6 +65,7 @@ private:
|
||||||
TorrentFilesModel *PropListModel;
|
TorrentFilesModel *PropListModel;
|
||||||
PropListDelegate *PropDelegate;
|
PropListDelegate *PropDelegate;
|
||||||
PeerListWidget *peersList;
|
PeerListWidget *peersList;
|
||||||
|
TrackerList *trackerList;
|
||||||
QAction *actionIgnored;
|
QAction *actionIgnored;
|
||||||
QAction *actionNormal;
|
QAction *actionNormal;
|
||||||
QAction *actionMaximum;
|
QAction *actionMaximum;
|
||||||
|
@ -79,7 +81,6 @@ protected slots:
|
||||||
void loadTorrentInfos(QTorrentHandle &h);
|
void loadTorrentInfos(QTorrentHandle &h);
|
||||||
void loadDynamicData();
|
void loadDynamicData();
|
||||||
void setIncrementalDownload(int checkboxState);
|
void setIncrementalDownload(int checkboxState);
|
||||||
void loadTrackers();
|
|
||||||
void loadUrlSeeds();
|
void loadUrlSeeds();
|
||||||
void on_main_infos_button_clicked();
|
void on_main_infos_button_clicked();
|
||||||
void on_trackers_button_clicked();
|
void on_trackers_button_clicked();
|
||||||
|
@ -92,13 +93,8 @@ protected slots:
|
||||||
void maximumSelection();
|
void maximumSelection();
|
||||||
void askWebSeed();
|
void askWebSeed();
|
||||||
void deleteSelectedUrlSeeds();
|
void deleteSelectedUrlSeeds();
|
||||||
void askForTracker();
|
|
||||||
void deleteSelectedTrackers();
|
|
||||||
void lowerSelectedTracker();
|
|
||||||
void riseSelectedTracker();
|
|
||||||
void displayFilesListMenu(const QPoint& pos);
|
void displayFilesListMenu(const QPoint& pos);
|
||||||
void on_changeSavePathButton_clicked();
|
void on_changeSavePathButton_clicked();
|
||||||
void addTrackerList(QStringList myTrackers);
|
|
||||||
void filteredFilesChanged();
|
void filteredFilesChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -522,6 +522,11 @@ void QTorrentHandle::set_peer_download_limit(asio::ip::tcp::endpoint ip, int lim
|
||||||
h.set_peer_download_limit(ip, limit);
|
h.set_peer_download_limit(ip, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QTorrentHandle::add_tracker(announce_entry const& url) {
|
||||||
|
Q_ASSERT(h.is_valid());
|
||||||
|
h.add_tracker(url);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Operators
|
// Operators
|
||||||
//
|
//
|
||||||
|
|
|
@ -153,6 +153,7 @@ class QTorrentHandle {
|
||||||
void connect_peer(asio::ip::tcp::endpoint const& adr, int source = 0) const;
|
void connect_peer(asio::ip::tcp::endpoint const& adr, int source = 0) const;
|
||||||
void set_peer_upload_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
void set_peer_upload_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
||||||
void set_peer_download_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
void set_peer_download_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
||||||
|
void add_tracker(announce_entry const& url);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Operators
|
// Operators
|
||||||
|
|
|
@ -173,7 +173,7 @@ HEADERS += GUI.h \
|
||||||
json.h \
|
json.h \
|
||||||
eventmanager.h \
|
eventmanager.h \
|
||||||
filterParserThread.h \
|
filterParserThread.h \
|
||||||
TrackersAdditionDlg.h \
|
trackersadditiondlg.h \
|
||||||
searchTab.h \
|
searchTab.h \
|
||||||
console_imp.h \
|
console_imp.h \
|
||||||
ico.h \
|
ico.h \
|
||||||
|
@ -195,7 +195,8 @@ HEADERS += GUI.h \
|
||||||
geoip.h \
|
geoip.h \
|
||||||
peeraddition.h \
|
peeraddition.h \
|
||||||
deletionconfirmationdlg.h \
|
deletionconfirmationdlg.h \
|
||||||
statusbar.h
|
statusbar.h \
|
||||||
|
trackerlist.h
|
||||||
FORMS += MainWindow.ui \
|
FORMS += MainWindow.ui \
|
||||||
options.ui \
|
options.ui \
|
||||||
about.ui \
|
about.ui \
|
||||||
|
|
196
src/trackerlist.h
Normal file
196
src/trackerlist.h
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
|
* Copyright (C) 2006 Christophe Dumez
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*
|
||||||
|
* Contact : chris@qbittorrent.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRACKERLIST_H
|
||||||
|
#define TRACKERLIST_H
|
||||||
|
|
||||||
|
#include <QTreeWidget>
|
||||||
|
#include <QTreeWidgetItem>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QAction>
|
||||||
|
#include "propertieswidget.h"
|
||||||
|
#include "trackersadditiondlg.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "bittorrent.h"
|
||||||
|
|
||||||
|
enum TrackerListColumn {COL_URL, COL_STATUS, COL_MSG};
|
||||||
|
|
||||||
|
class TrackerList: public QTreeWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
PropertiesWidget *properties;
|
||||||
|
QHash<QString, QTreeWidgetItem*> tracker_items;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TrackerList(PropertiesWidget *properties): QTreeWidget(), properties(properties) {
|
||||||
|
// Graphical settings
|
||||||
|
setRootIsDecorated(false);
|
||||||
|
setAllColumnsShowFocus(true);
|
||||||
|
setItemsExpandable(false);
|
||||||
|
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
// Context menu
|
||||||
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTrackerListMenu(QPoint)));
|
||||||
|
// Set header
|
||||||
|
QStringList header;
|
||||||
|
header << tr("URL");
|
||||||
|
header << tr("Status");
|
||||||
|
header << tr("Message");
|
||||||
|
setHeaderItem(new QTreeWidgetItem(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
~TrackerList() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void loadTrackers() {
|
||||||
|
QStringList old_trackers_urls = tracker_items.keys();
|
||||||
|
// Load trackers from torrent handle
|
||||||
|
QTorrentHandle h = properties->getCurrentTorrent();
|
||||||
|
if(!h.is_valid()) return;
|
||||||
|
QHash<QString, QString> errors = properties->getBTSession()->getTrackersErrors(h.hash());
|
||||||
|
std::vector<announce_entry> trackers = h.trackers();
|
||||||
|
std::vector<announce_entry>::iterator it;
|
||||||
|
for(it = trackers.begin(); it != trackers.end(); it++) {
|
||||||
|
QStringList item_list;
|
||||||
|
QString tracker_url = misc::toQString((*it).url);
|
||||||
|
QTreeWidgetItem *item = tracker_items.value(tracker_url, 0);
|
||||||
|
if(!item) {
|
||||||
|
item = new QTreeWidgetItem();
|
||||||
|
item->setText(COL_URL, tracker_url);
|
||||||
|
addTopLevelItem(item);
|
||||||
|
tracker_items[tracker_url] = item;
|
||||||
|
} else {
|
||||||
|
old_trackers_urls.removeOne(tracker_url);
|
||||||
|
}
|
||||||
|
if((*it).verified) {
|
||||||
|
item->setText(COL_STATUS, tr("Working"));
|
||||||
|
} else {
|
||||||
|
if((*it).updating) {
|
||||||
|
item->setText(COL_STATUS, tr("Updating..."));
|
||||||
|
} else {
|
||||||
|
if((*it).fails > 0) {
|
||||||
|
item->setText(COL_STATUS, tr("Not working"));
|
||||||
|
} else {
|
||||||
|
item->setText(COL_STATUS, tr("Not contacted yet"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item->setText(COL_MSG, errors.value(tracker_url, ""));
|
||||||
|
}
|
||||||
|
// Remove old trackers
|
||||||
|
foreach(const QString &tracker, old_trackers_urls) {
|
||||||
|
delete tracker_items.take(tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask the user for new trackers and add them to the torrent
|
||||||
|
void askForTrackers(){
|
||||||
|
QStringList trackers = TrackersAdditionDlg::asForTrackers();
|
||||||
|
if(!trackers.empty()) {
|
||||||
|
QTorrentHandle h = properties->getCurrentTorrent();
|
||||||
|
if(!h.is_valid()) return;
|
||||||
|
foreach(const QString& tracker, trackers) {
|
||||||
|
announce_entry url(tracker.toStdString());
|
||||||
|
url.tier = 0;
|
||||||
|
h.add_tracker(url);
|
||||||
|
}
|
||||||
|
// Reannounce to new trackers
|
||||||
|
h.force_reannounce();
|
||||||
|
// Reload tracker list
|
||||||
|
loadTrackers();
|
||||||
|
// XXX: I don't think this is necessary now
|
||||||
|
//BTSession->saveTrackerFile(h.hash());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteSelectedTrackers(){
|
||||||
|
QTorrentHandle h = properties->getCurrentTorrent();
|
||||||
|
if(!h.is_valid()) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QList<QTreeWidgetItem *> selected_items = selectedItems();
|
||||||
|
if(selected_items.isEmpty()) return;
|
||||||
|
QStringList urls_to_remove;
|
||||||
|
foreach(QTreeWidgetItem *item, selected_items){
|
||||||
|
QString tracker_url = item->data(COL_URL, Qt::DisplayRole).toString();
|
||||||
|
urls_to_remove << tracker_url;
|
||||||
|
tracker_items.remove(tracker_url);
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
// Iterate of trackers and remove selected ones
|
||||||
|
std::vector<announce_entry> trackers = h.trackers();
|
||||||
|
std::vector<announce_entry>::iterator it = trackers.begin();
|
||||||
|
while(it != trackers.end()) {
|
||||||
|
int index = urls_to_remove.indexOf(misc::toQString((*it).url));
|
||||||
|
if(index >= 0) {
|
||||||
|
trackers.erase(it);
|
||||||
|
urls_to_remove.removeAt(index);
|
||||||
|
} else {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h.replace_trackers(trackers);
|
||||||
|
h.force_reannounce();
|
||||||
|
// Reload Trackers
|
||||||
|
loadTrackers();
|
||||||
|
//XXX: I don't think this is necessary
|
||||||
|
//BTSession->saveTrackerFile(h.hash());
|
||||||
|
}
|
||||||
|
|
||||||
|
void showTrackerListMenu(QPoint) {
|
||||||
|
QList<QTreeWidgetItem*> selected_items = selectedItems();
|
||||||
|
QMenu menu;
|
||||||
|
// Add actions
|
||||||
|
QAction *addAct = menu.addAction(QIcon(":/Icons/oxygen/list-add.png"), tr("Add a new tracker"));
|
||||||
|
QAction *delAct = 0;
|
||||||
|
if(!selectedItems().isEmpty()) {
|
||||||
|
delAct = menu.addAction(QIcon(":/Icons/oxygen/list-remove.png"), "Remove tracker");
|
||||||
|
}
|
||||||
|
QAction *act = menu.exec(QCursor::pos());
|
||||||
|
if(act == addAct) {
|
||||||
|
askForTrackers();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(act == delAct) {
|
||||||
|
deleteSelectedTrackers();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRACKERLIST_H
|
|
@ -35,27 +35,27 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include "ui_trackersAdd.h"
|
#include "ui_trackersAdd.h"
|
||||||
|
|
||||||
class TrackersAddDlg : public QDialog, private Ui::TrackersAdditionDlg{
|
class TrackersAdditionDlg : public QDialog, private Ui::TrackersAdditionDlg{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TrackersAddDlg(QWidget *parent): QDialog(parent){
|
TrackersAdditionDlg(QWidget *parent=0): QDialog(parent){
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~TrackersAddDlg(){}
|
~TrackersAdditionDlg(){}
|
||||||
|
|
||||||
|
QStringList newTrackers() const {
|
||||||
|
return trackers_list->toPlainText().trimmed().split("\n");
|
||||||
|
}
|
||||||
|
|
||||||
signals:
|
static QStringList asForTrackers() {
|
||||||
void TrackersToAdd(QStringList trackers);
|
QStringList trackers;
|
||||||
|
TrackersAdditionDlg dlg;
|
||||||
public slots:
|
if(dlg.exec() == QDialog::Accepted) {
|
||||||
void on_buttonBox_accepted() {
|
return dlg.newTrackers();
|
||||||
QStringList trackers = trackers_list->toPlainText().trimmed().split("\n");
|
|
||||||
if(trackers.size()) {
|
|
||||||
emit TrackersToAdd(trackers);
|
|
||||||
}
|
}
|
||||||
|
return trackers;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue