diff --git a/src/core/misc.cpp b/src/core/misc.cpp index 16995e322..57bcd8254 100644 --- a/src/core/misc.cpp +++ b/src/core/misc.cpp @@ -389,22 +389,6 @@ QString misc::magnetUriToName(const QString& magnet_uri) return toQStringU(p.name); } -QList misc::magnetUriToTrackers(const QString& magnet_uri) -{ - QList trackers; - add_torrent_params p; - error_code ec; - parse_magnet_uri(magnet_uri.toUtf8().constData(), p, ec); - - if (ec) - return trackers; - - for (std::vector::const_iterator i = p.trackers.begin(), e = p.trackers.end(); i != e; ++i) - trackers.push_back(QUrl(toQStringU(*i))); - - return trackers; -} - QString misc::magnetUriToHash(const QString& magnet_uri) { add_torrent_params p; diff --git a/src/core/misc.h b/src/core/misc.h index 4d7461983..b99d58ae7 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -89,7 +89,6 @@ namespace misc bool isPreviewable(const QString& extension); QString magnetUriToName(const QString& magnet_uri); QString magnetUriToHash(const QString& magnet_uri); - QList magnetUriToTrackers(const QString& magnet_uri); QString bcLinkToMagnet(QString bc_link); // Take a number of seconds and return an user-friendly // time duration like "1d 2h 10m". diff --git a/src/core/qtlibtorrent/qbtsession.cpp b/src/core/qtlibtorrent/qbtsession.cpp index 61e331e53..dec604684 100644 --- a/src/core/qtlibtorrent/qbtsession.cpp +++ b/src/core/qtlibtorrent/qbtsession.cpp @@ -1276,76 +1276,95 @@ void QBtSession::loadTorrentTempData(QTorrentHandle &h, QString savePath, bool m TorrentPersistentData::instance()->saveTorrentPersistentData(h, fsutils::fromNativePath(savePath), magnet); } -void QBtSession::mergeTorrents(QTorrentHandle& h_ex, const QString& magnet_uri) +void QBtSession::mergeTorrents(const QTorrentHandle &h, const QString &magnet_uri) { - QString hash = h_ex.hash(); - QList new_trackers = misc::magnetUriToTrackers(magnet_uri); - bool trackers_added = false; - foreach (const QUrl& new_tracker, new_trackers) { - bool found = false; - std::vector existing_trackers = h_ex.trackers(); - foreach (const announce_entry& existing_tracker, existing_trackers) { - if (new_tracker == QUrl(existing_tracker.url.c_str())) { - found = true; - break; - } - } + QStringList trackers; + QStringList urlSeeds; + add_torrent_params p; + boost::system::error_code ec; - if (!found) { - h_ex.add_tracker(announce_entry(new_tracker.toString().toStdString())); - trackers_added = true; - emit trackerAdded(new_tracker.toString(), hash); - } - } - if (trackers_added) - Logger::instance()->addMessage(tr("Note: new trackers were added to the existing torrent.")); + parse_magnet_uri(magnet_uri.toUtf8().constData(), p, ec); + + for (std::vector::const_iterator i = p.trackers.begin(), e = p.trackers.end(); i != e; ++i) + trackers.push_back(misc::toQStringU(*i)); + +#if LIBTORRENT_VERSION_NUM >= 10000 + for (std::vector::const_iterator i = p.url_seeds.begin(), e = p.url_seeds.end(); i != e; ++i) + urlSeeds.push_back(misc::toQStringU(*i)); +#endif + + mergeTorrents_impl(h, trackers, urlSeeds); } -void QBtSession::mergeTorrents(QTorrentHandle &h_ex, boost::intrusive_ptr t) { - // Check if the torrent contains trackers or url seeds we don't know about - // and add them - QString hash = h_ex.hash(); - if (!h_ex.is_valid()) return; - std::vector existing_trackers = h_ex.trackers(); - std::vector new_trackers = t->trackers(); - bool trackers_added = false; - foreach (const announce_entry& new_tracker, new_trackers) { - std::string new_tracker_url = new_tracker.url; - // Check if existing torrent has this tracker +void QBtSession::mergeTorrents(const QTorrentHandle &h, const boost::intrusive_ptr t) { + QStringList trackers; + QStringList urlSeeds; + + foreach (const announce_entry& newTracker, t->trackers()) + trackers.append(misc::toQStringU(newTracker.url)); + + foreach (const web_seed_entry& newUrlSeed, t->web_seeds()) + urlSeeds.append(misc::toQStringU(newUrlSeed.url)); + + mergeTorrents_impl(h, trackers, urlSeeds); +} + +void QBtSession::mergeTorrents_impl(const QTorrentHandle &h, const QStringList &trackers, const QStringList &urlSeeds) +{ + if (!h.is_valid()) + return; + + QString hash = h.hash(); + QString name = h.name(); + QStringList addedTrackers; + const std::vector existingTrackers = h.trackers(); + const QStringList existingUrlSeeds = h.url_seeds(); + + foreach (const QString &tracker, trackers) { + QUrl trackerUrl(tracker); bool found = false; - foreach (const announce_entry& existing_tracker, existing_trackers) { - if (QUrl(new_tracker_url.c_str()) == QUrl(existing_tracker.url.c_str())) { + + foreach (const announce_entry &existingTracker, existingTrackers) { + QUrl existingTrackerUrl(misc::toQStringU(existingTracker.url)); + if (trackerUrl == existingTrackerUrl) { found = true; break; } } if (!found) { - h_ex.add_tracker(announce_entry(new_tracker_url)); - trackers_added = true; - emit trackerAdded(new_tracker_url.c_str(), hash); + h.add_tracker(announce_entry(tracker.toUtf8().constData())); + addedTrackers.append(tracker); + Logger::instance()->addMessage(tr("Tracker '%1' was added to torrent '%2'").arg(tracker).arg(name)); } } - Logger* const logger = Logger::instance(); - if (trackers_added) - logger->addMessage(tr("Note: new trackers were added to the existing torrent.")); + if (!addedTrackers.empty()) + emit trackersAdded(addedTrackers, hash); - bool urlseeds_added = false; - const QStringList old_urlseeds = h_ex.url_seeds(); - std::vector new_urlseeds = t->web_seeds(); + if (existingTrackers.empty() && !h.trackers().empty()) + emit trackerlessChange(false, hash); - std::vector::iterator it = new_urlseeds.begin(); - std::vector::iterator itend = new_urlseeds.end(); - for ( ; it != itend; ++it) { - const QString new_url = misc::toQString(it->url.c_str()); - if (!old_urlseeds.contains(new_url)) { - urlseeds_added = true; - h_ex.add_url_seed(new_url); + foreach (const QString &urlSeed, urlSeeds) { + QUrl urlSeedUrl(urlSeed); + bool found = false; + + foreach (const QString &existingUrlSeed, existingUrlSeeds) { + QUrl existingUrlSeedUrl(existingUrlSeed); + if (urlSeedUrl == existingUrlSeedUrl) { + found = true; + break; + } + } + + if (!found) { + h.add_url_seed(urlSeed); + Logger::instance()->addMessage(tr("URL seed '%1' was added to torrent '%2'").arg(urlSeed).arg(name)); } } - if (urlseeds_added) - logger->addMessage(tr("Note: new URL seeds were added to the existing torrent.")); + + h.force_reannounce(); + emit reloadTrackersAndUrlSeeds(h); } void QBtSession::exportTorrentFiles(QString path) { @@ -3141,3 +3160,11 @@ void QBtSession::unhideMagnet(const QString &hash) { emit addedTorrent(h); } + + +void QBtSession::addTrackersAndUrlSeeds(const QString &hash, const QStringList &trackers, const QStringList& urlSeeds) +{ + QTorrentHandle h = getTorrentHandle(hash); + if (h.is_valid()) + mergeTorrents_impl(h, trackers, urlSeeds); +} diff --git a/src/core/qtlibtorrent/qbtsession.h b/src/core/qtlibtorrent/qbtsession.h index 7618d60ac..bf8294402 100644 --- a/src/core/qtlibtorrent/qbtsession.h +++ b/src/core/qtlibtorrent/qbtsession.h @@ -210,6 +210,7 @@ public slots: void banIP(QString ip); void recursiveTorrentDownload(const QTorrentHandle &h); void unhideMagnet(const QString &hash); + void addTrackersAndUrlSeeds(const QString &hash, const QStringList &trackers, const QStringList& urlSeeds); private: void applyEncryptionSettings(libtorrent::pe_settings se); @@ -258,8 +259,9 @@ private slots: void saveTempFastResumeData(); void sendNotificationEmail(const QTorrentHandle &h); void autoRunExternalProgram(const QTorrentHandle &h); - void mergeTorrents(QTorrentHandle& h_ex, boost::intrusive_ptr t); - void mergeTorrents(QTorrentHandle& h_ex, const QString& magnet_uri); + void mergeTorrents(const QTorrentHandle &h, const boost::intrusive_ptr t); + void mergeTorrents(const QTorrentHandle &h, const QString &magnet_uri); + void mergeTorrents_impl(const QTorrentHandle &h, const QStringList &trackers, const QStringList& urlSeeds); void exportTorrentFile(const QTorrentHandle &h, TorrentExportFolder folder = RegularTorrentExportFolder); void handleIPFilterParsed(int ruleCount); void handleIPFilterError(); @@ -288,7 +290,9 @@ signals: void metadataReceivedHidden(const QTorrentHandle &h); void stateUpdate(const std::vector &statuses); void statsReceived(const libtorrent::stats_alert&); - void trackerAdded(const QString &tracker, const QString &hash); + void trackersAdded(const QStringList &trackers, const QString &hash); + void trackerlessChange(bool trackerless, const QString &hash); + void reloadTrackersAndUrlSeeds(const QTorrentHandle &h); private: // Bittorrent diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 2e1d3a673..60320e287 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -214,9 +214,12 @@ MainWindow::MainWindow(QWidget *parent) connect(search_filter, SIGNAL(textChanged(QString)), transferList, SLOT(applyNameFilter(QString))); connect(hSplitter, SIGNAL(splitterMoved(int, int)), this, SLOT(writeSettings())); connect(vSplitter, SIGNAL(splitterMoved(int, int)), this, SLOT(writeSettings())); - connect(properties, SIGNAL(trackerAdded(const QString&, const QString&)), transferListFilters, SLOT(addTracker(const QString&, const QString&))); - connect(properties, SIGNAL(trackerRemoved(const QString&, const QString&)), transferListFilters, SLOT(removeTracker(const QString&, const QString&))); - connect(QBtSession::instance(), SIGNAL(trackerAdded(const QString&, const QString&)), transferListFilters, SLOT(addTracker(const QString&, const QString&))); + connect(properties, SIGNAL(trackersAdded(const QStringList &, const QString &)), transferListFilters, SLOT(addTrackers(const QStringList &, const QString &))); + connect(properties, SIGNAL(trackersRemoved(const QStringList &, const QString &)), transferListFilters, SLOT(removeTrackers(const QStringList &, const QString &))); + connect(properties, SIGNAL(trackerlessChange(bool, const QString &)), transferListFilters, SLOT(changeTrackerless(bool, const QString &))); + connect(QBtSession::instance(), SIGNAL(trackersAdded(const QStringList &, const QString &)), transferListFilters, SLOT(addTrackers(const QStringList &, const QString &))); + connect(QBtSession::instance(), SIGNAL(trackerlessChange(bool, const QString &)), transferListFilters, SLOT(changeTrackerless(bool, const QString &))); + connect(QBtSession::instance(), SIGNAL(reloadTrackersAndUrlSeeds(const QTorrentHandle &)), properties, SLOT(loadTrackers(const QTorrentHandle &))); vboxLayout->addWidget(tabs); diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index ef7be8798..c34fb0102 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -111,8 +111,9 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow* main_window, Tra trackerList = new TrackerList(this); connect(trackerUpButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionUp())); connect(trackerDownButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionDown())); - connect(trackerList, SIGNAL(trackerAdded(const QString&, const QString&)), this, SIGNAL(trackerAdded(const QString&, const QString&))); - connect(trackerList, SIGNAL(trackerRemoved(const QString&, const QString&)), this, SIGNAL(trackerRemoved(const QString&, const QString&))); + connect(trackerList, SIGNAL(trackersAdded(const QStringList &, const QString &)), this, SIGNAL(trackersAdded(const QStringList &, const QString &))); + connect(trackerList, SIGNAL(trackersRemoved(const QStringList &, const QString &)), this, SIGNAL(trackersRemoved(const QStringList &, const QString &))); + connect(trackerList, SIGNAL(trackerlessChange(bool, const QString &)), this, SIGNAL(trackerlessChange(bool, const QString &))); horizontalLayout_trackers->insertWidget(0, trackerList); connect(trackerList->header(), SIGNAL(sectionMoved(int, int, int)), trackerList, SLOT(saveSettings())); connect(trackerList->header(), SIGNAL(sectionResized(int, int, int)), trackerList, SLOT(saveSettings())); @@ -239,6 +240,12 @@ void PropertiesWidget::updateSavePath(const QTorrentHandle& _h) { } } +void PropertiesWidget::loadTrackers(const QTorrentHandle &handle) +{ + if (handle == h) + trackerList->loadTrackers(); +} + void PropertiesWidget::updateTorrentInfos(const QTorrentHandle& _h) { if (h.is_valid() && h == _h) { loadTorrentInfos(h); diff --git a/src/gui/properties/propertieswidget.h b/src/gui/properties/propertieswidget.h index 5b9a194f4..23cb8c46d 100644 --- a/src/gui/properties/propertieswidget.h +++ b/src/gui/properties/propertieswidget.h @@ -70,8 +70,9 @@ public: QTreeView* getFilesList() const { return filesList; } signals: - void trackerAdded(const QString &tracker, const QString &hash); - void trackerRemoved(const QString &tracker, const QString &hash); + void trackersAdded(const QStringList &trackers, const QString &hash); + void trackersRemoved(const QStringList &trackers, const QString &hash); + void trackerlessChange(bool trackerless, const QString &hash); protected: QPushButton* getButtonFromIndex(int index); @@ -101,6 +102,7 @@ public slots: void reloadPreferences(); void openDoubleClickedFile(const QModelIndex &); void updateSavePath(const QTorrentHandle& h); + void loadTrackers(const QTorrentHandle &handle); private: void openFile(const QModelIndex &index); diff --git a/src/gui/properties/trackerlist.cpp b/src/gui/properties/trackerlist.cpp index 2a1ad3ecc..3910c0258 100644 --- a/src/gui/properties/trackerlist.cpp +++ b/src/gui/properties/trackerlist.cpp @@ -302,24 +302,8 @@ void TrackerList::askForTrackers() { if (!h.is_valid()) return; QString hash = h.hash(); QStringList trackers = TrackersAdditionDlg::askForTrackers(h); - if (!trackers.empty()) { - if (h.trackers().empty()) - emit trackerRemoved("", hash); - - for (int i=0; iaddTrackersAndUrlSeeds(hash, trackers, QStringList()); + loadTrackers(); } void TrackerList::copyTrackerUrl() { @@ -350,7 +334,6 @@ void TrackerList::deleteSelectedTrackers() { urls_to_remove << tracker_url; tracker_items.remove(tracker_url); delete item; - emit trackerRemoved(tracker_url, hash); } // Iterate of trackers and remove selected ones std::vector remaining_trackers; @@ -364,8 +347,10 @@ void TrackerList::deleteSelectedTrackers() { } } h.replace_trackers(remaining_trackers); + if (!urls_to_remove.empty()) + emit trackersRemoved(urls_to_remove, hash); if (remaining_trackers.empty()) - emit trackerAdded("", hash); + emit trackerlessChange(true, hash); if (!h.is_paused()) h.force_reannounce(); // Reload Trackers @@ -407,13 +392,13 @@ void TrackerList::editSelectedTracker() { return; } - if (tracker_url == QUrl(misc::toQString(it->url)) && !match) { - announce_entry new_entry(new_tracker_url.toString().toStdString()); + if (tracker_url == QUrl(misc::toQStringU(it->url)) && !match) { + announce_entry new_entry(new_tracker_url.toString().toUtf8().constData()); new_entry.tier = it->tier; match = true; *it = new_entry; - emit trackerRemoved(tracker_url.toString(), hash); - emit trackerAdded(new_tracker_url.toString(), hash); + emit trackersRemoved(QStringList(tracker_url.toString()), hash); + emit trackersAdded(QStringList(new_tracker_url.toString()), hash); } } diff --git a/src/gui/properties/trackerlist.h b/src/gui/properties/trackerlist.h index 277aaf2e8..d1b01b92e 100644 --- a/src/gui/properties/trackerlist.h +++ b/src/gui/properties/trackerlist.h @@ -61,8 +61,9 @@ public: ~TrackerList(); signals: - void trackerAdded(const QString &tracker, const QString &hash); - void trackerRemoved(const QString &tracker, const QString &hash); + void trackersAdded(const QStringList &trackers, const QString &hash); + void trackersRemoved(const QStringList &trackers, const QString &hash); + void trackerlessChange(bool trackerless, const QString &hash); protected: QList getSelectedTrackerItems() const; diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp index 613bd045f..0d579ffb9 100644 --- a/src/gui/transferlistfilterswidget.cpp +++ b/src/gui/transferlistfilterswidget.cpp @@ -260,7 +260,7 @@ void TrackerFiltersList::addItem(const QTorrentHandle& handle) QString hash = handle.hash(); std::vector trackers = handle.trackers(); for (std::vector::iterator i = trackers.begin(), e = trackers.end(); i != e; ++i) - addItem(misc::toQString(i->url), hash); + addItem(misc::toQStringU(i->url), hash); //Check for trackerless torrent if (trackers.size() == 0) @@ -306,7 +306,7 @@ void TrackerFiltersList::removeItem(const QTorrentHandle& handle) QString hash = handle.hash(); std::vector trackers = handle.trackers(); for (std::vector::iterator i = trackers.begin(), e = trackers.end(); i != e; ++i) - removeItem(misc::toQString(i->url), hash); + removeItem(misc::toQStringU(i->url), hash); //Check for trackerless torrent if (trackers.size() == 0) @@ -361,6 +361,14 @@ void TrackerFiltersList::handleFavicoFailure(const QString& url, const QString& Log::WARNING); } +void TrackerFiltersList::changeTrackerless(bool trackerless, const QString &hash) +{ + if (trackerless) + addItem("", hash); + else + removeItem("", hash); +} + QString TrackerFiltersList::trackerFromRow(int row) const { Q_ASSERT(row > 1); @@ -556,14 +564,21 @@ void TransferListFiltersWidget::addLabel(QString& label) Preferences::instance()->addTorrentLabel(label); } -void TransferListFiltersWidget::addTracker(const QString &tracker, const QString &hash) +void TransferListFiltersWidget::addTrackers(const QStringList &trackers, const QString &hash) { - trackerFilters->addItem(tracker, hash); + foreach (const QString &tracker, trackers) + trackerFilters->addItem(tracker, hash); } -void TransferListFiltersWidget::removeTracker(const QString &tracker, const QString &hash) +void TransferListFiltersWidget::removeTrackers(const QStringList &trackers, const QString &hash) { - trackerFilters->removeItem(tracker, hash); + foreach (const QString &tracker, trackers) + trackerFilters->removeItem(tracker, hash); +} + +void TransferListFiltersWidget::changeTrackerless(bool trackerless, const QString &hash) +{ + trackerFilters->changeTrackerless(trackerless, hash); } void TransferListFiltersWidget::showLabelMenu(QPoint) diff --git a/src/gui/transferlistfilterswidget.h b/src/gui/transferlistfilterswidget.h index 215a95e8c..2060b4531 100644 --- a/src/gui/transferlistfilterswidget.h +++ b/src/gui/transferlistfilterswidget.h @@ -113,6 +113,7 @@ public: public slots: void handleFavicoDownload(const QString &url, const QString &filePath); void handleFavicoFailure(const QString &url, const QString &reason); + void changeTrackerless(bool trackerless, const QString &hash); private: QHash m_trackers; @@ -149,8 +150,9 @@ public: void loadSettings(); public slots: - void addTracker(const QString &tracker, const QString &hash); - void removeTracker(const QString &tracker, const QString &hash); + void addTrackers(const QStringList &trackers, const QString &hash); + void removeTrackers(const QStringList &trackers, const QString &hash); + void changeTrackerless(bool trackerless, const QString &hash); protected: virtual void resizeEvent(QResizeEvent *event); diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index ed2d5b36c..f1ce1e3de 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -354,17 +354,9 @@ void WebApplication::action_command_addTrackers() QString hash = request().posts["hash"]; if (!hash.isEmpty()) { - QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); - - if (h.is_valid() && h.has_metadata()) { - QString urls = request().posts["urls"]; - QStringList list = urls.split('\n'); - - foreach (const QString& url, list) { - announce_entry e(url.toStdString()); - h.add_tracker(e); - } - } + QString urls = request().posts["urls"]; + QStringList list = urls.split('\n'); + QBtSession::instance()->addTrackersAndUrlSeeds(hash, list, QStringList()); } }