mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-20 15:37:26 -06:00
Redesign main core classes.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -34,9 +34,12 @@
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include "iconprovider.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "core/net/downloadhandler.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/magneturi.h"
|
||||
#include "core/bittorrent/torrentinfo.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "messageboxraised.h"
|
||||
@@ -47,18 +50,13 @@
|
||||
#include <QUrl>
|
||||
#include <QMenu>
|
||||
#include <QFileDialog>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
AddNewTorrentDialog::AddNewTorrentDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::AddNewTorrentDialog)
|
||||
, m_contentModel(0)
|
||||
, m_contentDelegate(0)
|
||||
, m_isMagnet(false)
|
||||
, m_hasMetadata(false)
|
||||
, m_hasRenamedFile(false)
|
||||
, m_oldIndex(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@@ -123,22 +121,115 @@ void AddNewTorrentDialog::saveState()
|
||||
pref->setAddNewTorrentDialogExpanded(ui->adv_button->isChecked());
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showTorrent(const QString &torrent_path, const QString& from_url, QWidget *parent)
|
||||
void AddNewTorrentDialog::show(QString source, QWidget *parent)
|
||||
{
|
||||
if (source.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
source = misc::bcLinkToMagnet(source);
|
||||
}
|
||||
|
||||
AddNewTorrentDialog *dlg = new AddNewTorrentDialog(parent);
|
||||
if (dlg->loadTorrent(torrent_path, from_url))
|
||||
dlg->open();
|
||||
else
|
||||
delete dlg;
|
||||
|
||||
if (misc::isUrl(source)) {
|
||||
// Launch downloader
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), dlg, SLOT(handleDownloadFinished(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), dlg, SLOT(handleDownloadFailed(QString, QString)));
|
||||
connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), dlg, SLOT(handleRedirectedToMagnet(QString, QString)));
|
||||
}
|
||||
else {
|
||||
bool ok = false;
|
||||
if (source.startsWith("magnet:", Qt::CaseInsensitive))
|
||||
ok = dlg->loadMagnet(source);
|
||||
else
|
||||
ok = dlg->loadTorrent(source);
|
||||
|
||||
if (ok)
|
||||
dlg->open();
|
||||
else
|
||||
delete dlg;
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showMagnet(const QString& link, QWidget *parent)
|
||||
bool AddNewTorrentDialog::loadTorrent(const QString& torrent_path)
|
||||
{
|
||||
AddNewTorrentDialog *dlg = new AddNewTorrentDialog(parent);
|
||||
if (dlg->loadMagnet(link))
|
||||
dlg->open();
|
||||
if (torrent_path.startsWith("file://", Qt::CaseInsensitive))
|
||||
m_filePath = QUrl::fromEncoded(torrent_path.toLocal8Bit()).toLocalFile();
|
||||
else
|
||||
delete dlg;
|
||||
m_filePath = torrent_path;
|
||||
|
||||
if (!QFile::exists(m_filePath)) {
|
||||
MessageBoxRaised::critical(0, tr("I/O Error"), tr("The torrent file does not exist."));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hasMetadata = true;
|
||||
QString error;
|
||||
m_torrentInfo = BitTorrent::TorrentInfo::loadFromFile(m_filePath, error);
|
||||
if (!m_torrentInfo.isValid()) {
|
||||
MessageBoxRaised::critical(0, tr("Invalid torrent"), tr("Failed to load the torrent: %1").arg(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hash = m_torrentInfo.hash();
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (BitTorrent::Session::instance()->isKnownTorrent(m_hash)) {
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(m_hash);
|
||||
if (torrent) {
|
||||
torrent->addTrackers(m_torrentInfo.trackers());
|
||||
torrent->addUrlSeeds(m_torrentInfo.urlSeeds());
|
||||
MessageBoxRaised::information(0, tr("Already in download list"), tr("Torrent is already in download list. Trackers were merged."), QMessageBox::Ok);
|
||||
}
|
||||
else {
|
||||
MessageBoxRaised::critical(0, tr("Cannot add torrent"), tr("Cannot add this torrent. Perhaps it is already in adding state."), QMessageBox::Ok);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ui->lblhash->setText(m_hash);
|
||||
setupTreeview();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadMagnet(const QString &magnet_uri)
|
||||
{
|
||||
BitTorrent::MagnetUri magnet(magnet_uri);
|
||||
if (!magnet.isValid()) {
|
||||
MessageBoxRaised::critical(0, tr("Invalid magnet link"), tr("This magnet link was not recognized"));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hash = magnet.hash();
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (BitTorrent::Session::instance()->isKnownTorrent(m_hash)) {
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(m_hash);
|
||||
if (torrent) {
|
||||
torrent->addTrackers(magnet.trackers());
|
||||
torrent->addUrlSeeds(magnet.urlSeeds());
|
||||
MessageBoxRaised::information(0, tr("Already in download list"), tr("Magnet link is already in download list. Trackers were merged."), QMessageBox::Ok);
|
||||
}
|
||||
else {
|
||||
MessageBoxRaised::critical(0, tr("Cannot add torrent"), tr("Cannot add this torrent. Perhaps it is already in adding."), QMessageBox::Ok);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(metadataLoaded(BitTorrent::TorrentInfo)), SLOT(updateMetadata(BitTorrent::TorrentInfo)));
|
||||
|
||||
// Set dialog title
|
||||
QString torrent_name = magnet.name();
|
||||
setWindowTitle(torrent_name.isEmpty() ? tr("Magnet link") : torrent_name);
|
||||
|
||||
setupTreeview();
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
|
||||
BitTorrent::Session::instance()->loadMetadata(magnet_uri);
|
||||
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
|
||||
ui->lblhash->setText(m_hash);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showEvent(QShowEvent *event)
|
||||
@@ -158,7 +249,7 @@ void AddNewTorrentDialog::showAdvancedSettings(bool show)
|
||||
ui->adv_button->setText(QString::fromUtf8("▲"));
|
||||
ui->settings_group->setVisible(true);
|
||||
ui->info_group->setVisible(true);
|
||||
if (m_hasMetadata && (m_torrentInfo->num_files() > 1)) {
|
||||
if (m_hasMetadata && (m_torrentInfo.filesCount() > 1)) {
|
||||
ui->content_tree->setVisible(true);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
}
|
||||
@@ -178,83 +269,6 @@ void AddNewTorrentDialog::showAdvancedSettings(bool show)
|
||||
relayout();
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadTorrent(const QString& torrent_path, const QString& from_url)
|
||||
{
|
||||
m_isMagnet = false;
|
||||
m_url = from_url;
|
||||
if (torrent_path.startsWith("file://", Qt::CaseInsensitive))
|
||||
m_filePath = QUrl::fromEncoded(torrent_path.toLocal8Bit()).toLocalFile();
|
||||
else
|
||||
m_filePath = torrent_path;
|
||||
|
||||
if (!QFile::exists(m_filePath)) {
|
||||
MessageBoxRaised::critical(0, tr("I/O Error"), tr("The torrent file does not exist."));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hasMetadata = true;
|
||||
|
||||
try {
|
||||
std::vector<char> buffer;
|
||||
lazy_entry entry;
|
||||
libtorrent::error_code ec;
|
||||
misc::loadBencodedFile(m_filePath, buffer, entry, ec);
|
||||
m_torrentInfo = new torrent_info(entry);
|
||||
m_hash = misc::toQString(m_torrentInfo->info_hash());
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
MessageBoxRaised::critical(0, tr("Invalid torrent"), tr("Failed to load the torrent: %1").arg(misc::toQStringU(e.what())));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (QBtSession::instance()->getTorrentHandle(m_hash).is_valid()) {
|
||||
MessageBoxRaised::information(0, tr("Already in download list"), tr("Torrent is already in download list. Merging trackers."), QMessageBox::Ok);
|
||||
QBtSession::instance()->addTorrent(m_filePath, false, m_url);;
|
||||
return false;
|
||||
}
|
||||
|
||||
ui->lblhash->setText(m_hash);
|
||||
setupTreeview();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadMagnet(const QString &magnet_uri)
|
||||
{
|
||||
connect(QBtSession::instance(), SIGNAL(metadataReceivedHidden(const QTorrentHandle &)), SLOT(updateMetadata(const QTorrentHandle &)));
|
||||
m_isMagnet = true;
|
||||
m_url = magnet_uri;
|
||||
m_hash = misc::magnetUriToHash(m_url);
|
||||
if (m_hash.isEmpty()) {
|
||||
MessageBoxRaised::critical(0, tr("Invalid magnet link"), tr("This magnet link was not recognized"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (QBtSession::instance()->getTorrentHandle(m_hash).is_valid()) {
|
||||
MessageBoxRaised::information(0, tr("Already in download list"), tr("Magnet link is already in download list. Merging trackers."), QMessageBox::Ok);
|
||||
QBtSession::instance()->addMagnetUri(m_url, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set dialog title
|
||||
QString torrent_name = misc::magnetUriToName(m_url);
|
||||
setWindowTitle(torrent_name.isEmpty() ? tr("Magnet link") : torrent_name);
|
||||
|
||||
setupTreeview();
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
|
||||
// Override save path
|
||||
TorrentTempData::setSavePath(m_hash, QString(QDir::tempPath() + "/" + m_hash));
|
||||
HiddenData::addData(m_hash);
|
||||
QBtSession::instance()->addMagnetUri(m_url, false);
|
||||
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
|
||||
ui->lblhash->setText(m_hash);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveSavePathHistory() const
|
||||
{
|
||||
QDir selected_save_path(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString());
|
||||
@@ -279,7 +293,7 @@ void AddNewTorrentDialog::saveSavePathHistory() const
|
||||
int AddNewTorrentDialog::indexOfSavePath(const QString &save_path)
|
||||
{
|
||||
QDir saveDir(save_path);
|
||||
for(int i = 0; i<ui->save_path_combo->count() - 1; ++i)
|
||||
for(int i = 0; i < ui->save_path_combo->count(); ++i)
|
||||
if (QDir(ui->save_path_combo->itemData(i).toString()) == saveDir)
|
||||
return i;
|
||||
return -1;
|
||||
@@ -287,7 +301,7 @@ int AddNewTorrentDialog::indexOfSavePath(const QString &save_path)
|
||||
|
||||
void AddNewTorrentDialog::updateFileNameInSavePaths(const QString &new_filename)
|
||||
{
|
||||
for(int i = 0; i<ui->save_path_combo->count() - 1; ++i) {
|
||||
for(int i = 0; i < ui->save_path_combo->count(); ++i) {
|
||||
const QDir folder(ui->save_path_combo->itemData(i).toString());
|
||||
ui->save_path_combo->setItemText(i, fsutils::toNativePath(folder.absoluteFilePath(new_filename)));
|
||||
}
|
||||
@@ -300,14 +314,14 @@ void AddNewTorrentDialog::updateDiskSpaceLabel()
|
||||
|
||||
if (m_hasMetadata) {
|
||||
if (m_contentModel) {
|
||||
const std::vector<int> priorities = m_contentModel->model()->getFilesPriorities();
|
||||
Q_ASSERT(priorities.size() == (uint) m_torrentInfo->num_files());
|
||||
for (uint i = 0; i<priorities.size(); ++i)
|
||||
const QVector<int> priorities = m_contentModel->model()->getFilePriorities();
|
||||
Q_ASSERT(priorities.size() == m_torrentInfo.filesCount());
|
||||
for (int i = 0; i < priorities.size(); ++i)
|
||||
if (priorities[i] > 0)
|
||||
torrent_size += m_torrentInfo->files().file_size(i);
|
||||
torrent_size += m_torrentInfo.fileSize(i);
|
||||
}
|
||||
else {
|
||||
torrent_size = m_torrentInfo->total_size();
|
||||
torrent_size = m_torrentInfo.totalSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,7 +352,7 @@ void AddNewTorrentDialog::browseButton_clicked()
|
||||
QString cur_save_path = ui->save_path_combo->itemText(m_oldIndex);
|
||||
QString new_path, old_filename, new_filename;
|
||||
|
||||
if (m_torrentInfo && m_torrentInfo->num_files() == 1) {
|
||||
if (m_torrentInfo.isValid() && (m_torrentInfo.filesCount() == 1)) {
|
||||
old_filename = fsutils::fileName(cur_save_path);
|
||||
new_path = QFileDialog::getSaveFileName(this, tr("Choose save path"), cur_save_path, QString(), 0, QFileDialog::DontConfirmOverwrite);
|
||||
if (!new_path.isEmpty())
|
||||
@@ -367,8 +381,7 @@ void AddNewTorrentDialog::browseButton_clicked()
|
||||
}
|
||||
// Update file name in all save_paths
|
||||
if (!new_filename.isEmpty() && !fsutils::sameFileNames(old_filename, new_filename)) {
|
||||
m_hasRenamedFile = true;
|
||||
m_filesPath[0] = new_filename;
|
||||
m_torrentInfo.renameFile(0, new_filename);
|
||||
updateFileNameInSavePaths(new_filename);
|
||||
}
|
||||
|
||||
@@ -415,7 +428,7 @@ void AddNewTorrentDialog::renameSelectedFile()
|
||||
if (m_contentModel->itemType(index) == TorrentContentModelItem::FileType) {
|
||||
// File renaming
|
||||
const int file_index = m_contentModel->getFileIndex(index);
|
||||
QString old_name = fsutils::fromNativePath(m_filesPath.at(file_index));
|
||||
QString old_name = fsutils::fromNativePath(m_torrentInfo.filePath(file_index));
|
||||
qDebug("Old name: %s", qPrintable(old_name));
|
||||
QStringList path_items = old_name.split("/");
|
||||
path_items.removeLast();
|
||||
@@ -428,9 +441,9 @@ void AddNewTorrentDialog::renameSelectedFile()
|
||||
new_name = fsutils::expandPath(new_name);
|
||||
qDebug("New name: %s", qPrintable(new_name));
|
||||
// Check if that name is already used
|
||||
for (int i = 0; i<m_torrentInfo->num_files(); ++i) {
|
||||
for (int i = 0; i < m_torrentInfo.filesCount(); ++i) {
|
||||
if (i == file_index) continue;
|
||||
if (fsutils::sameFileNames(m_filesPath.at(i), new_name)) {
|
||||
if (fsutils::sameFileNames(m_torrentInfo.filePath(i), new_name)) {
|
||||
// Display error message
|
||||
MessageBoxRaised::warning(this, tr("The file could not be renamed"),
|
||||
tr("This name is already in use in this folder. Please use a different name."),
|
||||
@@ -439,9 +452,7 @@ void AddNewTorrentDialog::renameSelectedFile()
|
||||
}
|
||||
}
|
||||
qDebug("Renaming %s to %s", qPrintable(old_name), qPrintable(new_name));
|
||||
// Rename file in files_path
|
||||
m_filesPath.replace(file_index, new_name);
|
||||
m_hasRenamedFile = true;
|
||||
m_torrentInfo.renameFile(file_index, new_name);
|
||||
// Rename in torrent files model too
|
||||
m_contentModel->setData(index, new_name_last);
|
||||
}
|
||||
@@ -460,8 +471,8 @@ void AddNewTorrentDialog::renameSelectedFile()
|
||||
QString new_path = path_items.join("/");
|
||||
if (!new_path.endsWith("/")) new_path += "/";
|
||||
// Check for overwriting
|
||||
for (int i = 0; i<m_torrentInfo->num_files(); ++i) {
|
||||
const QString ¤t_name = m_filesPath.at(i);
|
||||
for (int i = 0; i < m_torrentInfo.filesCount(); ++i) {
|
||||
const QString ¤t_name = m_torrentInfo.filePath(i);
|
||||
#if defined(Q_OS_UNIX) || defined(Q_WS_QWS)
|
||||
if (current_name.startsWith(new_path, Qt::CaseSensitive)) {
|
||||
#else
|
||||
@@ -474,18 +485,17 @@ void AddNewTorrentDialog::renameSelectedFile()
|
||||
}
|
||||
}
|
||||
// Replace path in all files
|
||||
for (int i = 0; i<m_torrentInfo->num_files(); ++i) {
|
||||
const QString ¤t_name = m_filesPath.at(i);
|
||||
for (int i = 0; i < m_torrentInfo.filesCount(); ++i) {
|
||||
const QString ¤t_name = m_torrentInfo.filePath(i);
|
||||
if (current_name.startsWith(old_path)) {
|
||||
QString new_name = current_name;
|
||||
new_name.replace(0, old_path.length(), new_path);
|
||||
new_name = fsutils::expandPath(new_name);
|
||||
qDebug("Rename %s to %s", qPrintable(current_name), qPrintable(new_name));
|
||||
// Rename in files_path
|
||||
m_filesPath.replace(i, new_name);
|
||||
m_torrentInfo.renameFile(i, new_name);
|
||||
}
|
||||
}
|
||||
m_hasRenamedFile = true;
|
||||
|
||||
// Rename folder in torrent files model too
|
||||
m_contentModel->setData(index, new_name_last);
|
||||
}
|
||||
@@ -524,8 +534,8 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint&)
|
||||
QMenu myFilesLlistMenu;
|
||||
const QModelIndexList selectedRows = ui->content_tree->selectionModel()->selectedRows(0);
|
||||
QAction *actRename = 0;
|
||||
if (selectedRows.size() == 1 && m_torrentInfo->num_files() > 1) {
|
||||
actRename = myFilesLlistMenu.addAction(IconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
|
||||
if ((selectedRows.size() == 1) && (m_torrentInfo.filesCount() > 1)) {
|
||||
actRename = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
|
||||
myFilesLlistMenu.addSeparator();
|
||||
}
|
||||
QMenu subMenu;
|
||||
@@ -564,85 +574,78 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint&)
|
||||
|
||||
void AddNewTorrentDialog::accept()
|
||||
{
|
||||
if (m_isMagnet)
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle &)));
|
||||
if (!m_hasMetadata)
|
||||
disconnect(this, SLOT(updateMetadata(const BitTorrent::TorrentInfo &)));
|
||||
|
||||
Preferences *const pref = Preferences::instance();
|
||||
BitTorrent::AddTorrentParams params;
|
||||
|
||||
Preferences* const pref = Preferences::instance();
|
||||
// Save Temporary data about torrent
|
||||
QString save_path = ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString();
|
||||
TorrentTempData::setSavePath(m_hash, save_path);
|
||||
if (ui->skip_check_cb->isChecked())
|
||||
// TODO: Check if destination actually exists
|
||||
TorrentTempData::setSeedingMode(m_hash, true);
|
||||
params.skipChecking = true;
|
||||
|
||||
// Label
|
||||
const QString label = ui->label_combo->currentText();
|
||||
if (!label.isEmpty())
|
||||
TorrentTempData::setLabel(m_hash, label);
|
||||
params.label = ui->label_combo->currentText();
|
||||
|
||||
// Save file priorities
|
||||
if (m_contentModel)
|
||||
TorrentTempData::setFilesPriority(m_hash, m_contentModel->model()->getFilesPriorities());
|
||||
params.filePriorities = m_contentModel->model()->getFilePriorities();
|
||||
|
||||
// Rename files if necessary
|
||||
if (m_hasRenamedFile)
|
||||
TorrentTempData::setFilesPath(m_hash, m_filesPath);
|
||||
|
||||
TorrentTempData::setAddPaused(m_hash, !ui->start_torrent_cb->isChecked());
|
||||
|
||||
// Add torrent
|
||||
if (m_isMagnet)
|
||||
QBtSession::instance()->unhideMagnet(m_hash);
|
||||
else
|
||||
QBtSession::instance()->addTorrent(m_filePath, false, m_url);
|
||||
params.addPaused = !ui->start_torrent_cb->isChecked();
|
||||
|
||||
saveSavePathHistory();
|
||||
// Save settings
|
||||
pref->useAdditionDialog(!ui->never_show_cb->isChecked());
|
||||
|
||||
QString savePath = ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString();
|
||||
if (ui->default_save_path_cb->isChecked()) {
|
||||
pref->setSavePath(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString());
|
||||
QBtSession::instance()->setDefaultSavePath(pref->getSavePath());
|
||||
pref->setSavePath(savePath);
|
||||
pref->apply();
|
||||
}
|
||||
else {
|
||||
// if we don't use default save path...
|
||||
if (QDir(savePath) != QDir(pref->getSavePath()))
|
||||
params.savePath = savePath;
|
||||
}
|
||||
|
||||
// Add torrent
|
||||
if (!m_hasMetadata)
|
||||
BitTorrent::Session::instance()->addTorrent(m_hash, params);
|
||||
else
|
||||
BitTorrent::Session::instance()->addTorrent(m_torrentInfo, params);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::reject()
|
||||
{
|
||||
if (m_isMagnet) {
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle &)));
|
||||
if (!m_hasMetadata) {
|
||||
disconnect(this, SLOT(updateMetadata(BitTorrent::TorrentInfo)));
|
||||
setMetadataProgressIndicator(false);
|
||||
QBtSession::instance()->deleteTorrent(m_hash, true);
|
||||
BitTorrent::Session::instance()->cancelLoadMetadata(m_hash);
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateMetadata(const QTorrentHandle &h)
|
||||
void AddNewTorrentDialog::updateMetadata(const BitTorrent::TorrentInfo &info)
|
||||
{
|
||||
try {
|
||||
if (h.hash() != m_hash)
|
||||
return;
|
||||
if (info.hash() != m_hash) return;
|
||||
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle &)));
|
||||
Q_ASSERT(h.has_metadata());
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
m_torrentInfo = new torrent_info(h.get_torrent_info());
|
||||
#else
|
||||
m_torrentInfo = new torrent_info(*h.torrent_file());
|
||||
#endif
|
||||
|
||||
// Good to go
|
||||
m_hasMetadata = true;
|
||||
setMetadataProgressIndicator(true, tr("Parsing metadata..."));
|
||||
|
||||
// Update UI
|
||||
setupTreeview();
|
||||
setMetadataProgressIndicator(false, tr("Metadata retrieval complete"));
|
||||
} catch (invalid_handle&) {
|
||||
MessageBoxRaised::critical(0, tr("I/O Error"), ("Unknown error."));
|
||||
setMetadataProgressIndicator(false, tr("Unknown error"));
|
||||
disconnect(this, SLOT(updateMetadata(BitTorrent::TorrentInfo)));
|
||||
if (!info.isValid()) {
|
||||
MessageBoxRaised::critical(0, tr("I/O Error"), ("Invalid metadata."));
|
||||
setMetadataProgressIndicator(false, tr("Invalid metadata"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Good to go
|
||||
m_torrentInfo = info;
|
||||
m_hasMetadata = true;
|
||||
setMetadataProgressIndicator(true, tr("Parsing metadata..."));
|
||||
|
||||
// Update UI
|
||||
setupTreeview();
|
||||
setMetadataProgressIndicator(false, tr("Metadata retrieval complete"));
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText)
|
||||
@@ -661,21 +664,15 @@ void AddNewTorrentDialog::setupTreeview()
|
||||
}
|
||||
else {
|
||||
// Set dialog title
|
||||
setWindowTitle(misc::toQStringU(m_torrentInfo->name()));
|
||||
setWindowTitle(m_torrentInfo.name());
|
||||
|
||||
// Set torrent information
|
||||
QString comment = misc::toQString(m_torrentInfo->comment());
|
||||
QString comment = m_torrentInfo.comment();
|
||||
ui->comment_lbl->setText(comment.replace('\n', ' '));
|
||||
ui->date_lbl->setText(m_torrentInfo->creation_date() ? misc::toQString(*m_torrentInfo->creation_date()) : tr("Not available"));
|
||||
|
||||
file_storage const& fs = m_torrentInfo->files();
|
||||
|
||||
// Populate m_filesList
|
||||
for (int i = 0; i < fs.num_files(); ++i)
|
||||
m_filesPath << misc::toQStringU(fs.file_path(i));
|
||||
ui->date_lbl->setText(!m_torrentInfo.creationDate().isNull() ? m_torrentInfo.creationDate().toString(Qt::DefaultLocaleLongDate) : tr("Not available"));
|
||||
|
||||
// Prepare content tree
|
||||
if (fs.num_files() > 1) {
|
||||
if (m_torrentInfo.filesCount() > 1) {
|
||||
m_contentModel = new TorrentContentFilterModel(this);
|
||||
connect(m_contentModel->model(), SIGNAL(filteredFilesChanged()), SLOT(updateDiskSpaceLabel()));
|
||||
ui->content_tree->setModel(m_contentModel);
|
||||
@@ -686,7 +683,7 @@ void AddNewTorrentDialog::setupTreeview()
|
||||
connect(ui->content_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(displayContentTreeMenu(const QPoint &)));
|
||||
|
||||
// List files in torrent
|
||||
m_contentModel->model()->setupModelData(*m_torrentInfo);
|
||||
m_contentModel->model()->setupModelData(m_torrentInfo);
|
||||
if (!m_headerState.isEmpty())
|
||||
ui->content_tree->header()->restoreState(m_headerState);
|
||||
|
||||
@@ -695,8 +692,8 @@ void AddNewTorrentDialog::setupTreeview()
|
||||
}
|
||||
else {
|
||||
// Update save paths (append file name to them)
|
||||
QString single_file_relpath = misc::toQStringU(fs.file_path(0));
|
||||
for (int i = 0; i<ui->save_path_combo->count() - 1; ++i)
|
||||
QString single_file_relpath = m_torrentInfo.filePath(0);
|
||||
for (int i = 0; i < ui->save_path_combo->count(); ++i)
|
||||
ui->save_path_combo->setItemText(i, fsutils::toNativePath(QDir(ui->save_path_combo->itemText(i)).absoluteFilePath(single_file_relpath)));
|
||||
}
|
||||
}
|
||||
@@ -706,3 +703,27 @@ void AddNewTorrentDialog::setupTreeview()
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::handleDownloadFailed(const QString &url, const QString &reason)
|
||||
{
|
||||
MessageBoxRaised::critical(0, tr("Download Error"), QString("Cannot download %1: %2").arg(url).arg(reason));
|
||||
this->deleteLater();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::handleRedirectedToMagnet(const QString &url, const QString &magnetUri)
|
||||
{
|
||||
Q_UNUSED(url)
|
||||
if (loadMagnet(magnetUri))
|
||||
open();
|
||||
else
|
||||
this->deleteLater();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::handleDownloadFinished(const QString &url, const QString &filePath)
|
||||
{
|
||||
Q_UNUSED(url)
|
||||
if (loadTorrent(filePath))
|
||||
open();
|
||||
else
|
||||
this->deleteLater();
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
#include <QDialog>
|
||||
#include <QUrl>
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include "qtorrenthandle.h"
|
||||
#include "core/bittorrent/infohash.h"
|
||||
#include "core/bittorrent/torrentinfo.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
@@ -54,8 +54,7 @@ class AddNewTorrentDialog: public QDialog
|
||||
public:
|
||||
~AddNewTorrentDialog();
|
||||
|
||||
static void showTorrent(const QString& torrent_path, const QString& from_url, QWidget *parent = 0);
|
||||
static void showMagnet(const QString& torrent_link, QWidget *parent = 0);
|
||||
static void show(QString source, QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event);
|
||||
@@ -68,8 +67,11 @@ private slots:
|
||||
void relayout();
|
||||
void renameSelectedFile();
|
||||
void setdialogPosition();
|
||||
void updateMetadata(const QTorrentHandle& h);
|
||||
void updateMetadata(const BitTorrent::TorrentInfo &info);
|
||||
void browseButton_clicked();
|
||||
void handleDownloadFailed(const QString &url, const QString &reason);
|
||||
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
|
||||
void handleDownloadFinished(const QString &url, const QString &filePath);
|
||||
|
||||
protected slots:
|
||||
virtual void accept();
|
||||
@@ -77,7 +79,7 @@ protected slots:
|
||||
|
||||
private:
|
||||
explicit AddNewTorrentDialog(QWidget *parent = 0);
|
||||
bool loadTorrent(const QString& torrent_path, const QString& from_url);
|
||||
bool loadTorrent(const QString& torrent_path);
|
||||
bool loadMagnet(const QString& magnet_uri);
|
||||
void loadSavePathHistory();
|
||||
void saveSavePathHistory() const;
|
||||
@@ -92,14 +94,10 @@ private:
|
||||
Ui::AddNewTorrentDialog *ui;
|
||||
TorrentContentFilterModel *m_contentModel;
|
||||
PropListDelegate *m_contentDelegate;
|
||||
bool m_isMagnet;
|
||||
bool m_hasMetadata;
|
||||
QString m_filePath;
|
||||
QString m_url;
|
||||
QString m_hash;
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> m_torrentInfo;
|
||||
QStringList m_filesPath;
|
||||
bool m_hasRenamedFile;
|
||||
BitTorrent::InfoHash m_hash;
|
||||
BitTorrent::TorrentInfo m_torrentInfo;
|
||||
QShortcut *editHotkey;
|
||||
QByteArray m_headerState;
|
||||
int m_oldIndex;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QNetworkInterface>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include "core/preferences.h"
|
||||
|
||||
enum AdvSettingsCols {PROPERTY, VALUE};
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <QPushButton>
|
||||
#include "ui_confirmdeletiondlg.h"
|
||||
#include "core/preferences.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/misc.h"
|
||||
|
||||
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
@@ -49,9 +49,9 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
else
|
||||
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
||||
// Icons
|
||||
lbl_warn->setPixmap(IconProvider::instance()->getIcon("dialog-warning").pixmap(lbl_warn->height()));
|
||||
lbl_warn->setPixmap(GuiIconProvider::instance()->getIcon("dialog-warning").pixmap(lbl_warn->height()));
|
||||
lbl_warn->setFixedWidth(lbl_warn->height());
|
||||
rememberBtn->setIcon(IconProvider::instance()->getIcon("object-locked"));
|
||||
rememberBtn->setIcon(GuiIconProvider::instance()->getIcon("object-locked"));
|
||||
|
||||
move(misc::screenCenter(this));
|
||||
checkPermDelete->setChecked(Preferences::instance()->deleteTorrentFilesAsDefault());
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "executionlog.h"
|
||||
#include "ui_executionlog.h"
|
||||
#include "core/logger.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "loglistwidget.h"
|
||||
|
||||
ExecutionLog::ExecutionLog(QWidget *parent)
|
||||
@@ -47,8 +47,8 @@ ExecutionLog::ExecutionLog(QWidget *parent)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->tabConsole->setTabIcon(0, IconProvider::instance()->getIcon("view-calendar-journal"));
|
||||
ui->tabConsole->setTabIcon(1, IconProvider::instance()->getIcon("view-filter"));
|
||||
ui->tabConsole->setTabIcon(0, GuiIconProvider::instance()->getIcon("view-calendar-journal"));
|
||||
ui->tabConsole->setTabIcon(1, GuiIconProvider::instance()->getIcon("view-filter"));
|
||||
ui->tabGeneral->layout()->addWidget(m_msgList);
|
||||
ui->tabBan->layout()->addWidget(m_peerList);
|
||||
|
||||
|
||||
@@ -183,21 +183,21 @@ const char * country_name[253] =
|
||||
"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
|
||||
"Saint Barthelemy","Saint Martin"};
|
||||
|
||||
QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
||||
if (iso[0] == 0) return "N/A";
|
||||
QString GeoIPManager::CountryISOCodeToName(const QString &iso) {
|
||||
if (iso.isEmpty()) return "N/A";
|
||||
|
||||
for (uint i = 0; i < num_countries; ++i) {
|
||||
if (iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
||||
if (iso == country_code[i]) {
|
||||
return QLatin1String(country_name[i]);
|
||||
}
|
||||
}
|
||||
qDebug("GeoIPManager: Country name resolution failed for: %c%c", iso[0], iso[1]);
|
||||
qDebug("GeoIPManager: Country name resolution failed for: %s", qPrintable(iso));
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
QIcon GeoIPManager::CountryISOCodeToIcon(const char* iso) {
|
||||
if (iso[0] == 0 || iso[0] == '!') return QIcon();
|
||||
const QString isoStr = QString(QByteArray(iso, 2)).toLower();
|
||||
return QIcon(":/icons/flags/"+isoStr+".png");
|
||||
QIcon GeoIPManager::CountryISOCodeToIcon(const QString &iso) {
|
||||
if (iso.isEmpty() || (iso[0] == '!')) return QIcon();
|
||||
return QIcon(":/icons/flags/" + iso.toLower() + ".png");
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ class GeoIPManager : public QObject {
|
||||
|
||||
public:
|
||||
static void loadDatabase(libtorrent::session *s);
|
||||
static QIcon CountryISOCodeToIcon(const char* iso);
|
||||
static QString CountryISOCodeToName(const char* iso);
|
||||
static QIcon CountryISOCodeToIcon(const QString &iso);
|
||||
static QString CountryISOCodeToName(const QString &iso);
|
||||
|
||||
private:
|
||||
static QString geoipFolder(bool embedded=false);
|
||||
|
||||
@@ -3,7 +3,6 @@ INCLUDEPATH += $$PWD
|
||||
include(lineedit/lineedit.pri)
|
||||
include(properties/properties.pri)
|
||||
include(rss/rss.pri)
|
||||
include(torrentcreator/torrentcreator.pri)
|
||||
include(geoip/geoip.pri)
|
||||
include(powermanagement/powermanagement.pri)
|
||||
unix:!macx:dbus: include(qtnotify/qtnotify.pri)
|
||||
@@ -32,18 +31,18 @@ HEADERS += \
|
||||
$$PWD/hidabletabwidget.h \
|
||||
$$PWD/torrentimportdlg.h \
|
||||
$$PWD/executionlog.h \
|
||||
$$PWD/iconprovider.h \
|
||||
$$PWD/guiiconprovider.h \
|
||||
$$PWD/updownratiodlg.h \
|
||||
$$PWD/loglistwidget.h \
|
||||
$$PWD/addnewtorrentdialog.h \
|
||||
$$PWD/autoexpandabledialog.h \
|
||||
$$PWD/statsdialog.h \
|
||||
$$PWD/messageboxraised.h \
|
||||
$$PWD/torrentfilterenum.h \
|
||||
$$PWD/options_imp.h \
|
||||
$$PWD/advancedsettings.h \
|
||||
$$PWD/shutdownconfirm.h \
|
||||
$$PWD/torrentmodel.h
|
||||
$$PWD/torrentmodel.h \
|
||||
$$PWD/torrentcreatordlg.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/mainwindow.cpp \
|
||||
@@ -62,7 +61,7 @@ SOURCES += \
|
||||
$$PWD/executionlog.cpp \
|
||||
$$PWD/speedlimitdlg.cpp \
|
||||
$$PWD/previewselect.cpp \
|
||||
$$PWD/iconprovider.cpp \
|
||||
$$PWD/guiiconprovider.cpp \
|
||||
$$PWD/updownratiodlg.cpp \
|
||||
$$PWD/loglistwidget.cpp \
|
||||
$$PWD/addnewtorrentdialog.cpp \
|
||||
@@ -73,7 +72,8 @@ SOURCES += \
|
||||
$$PWD/trackerlogin.cpp \
|
||||
$$PWD/options_imp.cpp \
|
||||
$$PWD/shutdownconfirm.cpp \
|
||||
$$PWD/torrentmodel.cpp
|
||||
$$PWD/torrentmodel.cpp \
|
||||
$$PWD/torrentcreatordlg.cpp
|
||||
|
||||
win32|macx {
|
||||
HEADERS += $$PWD/programupdater.h
|
||||
@@ -94,6 +94,7 @@ FORMS += \
|
||||
$$PWD/addnewtorrentdialog.ui \
|
||||
$$PWD/autoexpandabledialog.ui \
|
||||
$$PWD/statsdialog.ui \
|
||||
$$PWD/options.ui
|
||||
$$PWD/options.ui \
|
||||
$$PWD/createtorrent.ui
|
||||
|
||||
RESOURCES += $$PWD/about.qrc
|
||||
|
||||
125
src/gui/guiiconprovider.cpp
Normal file
125
src/gui/guiiconprovider.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/preferences.h"
|
||||
|
||||
#include <QIcon>
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#endif
|
||||
|
||||
GuiIconProvider::GuiIconProvider(QObject *parent)
|
||||
: IconProvider(parent)
|
||||
{
|
||||
configure();
|
||||
connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure()));
|
||||
}
|
||||
|
||||
GuiIconProvider::~GuiIconProvider() {}
|
||||
|
||||
void GuiIconProvider::initInstance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new GuiIconProvider;
|
||||
}
|
||||
|
||||
GuiIconProvider *GuiIconProvider::instance()
|
||||
{
|
||||
return static_cast<GuiIconProvider *>(m_instance);
|
||||
}
|
||||
|
||||
QIcon GuiIconProvider::getIcon(const QString &iconId)
|
||||
{
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
if (m_useSystemTheme) {
|
||||
QIcon icon = QIcon::fromTheme(iconId, QIcon(IconProvider::getIconPath(iconId)));
|
||||
icon = generateDifferentSizes(icon);
|
||||
return icon;
|
||||
}
|
||||
#endif
|
||||
return QIcon(IconProvider::getIconPath(iconId));
|
||||
}
|
||||
|
||||
// Makes sure the icon is at least available in 16px and 24px size
|
||||
// It scales the icon from the theme if necessary
|
||||
// Otherwise, the UI looks broken if the icon is not available
|
||||
// in the correct size.
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
QIcon GuiIconProvider::generateDifferentSizes(const QIcon &icon)
|
||||
{
|
||||
QIcon newIcon;
|
||||
QList<QSize> requiredSizes;
|
||||
requiredSizes << QSize(16, 16) << QSize(24, 24) << QSize(32, 32);
|
||||
QList<QIcon::Mode> modes;
|
||||
modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled;
|
||||
foreach (const QSize &size, requiredSizes) {
|
||||
foreach (QIcon::Mode mode, modes) {
|
||||
QPixmap pixoff = icon.pixmap(size, mode, QIcon::Off);
|
||||
if (pixoff.height() > size.height())
|
||||
pixoff = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
newIcon.addPixmap(pixoff, mode, QIcon::Off);
|
||||
QPixmap pixon = icon.pixmap(size, mode, QIcon::On);
|
||||
if (pixon.height() > size.height())
|
||||
pixon = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
newIcon.addPixmap(pixon, mode, QIcon::On);
|
||||
}
|
||||
}
|
||||
|
||||
return newIcon;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString GuiIconProvider::getIconPath(const QString &iconId)
|
||||
{
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
if (m_useSystemTheme) {
|
||||
QString path = QDir::temp().absoluteFilePath(iconId + ".png");
|
||||
if (!QFile::exists(path)) {
|
||||
const QIcon icon = QIcon::fromTheme(iconId);
|
||||
if (!icon.isNull())
|
||||
icon.pixmap(32).save(path);
|
||||
else
|
||||
path = IconProvider::getIconPath(iconId);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
return IconProvider::getIconPath(iconId);
|
||||
}
|
||||
|
||||
|
||||
void GuiIconProvider::configure()
|
||||
{
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
m_useSystemTheme = Preferences::instance()->useSystemIconTheme();
|
||||
#endif
|
||||
}
|
||||
62
src/gui/guiiconprovider.h
Normal file
62
src/gui/guiiconprovider.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GUIICONPROVIDER_H
|
||||
#define GUIICONPROVIDER_H
|
||||
|
||||
#include "core/iconprovider.h"
|
||||
|
||||
class QIcon;
|
||||
|
||||
class GuiIconProvider : public IconProvider
|
||||
{
|
||||
Q_DISABLE_COPY(GuiIconProvider)
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void initInstance();
|
||||
static GuiIconProvider *instance();
|
||||
|
||||
QIcon getIcon(const QString &iconId);
|
||||
QString getIconPath(const QString &iconId);
|
||||
|
||||
private slots:
|
||||
void configure();
|
||||
|
||||
private:
|
||||
explicit GuiIconProvider(QObject *parent = 0);
|
||||
~GuiIconProvider();
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
QIcon generateDifferentSizes(const QIcon &icon);
|
||||
|
||||
bool m_useSystemTheme;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // GUIICONPROVIDER_H
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <QRegExp>
|
||||
#include <QAction>
|
||||
#include "loglistwidget.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
|
||||
LogListWidget::LogListWidget(int max_lines, QWidget *parent) :
|
||||
QListWidget(parent),
|
||||
@@ -44,8 +44,8 @@ LogListWidget::LogListWidget(int max_lines, QWidget *parent) :
|
||||
// Allow multiple selections
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
// Context menu
|
||||
QAction *copyAct = new QAction(IconProvider::instance()->getIcon("edit-copy"), tr("Copy"), this);
|
||||
QAction *clearAct = new QAction(IconProvider::instance()->getIcon("edit-clear"), tr("Clear"), this);
|
||||
QAction *copyAct = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy"), this);
|
||||
QAction *clearAct = new QAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear"), this);
|
||||
connect(copyAct, SIGNAL(triggered()), SLOT(copySelection()));
|
||||
connect(clearAct, SIGNAL(triggered()), SLOT(clearLog()));
|
||||
addAction(copyAct);
|
||||
|
||||
@@ -55,7 +55,9 @@
|
||||
#include "addnewtorrentdialog.h"
|
||||
#include "searchengine.h"
|
||||
#include "rss_imp.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/sessionstatus.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "about_imp.h"
|
||||
#include "trackerlogin.h"
|
||||
#include "options_imp.h"
|
||||
@@ -63,7 +65,6 @@
|
||||
#include "core/preferences.h"
|
||||
#include "trackerlist.h"
|
||||
#include "peerlistwidget.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "transferlistfilterswidget.h"
|
||||
#include "propertieswidget.h"
|
||||
#include "statusbar.h"
|
||||
@@ -71,11 +72,9 @@
|
||||
#include "torrentimportdlg.h"
|
||||
#include "torrentmodel.h"
|
||||
#include "executionlog.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/logger.h"
|
||||
#ifndef DISABLE_GUI
|
||||
#include "autoexpandabledialog.h"
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
void qt_mac_set_dock_menu(QMenu *menu);
|
||||
#endif
|
||||
@@ -86,13 +85,10 @@ void qt_mac_set_dock_menu(QMenu *menu);
|
||||
#endif
|
||||
#include "powermanagement.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#include "core/downloadthread.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "core/net/downloadhandler.h"
|
||||
#endif
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
#define TIME_TRAY_BALLOON 5000
|
||||
#define PREVENT_SUSPEND_INTERVAL 60000
|
||||
|
||||
@@ -128,32 +124,32 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
|
||||
addToolbarContextMenu();
|
||||
|
||||
actionOpen->setIcon(IconProvider::instance()->getIcon("list-add"));
|
||||
actionDownload_from_URL->setIcon(IconProvider::instance()->getIcon("insert-link"));
|
||||
actionOpen->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
||||
actionDownload_from_URL->setIcon(GuiIconProvider::instance()->getIcon("insert-link"));
|
||||
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/icons/skin/seeding.png")));
|
||||
actionSet_download_limit->setIcon(QIcon(QString::fromUtf8(":/icons/skin/download.png")));
|
||||
actionSet_global_upload_limit->setIcon(QIcon(QString::fromUtf8(":/icons/skin/seeding.png")));
|
||||
actionSet_global_download_limit->setIcon(QIcon(QString::fromUtf8(":/icons/skin/download.png")));
|
||||
actionCreate_torrent->setIcon(IconProvider::instance()->getIcon("document-edit"));
|
||||
actionAbout->setIcon(IconProvider::instance()->getIcon("help-about"));
|
||||
actionStatistics->setIcon(IconProvider::instance()->getIcon("view-statistics"));
|
||||
actionBugReport->setIcon(IconProvider::instance()->getIcon("tools-report-bug"));
|
||||
actionDecreasePriority->setIcon(IconProvider::instance()->getIcon("go-down"));
|
||||
actionBottomPriority->setIcon(IconProvider::instance()->getIcon("go-bottom"));
|
||||
actionDelete->setIcon(IconProvider::instance()->getIcon("list-remove"));
|
||||
actionDocumentation->setIcon(IconProvider::instance()->getIcon("help-contents"));
|
||||
actionDonate_money->setIcon(IconProvider::instance()->getIcon("wallet-open"));
|
||||
actionExit->setIcon(IconProvider::instance()->getIcon("application-exit"));
|
||||
actionIncreasePriority->setIcon(IconProvider::instance()->getIcon("go-up"));
|
||||
actionTopPriority->setIcon(IconProvider::instance()->getIcon("go-top"));
|
||||
actionLock_qBittorrent->setIcon(IconProvider::instance()->getIcon("object-locked"));
|
||||
actionOptions->setIcon(IconProvider::instance()->getIcon("preferences-system"));
|
||||
actionPause->setIcon(IconProvider::instance()->getIcon("media-playback-pause"));
|
||||
actionPause_All->setIcon(IconProvider::instance()->getIcon("media-playback-pause"));
|
||||
actionStart->setIcon(IconProvider::instance()->getIcon("media-playback-start"));
|
||||
actionStart_All->setIcon(IconProvider::instance()->getIcon("media-playback-start"));
|
||||
action_Import_Torrent->setIcon(IconProvider::instance()->getIcon("document-import"));
|
||||
menuAuto_Shutdown_on_downloads_completion->setIcon(IconProvider::instance()->getIcon("application-exit"));
|
||||
actionCreate_torrent->setIcon(GuiIconProvider::instance()->getIcon("document-edit"));
|
||||
actionAbout->setIcon(GuiIconProvider::instance()->getIcon("help-about"));
|
||||
actionStatistics->setIcon(GuiIconProvider::instance()->getIcon("view-statistics"));
|
||||
actionBugReport->setIcon(GuiIconProvider::instance()->getIcon("tools-report-bug"));
|
||||
actionDecreasePriority->setIcon(GuiIconProvider::instance()->getIcon("go-down"));
|
||||
actionBottomPriority->setIcon(GuiIconProvider::instance()->getIcon("go-bottom"));
|
||||
actionDelete->setIcon(GuiIconProvider::instance()->getIcon("list-remove"));
|
||||
actionDocumentation->setIcon(GuiIconProvider::instance()->getIcon("help-contents"));
|
||||
actionDonate_money->setIcon(GuiIconProvider::instance()->getIcon("wallet-open"));
|
||||
actionExit->setIcon(GuiIconProvider::instance()->getIcon("application-exit"));
|
||||
actionIncreasePriority->setIcon(GuiIconProvider::instance()->getIcon("go-up"));
|
||||
actionTopPriority->setIcon(GuiIconProvider::instance()->getIcon("go-top"));
|
||||
actionLock_qBittorrent->setIcon(GuiIconProvider::instance()->getIcon("object-locked"));
|
||||
actionOptions->setIcon(GuiIconProvider::instance()->getIcon("preferences-system"));
|
||||
actionPause->setIcon(GuiIconProvider::instance()->getIcon("media-playback-pause"));
|
||||
actionPause_All->setIcon(GuiIconProvider::instance()->getIcon("media-playback-pause"));
|
||||
actionStart->setIcon(GuiIconProvider::instance()->getIcon("media-playback-start"));
|
||||
actionStart_All->setIcon(GuiIconProvider::instance()->getIcon("media-playback-start"));
|
||||
action_Import_Torrent->setIcon(GuiIconProvider::instance()->getIcon("document-import"));
|
||||
menuAuto_Shutdown_on_downloads_completion->setIcon(GuiIconProvider::instance()->getIcon("application-exit"));
|
||||
|
||||
QMenu *startAllMenu = new QMenu(this);
|
||||
startAllMenu->addAction(actionStart_All);
|
||||
@@ -169,14 +165,13 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
actionLock_qBittorrent->setMenu(lockMenu);
|
||||
|
||||
// Creating Bittorrent session
|
||||
connect(QBtSession::instance(), SIGNAL(fullDiskError(QTorrentHandle, QString)), this, SLOT(fullDiskError(QTorrentHandle, QString)));
|
||||
connect(QBtSession::instance(), SIGNAL(finishedTorrent(QTorrentHandle)), this, SLOT(finishedTorrent(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(trackerAuthenticationRequired(QTorrentHandle)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString)));
|
||||
connect(QBtSession::instance(), SIGNAL(newMagnetLink(QString)), this, SLOT(processNewMagnetLink(QString)));
|
||||
connect(QBtSession::instance(), SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
|
||||
connect(QBtSession::instance(), SIGNAL(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
|
||||
connect(QBtSession::instance(), SIGNAL(recursiveTorrentDownloadPossible(QTorrentHandle)), this, SLOT(askRecursiveTorrentDownloadConfirmation(QTorrentHandle)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(fullDiskError(BitTorrent::TorrentHandle *const, QString)), this, SLOT(fullDiskError(BitTorrent::TorrentHandle *const, QString)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(addTorrentFailed(const QString &)), this, SLOT(addTorrentFailed(const QString &)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), this, SLOT(finishedTorrent(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackerAuthenticationRequired(BitTorrent::TorrentHandle *const)), this, SLOT(trackerAuthenticationRequired(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(downloadFromUrlFailed(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(speedLimitModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(recursiveTorrentDownloadPossible(BitTorrent::TorrentHandle *const)), this, SLOT(askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const)));
|
||||
|
||||
qDebug("create tabWidget");
|
||||
tabs = new HidableTabWidget(this);
|
||||
@@ -200,7 +195,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
toolBar->insertWidget(searchFilterAct, spacer);
|
||||
|
||||
// Transfer List tab
|
||||
transferList = new TransferListWidget(hSplitter, this, QBtSession::instance());
|
||||
transferList = new TransferListWidget(hSplitter, this);
|
||||
properties = new PropertiesWidget(hSplitter, this, transferList);
|
||||
transferListFilters = new TransferListFiltersWidget(vSplitter, transferList);
|
||||
hSplitter->addWidget(transferList);
|
||||
@@ -209,20 +204,18 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
vSplitter->addWidget(hSplitter);
|
||||
vSplitter->setCollapsible(0, true);
|
||||
vSplitter->setCollapsible(1, false);
|
||||
tabs->addTab(vSplitter, IconProvider::instance()->getIcon("folder-remote"), tr("Transfers"));
|
||||
tabs->addTab(vSplitter, GuiIconProvider::instance()->getIcon("folder-remote"), tr("Transfers"));
|
||||
|
||||
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(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 &)));
|
||||
connect(QBtSession::instance(), SIGNAL(trackerSuccess(const QString &, const QString &)), transferListFilters, SIGNAL(trackerSuccess(const QString &, const QString &)));
|
||||
connect(QBtSession::instance(), SIGNAL(trackerError(const QString &, const QString &)), transferListFilters, SIGNAL(trackerError(const QString &, const QString &)));
|
||||
connect(QBtSession::instance(), SIGNAL(trackerWarning(const QString &, const QString &)), transferListFilters, SIGNAL(trackerWarning(const QString &, const QString &)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackersChanged(BitTorrent::TorrentHandle *const)), properties, SLOT(loadTrackers(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackersAdded(BitTorrent::TorrentHandle *const, const QList<BitTorrent::TrackerEntry> &)), transferListFilters, SLOT(addTrackers(BitTorrent::TorrentHandle *const, const QList<BitTorrent::TrackerEntry> &)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackersRemoved(BitTorrent::TorrentHandle *const, const QList<BitTorrent::TrackerEntry> &)), transferListFilters, SLOT(removeTrackers(BitTorrent::TorrentHandle *const, const QList<BitTorrent::TrackerEntry> &)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackerlessStateChanged(BitTorrent::TorrentHandle *const, bool)), transferListFilters, SLOT(changeTrackerless(BitTorrent::TorrentHandle *const, bool)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackerSuccess(BitTorrent::TorrentHandle *const, const QString &)), transferListFilters, SLOT(trackerSuccess(BitTorrent::TorrentHandle *const, const QString &)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackerError(BitTorrent::TorrentHandle *const, const QString &)), transferListFilters, SLOT(trackerError(BitTorrent::TorrentHandle *const, const QString &)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(trackerWarning(BitTorrent::TorrentHandle *const, const QString &)), transferListFilters, SLOT(trackerWarning(BitTorrent::TorrentHandle *const, const QString &)));
|
||||
|
||||
vboxLayout->addWidget(tabs);
|
||||
|
||||
@@ -231,9 +224,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
|
||||
// Transfer list slots
|
||||
connect(actionStart, SIGNAL(triggered()), transferList, SLOT(startSelectedTorrents()));
|
||||
connect(actionStart_All, SIGNAL(triggered()), QBtSession::instance(), SLOT(resumeAllTorrents()));
|
||||
connect(actionStart_All, SIGNAL(triggered()), transferList, SLOT(resumeAllTorrents()));
|
||||
connect(actionPause, SIGNAL(triggered()), transferList, SLOT(pauseSelectedTorrents()));
|
||||
connect(actionPause_All, SIGNAL(triggered()), QBtSession::instance(), SLOT(pauseAllTorrents()));
|
||||
connect(actionPause_All, SIGNAL(triggered()), transferList, SLOT(pauseAllTorrents()));
|
||||
connect(actionDelete, SIGNAL(triggered()), transferList, SLOT(deleteSelectedTorrents()));
|
||||
connect(actionTopPriority, SIGNAL(triggered()), transferList, SLOT(topPrioSelectedTorrents()));
|
||||
connect(actionIncreasePriority, SIGNAL(triggered()), transferList, SLOT(increasePrioSelectedTorrents()));
|
||||
@@ -258,10 +251,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
// Configure BT session according to options
|
||||
loadPreferences(false);
|
||||
|
||||
// Start connection checking timer
|
||||
guiUpdater = new QTimer(this);
|
||||
connect(guiUpdater, SIGNAL(timeout()), this, SLOT(updateGUI()));
|
||||
guiUpdater->start(2000);
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentsUpdated()), this, SLOT(updateGUI()));
|
||||
|
||||
// Accept drag 'n drops
|
||||
setAcceptDrops(true);
|
||||
createKeyboardShortcuts();
|
||||
@@ -516,7 +507,7 @@ void MainWindow::displayRSSTab(bool enable)
|
||||
if (!rssWidget) {
|
||||
rssWidget = new RSSImp(tabs);
|
||||
int index_tab = tabs->addTab(rssWidget, tr("RSS"));
|
||||
tabs->setTabIcon(index_tab, IconProvider::instance()->getIcon("application-rss+xml"));
|
||||
tabs->setTabIcon(index_tab, GuiIconProvider::instance()->getIcon("application-rss+xml"));
|
||||
}
|
||||
}
|
||||
else if (rssWidget) {
|
||||
@@ -532,7 +523,7 @@ void MainWindow::displaySearchTab(bool enable)
|
||||
// RSS tab
|
||||
if (!searchEngine) {
|
||||
searchEngine = new SearchEngine(this);
|
||||
tabs->insertTab(1, searchEngine, IconProvider::instance()->getIcon("edit-find"), tr("Search"));
|
||||
tabs->insertTab(1, searchEngine, GuiIconProvider::instance()->getIcon("edit-find"), tr("Search"));
|
||||
}
|
||||
}
|
||||
else if (searchEngine) {
|
||||
@@ -595,7 +586,6 @@ void MainWindow::cleanup()
|
||||
writeSettings();
|
||||
|
||||
delete executable_watcher;
|
||||
guiUpdater->stop();
|
||||
if (systrayCreator)
|
||||
systrayCreator->stop();
|
||||
if (preventTimer)
|
||||
@@ -643,18 +633,21 @@ void MainWindow::balloonClicked()
|
||||
activateWindow();
|
||||
}
|
||||
|
||||
// called when a torrent has finished
|
||||
void MainWindow::finishedTorrent(const QTorrentHandle& h) const
|
||||
void MainWindow::addTorrentFailed(const QString &error) const
|
||||
{
|
||||
if (TorrentPersistentData::instance()->isSeed(h.hash()))
|
||||
showNotificationBaloon(tr("Download completion"), tr("%1 has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(h.name()));
|
||||
showNotificationBaloon(tr("Error"), tr("Failed to add torrent: %1").arg(error));
|
||||
}
|
||||
|
||||
// called when a torrent has finished
|
||||
void MainWindow::finishedTorrent(BitTorrent::TorrentHandle *const torrent) const
|
||||
{
|
||||
showNotificationBaloon(tr("Download completion"), tr("%1 has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(torrent->name()));
|
||||
}
|
||||
|
||||
// Notification when disk is full
|
||||
void MainWindow::fullDiskError(const QTorrentHandle& h, QString msg) const
|
||||
void MainWindow::fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const
|
||||
{
|
||||
if (!h.is_valid()) return;
|
||||
showNotificationBaloon(tr("I/O Error", "i.e: Input/Output Error"), tr("An I/O error occurred for torrent %1.\n Reason: %2", "e.g: An error occurred for torrent xxx.avi.\n Reason: disk is full.").arg(h.name()).arg(msg));
|
||||
showNotificationBaloon(tr("I/O Error", "i.e: Input/Output Error"), tr("An I/O error occurred for torrent %1.\n Reason: %2", "e.g: An error occurred for torrent xxx.avi.\n Reason: disk is full.").arg(torrent->name()).arg(msg));
|
||||
}
|
||||
|
||||
void MainWindow::createKeyboardShortcuts()
|
||||
@@ -709,28 +702,21 @@ void MainWindow::displayRSSTab() const
|
||||
|
||||
// End of keyboard shortcuts slots
|
||||
|
||||
void MainWindow::askRecursiveTorrentDownloadConfirmation(const QTorrentHandle &h)
|
||||
void MainWindow::askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
if (pref->recursiveDownloadDisabled()) return;
|
||||
// Get Torrent name
|
||||
QString torrent_name;
|
||||
try {
|
||||
torrent_name = h.name();
|
||||
} catch(invalid_handle&) {
|
||||
return;
|
||||
}
|
||||
QString torrent_name = torrent->name();
|
||||
QMessageBox confirmBox(QMessageBox::Question, tr("Recursive download confirmation"), tr("The torrent %1 contains torrent files, do you want to proceed with their download?").arg(torrent_name));
|
||||
QPushButton *yes = confirmBox.addButton(tr("Yes"), QMessageBox::YesRole);
|
||||
/*QPushButton *no = */ confirmBox.addButton(tr("No"), QMessageBox::NoRole);
|
||||
QPushButton *never = confirmBox.addButton(tr("Never"), QMessageBox::NoRole);
|
||||
confirmBox.exec();
|
||||
if (confirmBox.clickedButton() == 0) return;
|
||||
if (confirmBox.clickedButton() == yes) {
|
||||
QBtSession::instance()->recursiveTorrentDownload(h);
|
||||
return;
|
||||
}
|
||||
if (confirmBox.clickedButton() == never)
|
||||
|
||||
if (confirmBox.clickedButton() == yes)
|
||||
BitTorrent::Session::instance()->recursiveTorrentDownload(torrent->hash());
|
||||
else if (confirmBox.clickedButton() == never)
|
||||
pref->disableRecursiveDownload();
|
||||
}
|
||||
|
||||
@@ -744,11 +730,11 @@ void MainWindow::on_actionSet_global_upload_limit_triggered()
|
||||
{
|
||||
qDebug("actionSet_global_upload_limit_triggered");
|
||||
bool ok;
|
||||
int cur_limit = QBtSession::instance()->getSession()->settings().upload_rate_limit;
|
||||
int cur_limit = BitTorrent::Session::instance()->uploadRateLimit();
|
||||
const long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Global Upload Speed Limit"), cur_limit);
|
||||
if (ok) {
|
||||
qDebug("Setting global upload rate limit to %.1fKb/s", new_limit / 1024.);
|
||||
QBtSession::instance()->setUploadRateLimit(new_limit);
|
||||
BitTorrent::Session::instance()->setUploadRateLimit(new_limit);
|
||||
if (new_limit <= 0)
|
||||
Preferences::instance()->setGlobalUploadLimit(-1);
|
||||
else
|
||||
@@ -760,11 +746,11 @@ void MainWindow::on_actionSet_global_download_limit_triggered()
|
||||
{
|
||||
qDebug("actionSet_global_download_limit_triggered");
|
||||
bool ok;
|
||||
int cur_limit = QBtSession::instance()->getSession()->settings().download_rate_limit;
|
||||
int cur_limit = BitTorrent::Session::instance()->downloadRateLimit();
|
||||
const long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Global Download Speed Limit"), cur_limit);
|
||||
if (ok) {
|
||||
qDebug("Setting global download rate limit to %.1fKb/s", new_limit / 1024.);
|
||||
QBtSession::instance()->setDownloadRateLimit(new_limit);
|
||||
BitTorrent::Session::instance()->setDownloadRateLimit(new_limit);
|
||||
if (new_limit <= 0)
|
||||
Preferences::instance()->setGlobalDownloadLimit(-1);
|
||||
else
|
||||
@@ -904,7 +890,7 @@ void MainWindow::closeEvent(QCloseEvent *e)
|
||||
return;
|
||||
}
|
||||
|
||||
if (pref->confirmOnExit() && QBtSession::instance()->hasActiveTorrents()) {
|
||||
if (pref->confirmOnExit() && BitTorrent::Session::instance()->hasActiveTorrents()) {
|
||||
if (e->spontaneous() || force_exit) {
|
||||
if (!isVisible())
|
||||
show();
|
||||
@@ -941,13 +927,10 @@ void MainWindow::closeEvent(QCloseEvent *e)
|
||||
// Display window to create a torrent
|
||||
void MainWindow::on_actionCreate_torrent_triggered()
|
||||
{
|
||||
if (createTorrentDlg) {
|
||||
if (createTorrentDlg)
|
||||
createTorrentDlg->setFocus();
|
||||
}
|
||||
else {
|
||||
else
|
||||
createTorrentDlg = new TorrentCreatorDlg(this);
|
||||
connect(createTorrentDlg, SIGNAL(torrent_to_seed(QString)), this, SLOT(addTorrent(QString)));
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::event(QEvent * e)
|
||||
@@ -1015,33 +998,15 @@ void MainWindow::dropEvent(QDropEvent *event)
|
||||
else {
|
||||
files = event->mimeData()->text().split(QString::fromUtf8("\n"));
|
||||
}
|
||||
|
||||
// Add file to download list
|
||||
Preferences* const pref = Preferences::instance();
|
||||
const bool useTorrentAdditionDialog = pref->useAdditionDialog();
|
||||
const bool useTorrentAdditionDialog = Preferences::instance()->useAdditionDialog();
|
||||
foreach (QString file, files) {
|
||||
qDebug("Dropped file %s on download list", qPrintable(file));
|
||||
if (misc::isUrl(file)) {
|
||||
QBtSession::instance()->downloadFromUrl(file);
|
||||
continue;
|
||||
}
|
||||
// Bitcomet or Magnet link
|
||||
if (file.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
file = misc::bcLinkToMagnet(file);
|
||||
}
|
||||
if (file.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
if (useTorrentAdditionDialog)
|
||||
AddNewTorrentDialog::showMagnet(file, this);
|
||||
else
|
||||
QBtSession::instance()->addMagnetUri(file);
|
||||
}
|
||||
else {
|
||||
// Local file
|
||||
if (useTorrentAdditionDialog)
|
||||
AddNewTorrentDialog::showTorrent(file, QString(), this);
|
||||
else
|
||||
QBtSession::instance()->addTorrent(file);
|
||||
}
|
||||
if (useTorrentAdditionDialog)
|
||||
AddNewTorrentDialog::show(file, this);
|
||||
else
|
||||
BitTorrent::Session::instance()->addTorrent(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1067,22 +1032,22 @@ void MainWindow::on_actionOpen_triggered()
|
||||
Preferences* const pref = Preferences::instance();
|
||||
// Open File Open Dialog
|
||||
// Note: it is possible to select more than one file
|
||||
const QStringList pathsList = QFileDialog::getOpenFileNames(0,
|
||||
tr("Open Torrent Files"), pref->getMainLastDir(),
|
||||
tr("Torrent Files") + QString::fromUtf8(" (*.torrent)"));
|
||||
if (!pathsList.empty()) {
|
||||
const uint listSize = pathsList.size();
|
||||
for (uint i = 0; i<listSize; ++i) {
|
||||
if (pref->useAdditionDialog())
|
||||
AddNewTorrentDialog::showTorrent(pathsList.at(i), QString(), this);
|
||||
else
|
||||
QBtSession::instance()->addTorrent(pathsList.at(i));
|
||||
}
|
||||
// Save last dir to remember it
|
||||
QStringList top_dir = fsutils::fromNativePath(pathsList.at(0)).split("/");
|
||||
top_dir.removeLast();
|
||||
pref->setMainLastDir(fsutils::fromNativePath(top_dir.join("/")));
|
||||
const QStringList pathsList =
|
||||
QFileDialog::getOpenFileNames(0, tr("Open Torrent Files"), pref->getMainLastDir(),
|
||||
tr("Torrent Files") + QString::fromUtf8(" (*.torrent)"));
|
||||
const bool useTorrentAdditionDialog = Preferences::instance()->useAdditionDialog();
|
||||
foreach (QString file, pathsList) {
|
||||
qDebug("Dropped file %s on download list", qPrintable(file));
|
||||
if (useTorrentAdditionDialog)
|
||||
AddNewTorrentDialog::show(file, this);
|
||||
else
|
||||
BitTorrent::Session::instance()->addTorrent(file);
|
||||
}
|
||||
|
||||
// Save last dir to remember it
|
||||
QStringList top_dir = fsutils::fromNativePath(pathsList.at(0)).split("/");
|
||||
top_dir.removeLast();
|
||||
pref->setMainLastDir(fsutils::fromNativePath(top_dir.join("/")));
|
||||
}
|
||||
|
||||
void MainWindow::activate()
|
||||
@@ -1094,29 +1059,6 @@ void MainWindow::activate()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addTorrent(QString path)
|
||||
{
|
||||
QBtSession::instance()->addTorrent(path);
|
||||
}
|
||||
|
||||
void MainWindow::processDownloadedFiles(QString path, QString url)
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
if (pref->useAdditionDialog())
|
||||
AddNewTorrentDialog::showTorrent(path, url, this);
|
||||
else
|
||||
QBtSession::instance()->addTorrent(path, false, url);
|
||||
}
|
||||
|
||||
void MainWindow::processNewMagnetLink(const QString& link)
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
if (pref->useAdditionDialog())
|
||||
AddNewTorrentDialog::showMagnet(link, this);
|
||||
else
|
||||
QBtSession::instance()->addMagnetUri(link);
|
||||
}
|
||||
|
||||
void MainWindow::optionsSaved()
|
||||
{
|
||||
loadPreferences();
|
||||
@@ -1175,8 +1117,6 @@ void MainWindow::loadPreferences(bool configure_session)
|
||||
m_pwr->setActivityState(false);
|
||||
}
|
||||
|
||||
const uint new_refreshInterval = pref->getRefreshInterval();
|
||||
transferList->setRefreshInterval(new_refreshInterval);
|
||||
transferList->setAlternatingRowColors(pref->useAlternatingRowColors());
|
||||
properties->getFilesList()->setAlternatingRowColors(pref->useAlternatingRowColors());
|
||||
properties->getTrackerList()->setAlternatingRowColors(pref->useAlternatingRowColors());
|
||||
@@ -1209,11 +1149,6 @@ void MainWindow::loadPreferences(bool configure_session)
|
||||
// Torrent properties
|
||||
properties->reloadPreferences();
|
||||
|
||||
// Icon provider
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
IconProvider::instance()->useSystemIconTheme(pref->useSystemIconTheme());
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
if (pref->isUpdateCheckEnabled())
|
||||
checkProgramUpdate();
|
||||
@@ -1224,7 +1159,7 @@ void MainWindow::loadPreferences(bool configure_session)
|
||||
qDebug("GUI settings loaded");
|
||||
}
|
||||
|
||||
void MainWindow::addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker)
|
||||
void MainWindow::addUnauthenticatedTracker(const QPair<BitTorrent::TorrentHandle *const, QString> &tracker)
|
||||
{
|
||||
// Trackers whose authentication was cancelled
|
||||
if (unauthenticated_trackers.indexOf(tracker) < 0)
|
||||
@@ -1232,16 +1167,18 @@ void MainWindow::addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &
|
||||
}
|
||||
|
||||
// Called when a tracker requires authentication
|
||||
void MainWindow::trackerAuthenticationRequired(const QTorrentHandle& h)
|
||||
void MainWindow::trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
if (unauthenticated_trackers.indexOf(QPair<QTorrentHandle,QString>(h, h.current_tracker())) < 0)
|
||||
if (unauthenticated_trackers.indexOf(QPair<BitTorrent::TorrentHandle *const, QString>(torrent, torrent->currentTracker())) < 0)
|
||||
// Tracker login
|
||||
new trackerLogin(this, h);
|
||||
new trackerLogin(this, torrent);
|
||||
}
|
||||
|
||||
// Check connection status and display right icon
|
||||
void MainWindow::updateGUI()
|
||||
{
|
||||
BitTorrent::SessionStatus status = BitTorrent::Session::instance()->status();
|
||||
|
||||
// update global informations
|
||||
if (systrayIcon) {
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
@@ -1249,21 +1186,21 @@ void MainWindow::updateGUI()
|
||||
html += "qBittorrent";
|
||||
html += "</div>";
|
||||
html += "<div style='vertical-align: baseline; height: 18px;'>";
|
||||
html += "<img src=':/icons/skin/download.png'/> " + tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(misc::friendlyUnit(QBtSession::instance()->getPayloadDownloadRate(), true));
|
||||
html += "<img src=':/icons/skin/download.png'/> " + tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(misc::friendlyUnit(status.payloadDownloadRate(), true));
|
||||
html += "</div>";
|
||||
html += "<div style='vertical-align: baseline; height: 18px;'>";
|
||||
html += "<img src=':/icons/skin/seeding.png'/> " + tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(misc::friendlyUnit(QBtSession::instance()->getPayloadUploadRate(), true));
|
||||
html += "<img src=':/icons/skin/seeding.png'/> " + tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(misc::friendlyUnit(status.payloadUploadRate(), true));
|
||||
html += "</div>";
|
||||
#else
|
||||
// OSes such as Windows do not support html here
|
||||
QString html = tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(misc::friendlyUnit(QBtSession::instance()->getPayloadDownloadRate(), true));
|
||||
QString html = tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(misc::friendlyUnit(status.payloadDownloadRate(), true));
|
||||
html += "\n";
|
||||
html += tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(misc::friendlyUnit(QBtSession::instance()->getPayloadUploadRate(), true));
|
||||
html += tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(misc::friendlyUnit(status.payloadUploadRate(), true));
|
||||
#endif
|
||||
systrayIcon->setToolTip(html); // tray icon
|
||||
}
|
||||
if (displaySpeedInTitle)
|
||||
setWindowTitle(tr("[D: %1, U: %2] qBittorrent %3", "D = Download; U = Upload; %3 is qBittorrent version").arg(misc::friendlyUnit(QBtSession::instance()->getPayloadDownloadRate(), true)).arg(misc::friendlyUnit(QBtSession::instance()->getPayloadUploadRate(), true)).arg(QString::fromUtf8(VERSION)));
|
||||
setWindowTitle(tr("[D: %1, U: %2] qBittorrent %3", "D = Download; U = Upload; %3 is qBittorrent version").arg(misc::friendlyUnit(status.payloadDownloadRate(), true)).arg(misc::friendlyUnit(status.payloadUploadRate(), true)).arg(QString::fromUtf8(VERSION)));
|
||||
}
|
||||
|
||||
void MainWindow::showNotificationBaloon(QString title, QString msg) const
|
||||
@@ -1302,26 +1239,16 @@ void MainWindow::showNotificationBaloon(QString title, QString msg) const
|
||||
|
||||
void MainWindow::downloadFromURLList(const QStringList& url_list)
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
const bool useTorrentAdditionDialog = pref->useAdditionDialog();
|
||||
const bool useTorrentAdditionDialog = Preferences::instance()->useAdditionDialog();
|
||||
foreach (QString url, url_list) {
|
||||
if (url.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
url = misc::bcLinkToMagnet(url);
|
||||
}
|
||||
if ((url.size() == 40 && !url.contains(QRegExp("[^0-9A-Fa-f]")))
|
||||
|| (url.size() == 32 && !url.contains(QRegExp("[^2-7A-Za-z]"))))
|
||||
url = "magnet:?xt=urn:btih:" + url;
|
||||
if (url.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
if (useTorrentAdditionDialog)
|
||||
AddNewTorrentDialog::showMagnet(url, this);
|
||||
else
|
||||
QBtSession::instance()->addMagnetUri(url);
|
||||
}
|
||||
else if (url.startsWith("http://", Qt::CaseInsensitive) || url.startsWith("https://", Qt::CaseInsensitive)
|
||||
|| url.startsWith("ftp://", Qt::CaseInsensitive)) {
|
||||
QBtSession::instance()->downloadFromUrl(url);
|
||||
}
|
||||
|
||||
if (useTorrentAdditionDialog)
|
||||
AddNewTorrentDialog::show(url, this);
|
||||
else
|
||||
BitTorrent::Session::instance()->addTorrent(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1549,7 +1476,7 @@ void MainWindow::on_actionExecution_Logs_triggered(bool checked)
|
||||
Q_ASSERT(!m_executionLog);
|
||||
m_executionLog = new ExecutionLog(tabs);
|
||||
int index_tab = tabs->addTab(m_executionLog, tr("Execution Log"));
|
||||
tabs->setTabIcon(index_tab, IconProvider::instance()->getIcon("view-calendar-journal"));
|
||||
tabs->setTabIcon(index_tab, GuiIconProvider::instance()->getIcon("view-calendar-journal"));
|
||||
}
|
||||
else if (m_executionLog) {
|
||||
delete m_executionLog;
|
||||
@@ -1583,7 +1510,7 @@ void MainWindow::on_actionAutoShutdown_system_toggled(bool enabled)
|
||||
|
||||
void MainWindow::checkForActiveTorrents()
|
||||
{
|
||||
m_pwr->setActivityState(transferList->getSourceModel()->inhibitSystem());
|
||||
m_pwr->setActivityState(BitTorrent::Session::instance()->hasActiveTorrents());
|
||||
}
|
||||
|
||||
QIcon MainWindow::getSystrayIcon() const
|
||||
@@ -1650,21 +1577,20 @@ void MainWindow::installPython()
|
||||
{
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
// Download python
|
||||
DownloadThread *pydownloader = new DownloadThread(this);
|
||||
connect(pydownloader, SIGNAL(downloadFinished(QString,QString)), this, SLOT(pythonDownloadSuccess(QString,QString)));
|
||||
connect(pydownloader, SIGNAL(downloadFailure(QString,QString)), this, SLOT(pythonDownloadFailure(QString,QString)));
|
||||
pydownloader->downloadUrl("http://python.org/ftp/python/2.7.3/python-2.7.3.msi");
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("http://python.org/ftp/python/2.7.3/python-2.7.3.msi");
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(pythonDownloadSuccess(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(pythonDownloadFailure(QString, QString)));
|
||||
}
|
||||
|
||||
void MainWindow::pythonDownloadSuccess(QString url, QString file_path)
|
||||
void MainWindow::pythonDownloadSuccess(const QString &url, const QString &filePath)
|
||||
{
|
||||
Q_UNUSED(url)
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
Q_UNUSED(url);
|
||||
QFile::rename(file_path, file_path + ".msi");
|
||||
QFile::rename(filePath, filePath + ".msi");
|
||||
QProcess installer;
|
||||
qDebug("Launching Python installer in passive mode...");
|
||||
|
||||
installer.start("msiexec.exe /passive /i " + fsutils::toNativePath(file_path) + ".msi");
|
||||
installer.start("msiexec.exe /passive /i " + fsutils::toNativePath(filePath) + ".msi");
|
||||
// Wait for setup to complete
|
||||
installer.waitForFinished();
|
||||
|
||||
@@ -1672,21 +1598,19 @@ void MainWindow::pythonDownloadSuccess(QString url, QString file_path)
|
||||
qDebug("Installer stderr: %s", installer.readAllStandardError().data());
|
||||
qDebug("Setup should be complete!");
|
||||
// Delete temp file
|
||||
fsutils::forceRemove(file_path);
|
||||
fsutils::forceRemove(filePath);
|
||||
// Reload search engine
|
||||
has_python = addPythonPathToEnv();
|
||||
if (has_python) {
|
||||
actionSearch_engine->setChecked(true);
|
||||
displaySearchTab(true);
|
||||
}
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void MainWindow::pythonDownloadFailure(QString url, QString error)
|
||||
void MainWindow::pythonDownloadFailure(const QString &url, const QString &error)
|
||||
{
|
||||
Q_UNUSED(url);
|
||||
Q_UNUSED(url)
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
QMessageBox::warning(this, tr("Download error"), tr("Python setup could not be downloaded, reason: %1.\nPlease install it manually.").arg(error));
|
||||
sender()->deleteLater();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -35,10 +35,8 @@
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QPointer>
|
||||
#include "ui_mainwindow.h"
|
||||
#include "qtorrenthandle.h"
|
||||
#include "statsdialog.h"
|
||||
|
||||
class QBtSession;
|
||||
class downloadFromURL;
|
||||
class SearchEngine;
|
||||
class RSSImp;
|
||||
@@ -64,6 +62,11 @@ class QTabWidget;
|
||||
class QTimer;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentHandle;
|
||||
}
|
||||
|
||||
class MainWindow: public QMainWindow, private Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -79,7 +82,7 @@ public:
|
||||
PropertiesWidget *getProperties() const { return properties; }
|
||||
|
||||
public slots:
|
||||
void trackerAuthenticationRequired(const QTorrentHandle& h);
|
||||
void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent);
|
||||
void setTabText(int index, QString text) const;
|
||||
void showNotificationBaloon(QString title, QString msg) const;
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
@@ -101,7 +104,7 @@ protected slots:
|
||||
void readSettings();
|
||||
void on_actionExit_triggered();
|
||||
void createTrayIcon();
|
||||
void fullDiskError(const QTorrentHandle& h, QString msg) const;
|
||||
void fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const;
|
||||
void handleDownloadFromUrlFailure(QString, QString) const;
|
||||
void createSystrayDelayed();
|
||||
void tab_changed(int);
|
||||
@@ -125,12 +128,10 @@ protected slots:
|
||||
void on_actionOpen_triggered();
|
||||
void updateGUI();
|
||||
void loadPreferences(bool configure_session = true);
|
||||
void addTorrent(QString path);
|
||||
void addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker);
|
||||
void processDownloadedFiles(QString path, QString url);
|
||||
void processNewMagnetLink(const QString& link);
|
||||
void finishedTorrent(const QTorrentHandle& h) const;
|
||||
void askRecursiveTorrentDownloadConfirmation(const QTorrentHandle &h);
|
||||
void addUnauthenticatedTracker(const QPair<BitTorrent::TorrentHandle *const, QString> &tracker);
|
||||
void addTorrentFailed(const QString &error) const;
|
||||
void finishedTorrent(BitTorrent::TorrentHandle *const torrent) const;
|
||||
void askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const torrent);
|
||||
// Options slots
|
||||
void on_actionOptions_triggered();
|
||||
void optionsSaved();
|
||||
@@ -156,18 +157,17 @@ private:
|
||||
void installPython();
|
||||
|
||||
private slots:
|
||||
void pythonDownloadSuccess(QString url, QString file_path);
|
||||
void pythonDownloadFailure(QString url, QString error);
|
||||
void pythonDownloadSuccess(const QString &url, const QString &filePath);
|
||||
void pythonDownloadFailure(const QString &url, const QString &error);
|
||||
#endif
|
||||
void addToolbarContextMenu();
|
||||
|
||||
private:
|
||||
QFileSystemWatcher *executable_watcher;
|
||||
// Bittorrent
|
||||
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; // Still needed?
|
||||
QList<QPair<BitTorrent::TorrentHandle *const, QString> > unauthenticated_trackers; // Still needed?
|
||||
// GUI related
|
||||
bool m_posInitialized;
|
||||
QTimer *guiUpdater;
|
||||
QTabWidget *tabs;
|
||||
StatusBar *status_bar;
|
||||
QPointer<options_imp> options;
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
#include "core/preferences.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "advancedsettings.h"
|
||||
#include "core/scannedfoldersmodel.h"
|
||||
#include "qbtsession.h"
|
||||
#include "iconprovider.h"
|
||||
#include "core/scanfoldersmodel.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/net/dnsupdater.h"
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
@@ -55,8 +55,6 @@
|
||||
#include <QSslCertificate>
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
// Constructor
|
||||
options_imp::options_imp(QWidget *parent):
|
||||
QDialog(parent), m_refreshingIpFilter(false) {
|
||||
@@ -65,18 +63,18 @@ options_imp::options_imp(QWidget *parent):
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setModal(true);
|
||||
// Icons
|
||||
tabSelection->item(TAB_UI)->setIcon(IconProvider::instance()->getIcon("preferences-desktop"));
|
||||
tabSelection->item(TAB_BITTORRENT)->setIcon(IconProvider::instance()->getIcon("preferences-system-network"));
|
||||
tabSelection->item(TAB_CONNECTION)->setIcon(IconProvider::instance()->getIcon("network-wired"));
|
||||
tabSelection->item(TAB_DOWNLOADS)->setIcon(IconProvider::instance()->getIcon("download"));
|
||||
tabSelection->item(TAB_SPEED)->setIcon(IconProvider::instance()->getIcon("chronometer"));
|
||||
tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop"));
|
||||
tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network"));
|
||||
tabSelection->item(TAB_CONNECTION)->setIcon(GuiIconProvider::instance()->getIcon("network-wired"));
|
||||
tabSelection->item(TAB_DOWNLOADS)->setIcon(GuiIconProvider::instance()->getIcon("download"));
|
||||
tabSelection->item(TAB_SPEED)->setIcon(GuiIconProvider::instance()->getIcon("chronometer"));
|
||||
#ifndef DISABLE_WEBUI
|
||||
tabSelection->item(TAB_WEBUI)->setIcon(IconProvider::instance()->getIcon("network-server"));
|
||||
tabSelection->item(TAB_WEBUI)->setIcon(GuiIconProvider::instance()->getIcon("network-server"));
|
||||
#else
|
||||
tabSelection->item(TAB_WEBUI)->setHidden(true);
|
||||
#endif
|
||||
tabSelection->item(TAB_ADVANCED)->setIcon(IconProvider::instance()->getIcon("preferences-other"));
|
||||
IpFilterRefreshBtn->setIcon(IconProvider::instance()->getIcon("view-refresh"));
|
||||
tabSelection->item(TAB_ADVANCED)->setIcon(GuiIconProvider::instance()->getIcon("preferences-other"));
|
||||
IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
|
||||
|
||||
hsplitter->setCollapsible(0, false);
|
||||
hsplitter->setCollapsible(1, false);
|
||||
@@ -494,7 +492,7 @@ void options_imp::saveOptions() {
|
||||
advancedSettings->saveAdvancedSettings();
|
||||
// Assume that user changed multiple settings
|
||||
// so it's best to save immediately
|
||||
pref->save();
|
||||
pref->apply();
|
||||
}
|
||||
|
||||
bool options_imp::isFilteringEnabled() const {
|
||||
@@ -1250,9 +1248,9 @@ void options_imp::on_IpFilterRefreshBtn_clicked() {
|
||||
pref->setFilteringEnabled(true);
|
||||
pref->setFilter(getFilter());
|
||||
// Force refresh
|
||||
connect(QBtSession::instance(), SIGNAL(ipFilterParsed(bool, int)), SLOT(handleIPFilterParsed(bool, int)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(ipFilterParsed(bool, int)), SLOT(handleIPFilterParsed(bool, int)));
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
QBtSession::instance()->enableIPFilter(getFilter(), true);
|
||||
BitTorrent::Session::instance()->enableIPFilter(getFilter(), true);
|
||||
}
|
||||
|
||||
void options_imp::handleIPFilterParsed(bool error, int ruleCount)
|
||||
@@ -1264,7 +1262,7 @@ void options_imp::handleIPFilterParsed(bool error, int ruleCount)
|
||||
QMessageBox::information(this, tr("Successfully refreshed"), tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount));
|
||||
}
|
||||
m_refreshingIpFilter = false;
|
||||
disconnect(QBtSession::instance(), SIGNAL(ipFilterParsed(bool, int)), this, SLOT(handleIPFilterParsed(bool, int)));
|
||||
disconnect(BitTorrent::Session::instance(), SIGNAL(ipFilterParsed(bool, int)), this, SLOT(handleIPFilterParsed(bool, int)));
|
||||
}
|
||||
|
||||
QString options_imp::languageToLocalizedString(const QLocale &locale)
|
||||
|
||||
@@ -33,16 +33,16 @@
|
||||
#include <QMessageBox>
|
||||
#include <QFile>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
#include "core/misc.h"
|
||||
#include "previewlistdelegate.h"
|
||||
#include "previewselect.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/preferences.h"
|
||||
|
||||
PreviewSelect::PreviewSelect(QWidget* parent, QTorrentHandle h): QDialog(parent), h(h) {
|
||||
PreviewSelect::PreviewSelect(QWidget* parent, BitTorrent::TorrentHandle *const torrent)
|
||||
: QDialog(parent)
|
||||
, m_torrent(torrent)
|
||||
{
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
Preferences* const pref = Preferences::instance();
|
||||
@@ -58,11 +58,10 @@ PreviewSelect::PreviewSelect(QWidget* parent, QTorrentHandle h): QDialog(parent)
|
||||
previewList->header()->resizeSection(0, 200);
|
||||
previewList->setAlternatingRowColors(pref->useAlternatingRowColors());
|
||||
// Fill list in
|
||||
std::vector<libtorrent::size_type> fp;
|
||||
h.file_progress(fp);
|
||||
unsigned int nbFiles = h.num_files();
|
||||
for (unsigned int i=0; i<nbFiles; ++i) {
|
||||
QString fileName = h.filename_at(i);
|
||||
QVector<qreal> fp = torrent->filesProgress();
|
||||
uint nbFiles = torrent->filesCount();
|
||||
for (uint i = 0; i < nbFiles; ++i) {
|
||||
QString fileName = torrent->fileName(i);
|
||||
if (fileName.endsWith(".!qB"))
|
||||
fileName.chop(4);
|
||||
QString extension = fsutils::fileExtension(fileName).toUpper();
|
||||
@@ -70,8 +69,8 @@ PreviewSelect::PreviewSelect(QWidget* parent, QTorrentHandle h): QDialog(parent)
|
||||
int row = previewListModel->rowCount();
|
||||
previewListModel->insertRow(row);
|
||||
previewListModel->setData(previewListModel->index(row, NAME), QVariant(fileName));
|
||||
previewListModel->setData(previewListModel->index(row, SIZE), QVariant((qlonglong)h.filesize_at(i)));
|
||||
previewListModel->setData(previewListModel->index(row, PROGRESS), QVariant((double)fp[i]/h.filesize_at(i)));
|
||||
previewListModel->setData(previewListModel->index(row, SIZE), QVariant(torrent->fileSize(i)));
|
||||
previewListModel->setData(previewListModel->index(row, PROGRESS), QVariant(fp[i]));
|
||||
previewListModel->setData(previewListModel->index(row, FILE_INDEX), QVariant(i));
|
||||
}
|
||||
}
|
||||
@@ -105,9 +104,9 @@ void PreviewSelect::on_previewButton_clicked() {
|
||||
QModelIndexList selectedIndexes = previewList->selectionModel()->selectedRows(FILE_INDEX);
|
||||
if (selectedIndexes.size() == 0) return;
|
||||
// Flush data
|
||||
h.flush_cache();
|
||||
m_torrent->flushCache();
|
||||
|
||||
QStringList absolute_paths(h.absolute_files_path());
|
||||
QStringList absolute_paths(m_torrent->absoluteFilePaths());
|
||||
//only one file should be selected
|
||||
QString path = absolute_paths.at(selectedIndexes.at(0).data().toInt());
|
||||
// File
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <QDialog>
|
||||
#include <QList>
|
||||
#include "ui_preview.h"
|
||||
#include "qtorrenthandle.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
|
||||
class PreviewListDelegate;
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
enum PreviewColumn { NAME, SIZE, PROGRESS, FILE_INDEX, NB_COLUMNS };
|
||||
|
||||
public:
|
||||
PreviewSelect(QWidget* parent, QTorrentHandle h);
|
||||
PreviewSelect(QWidget* parent, BitTorrent::TorrentHandle *const torrent);
|
||||
~PreviewSelect();
|
||||
|
||||
signals:
|
||||
@@ -62,8 +62,7 @@ protected slots:
|
||||
private:
|
||||
QStandardItemModel *previewListModel;
|
||||
PreviewListDelegate *listDelegate;
|
||||
QTorrentHandle h;
|
||||
|
||||
BitTorrent::TorrentHandle *const m_torrent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,28 +28,25 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "downloadedpiecesbar.h"
|
||||
|
||||
//#include <QDebug>
|
||||
|
||||
DownloadedPiecesBar::DownloadedPiecesBar(QWidget *parent): QWidget(parent)
|
||||
{
|
||||
setFixedHeight(BAR_HEIGHT);
|
||||
|
||||
bg_color = 0xffffff;
|
||||
border_color = palette().color(QPalette::Dark).rgb();
|
||||
piece_color = 0x0000ff;
|
||||
piece_color_dl = 0x00d000;
|
||||
m_bgColor = 0xffffff;
|
||||
m_borderColor = palette().color(QPalette::Dark).rgb();
|
||||
m_pieceColor = 0x0000ff;
|
||||
m_dlPieceColor = 0x00d000;
|
||||
|
||||
updatePieceColors();
|
||||
}
|
||||
|
||||
std::vector<float> DownloadedPiecesBar::bitfieldToFloatVector(const libtorrent::bitfield &vecin, int reqSize)
|
||||
QVector<float> DownloadedPiecesBar::bitfieldToFloatVector(const QBitArray &vecin, int reqSize)
|
||||
{
|
||||
std::vector<float> result(reqSize, 0.0);
|
||||
|
||||
if (vecin.empty())
|
||||
return result;
|
||||
QVector<float> result(reqSize, 0.0);
|
||||
if (vecin.isEmpty()) return result;
|
||||
|
||||
const float ratio = vecin.size() / (float)reqSize;
|
||||
|
||||
@@ -154,18 +151,18 @@ void DownloadedPiecesBar::updateImage()
|
||||
// qDebug() << "updateImage";
|
||||
QImage image2(width() - 2, 1, QImage::Format_RGB888);
|
||||
|
||||
if (pieces.empty()) {
|
||||
if (m_pieces.isEmpty()) {
|
||||
image2.fill(0xffffff);
|
||||
image = image2;
|
||||
m_image = image2;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<float> scaled_pieces = bitfieldToFloatVector(pieces, image2.width());
|
||||
std::vector<float> scaled_pieces_dl = bitfieldToFloatVector(pieces_dl, image2.width());
|
||||
QVector<float> scaled_pieces = bitfieldToFloatVector(m_pieces, image2.width());
|
||||
QVector<float> scaled_pieces_dl = bitfieldToFloatVector(m_downloadedPieces, image2.width());
|
||||
|
||||
// filling image
|
||||
for (unsigned int x = 0; x < scaled_pieces.size(); ++x)
|
||||
for (int x = 0; x < scaled_pieces.size(); ++x)
|
||||
{
|
||||
float pieces2_val = scaled_pieces.at(x);
|
||||
float pieces2_val_dl = scaled_pieces_dl.at(x);
|
||||
@@ -174,23 +171,23 @@ void DownloadedPiecesBar::updateImage()
|
||||
float fill_ratio = pieces2_val + pieces2_val_dl;
|
||||
float ratio = pieces2_val_dl / fill_ratio;
|
||||
|
||||
int mixedColor = mixTwoColors(piece_color, piece_color_dl, ratio);
|
||||
mixedColor = mixTwoColors(bg_color, mixedColor, fill_ratio);
|
||||
int mixedColor = mixTwoColors(m_pieceColor, m_dlPieceColor, ratio);
|
||||
mixedColor = mixTwoColors(m_bgColor, mixedColor, fill_ratio);
|
||||
|
||||
image2.setPixel(x, 0, mixedColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
image2.setPixel(x, 0, piece_colors[pieces2_val * 255]);
|
||||
image2.setPixel(x, 0, m_pieceColors[pieces2_val * 255]);
|
||||
}
|
||||
}
|
||||
image = image2;
|
||||
m_image = image2;
|
||||
}
|
||||
|
||||
void DownloadedPiecesBar::setProgress(const libtorrent::bitfield &bf, const libtorrent::bitfield &bf_dl)
|
||||
void DownloadedPiecesBar::setProgress(const QBitArray &pieces, const QBitArray &downloadedPieces)
|
||||
{
|
||||
pieces = libtorrent::bitfield(bf);
|
||||
pieces_dl = libtorrent::bitfield(bf_dl);
|
||||
m_pieces = pieces;
|
||||
m_downloadedPieces = downloadedPieces;
|
||||
|
||||
updateImage();
|
||||
update();
|
||||
@@ -198,16 +195,16 @@ void DownloadedPiecesBar::setProgress(const libtorrent::bitfield &bf, const libt
|
||||
|
||||
void DownloadedPiecesBar::updatePieceColors()
|
||||
{
|
||||
piece_colors = std::vector<int>(256);
|
||||
m_pieceColors = QVector<int>(256);
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
float ratio = (i / 255.0);
|
||||
piece_colors[i] = mixTwoColors(bg_color, piece_color, ratio);
|
||||
m_pieceColors[i] = mixTwoColors(m_bgColor, m_pieceColor, ratio);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadedPiecesBar::clear()
|
||||
{
|
||||
image = QImage();
|
||||
m_image = QImage();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -215,30 +212,30 @@ void DownloadedPiecesBar::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
QRect imageRect(1, 1, width() - 2, height() - 2);
|
||||
if (image.isNull())
|
||||
if (m_image.isNull())
|
||||
{
|
||||
painter.setBrush(Qt::white);
|
||||
painter.drawRect(imageRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (image.width() != imageRect.width())
|
||||
if (m_image.width() != imageRect.width())
|
||||
updateImage();
|
||||
painter.drawImage(imageRect, image);
|
||||
painter.drawImage(imageRect, m_image);
|
||||
}
|
||||
QPainterPath border;
|
||||
border.addRect(0, 0, width() - 1, height() - 1);
|
||||
|
||||
painter.setPen(border_color);
|
||||
painter.setPen(m_borderColor);
|
||||
painter.drawPath(border);
|
||||
}
|
||||
|
||||
void DownloadedPiecesBar::setColors(int background, int border, int complete, int incomplete)
|
||||
{
|
||||
bg_color = background;
|
||||
border_color = border;
|
||||
piece_color = complete;
|
||||
piece_color_dl = incomplete;
|
||||
m_bgColor = background;
|
||||
m_borderColor = border;
|
||||
m_pieceColor = complete;
|
||||
m_dlPieceColor = incomplete;
|
||||
|
||||
updatePieceColors();
|
||||
updateImage();
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include <cmath>
|
||||
#include <libtorrent/bitfield.hpp>
|
||||
#include <QBitArray>
|
||||
#include <QVector>
|
||||
|
||||
#define BAR_HEIGHT 18
|
||||
|
||||
@@ -44,28 +44,28 @@ class DownloadedPiecesBar: public QWidget {
|
||||
Q_DISABLE_COPY(DownloadedPiecesBar)
|
||||
|
||||
private:
|
||||
QImage image;
|
||||
QImage m_image;
|
||||
|
||||
// I used values, bacause it should be possible to change colors in runtime
|
||||
|
||||
// background color
|
||||
int bg_color;
|
||||
int m_bgColor;
|
||||
// border color
|
||||
int border_color;
|
||||
int m_borderColor;
|
||||
// complete piece color
|
||||
int piece_color;
|
||||
int m_pieceColor;
|
||||
// incomplete piece color
|
||||
int piece_color_dl;
|
||||
int m_dlPieceColor;
|
||||
// buffered 256 levels gradient from bg_color to piece_color
|
||||
std::vector<int> piece_colors;
|
||||
QVector<int> m_pieceColors;
|
||||
|
||||
// last used bitfields, uses to better resize redraw
|
||||
// TODO: make a diff pieces to new pieces and update only changed pixels, speedup when update > 20x faster
|
||||
libtorrent::bitfield pieces;
|
||||
libtorrent::bitfield pieces_dl;
|
||||
QBitArray m_pieces;
|
||||
QBitArray m_downloadedPieces;
|
||||
|
||||
// scale bitfield vector to float vector
|
||||
std::vector<float> bitfieldToFloatVector(const libtorrent::bitfield &vecin, int reqSize);
|
||||
QVector<float> bitfieldToFloatVector(const QBitArray &vecin, int reqSize);
|
||||
// mix two colors by light model, ratio <0, 1>
|
||||
int mixTwoColors(int &rgb1, int &rgb2, float ratio);
|
||||
// draw new image and replace actual image
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
public:
|
||||
DownloadedPiecesBar(QWidget *parent);
|
||||
|
||||
void setProgress(const libtorrent::bitfield &bf, const libtorrent::bitfield &bf_dl);
|
||||
void setProgress(const QBitArray &m_pieces, const QBitArray &downloadedPieces);
|
||||
void updatePieceColors();
|
||||
void clear();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -34,72 +34,62 @@
|
||||
#include <QDialog>
|
||||
#include <QRegExp>
|
||||
#include <QMessageBox>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "core/bittorrent/peerinfo.h"
|
||||
#include "ui_peer.h"
|
||||
|
||||
#include <libtorrent/socket.hpp>
|
||||
#include <libtorrent/address.hpp>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <libtorrent/asio/ip/tcp.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#endif
|
||||
|
||||
class PeerAdditionDlg: public QDialog, private Ui::addPeerDialog {
|
||||
Q_OBJECT
|
||||
class PeerAdditionDlg: public QDialog, private Ui::addPeerDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PeerAdditionDlg(QWidget *parent=0): QDialog(parent) {
|
||||
setupUi(this);
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(validateInput()));
|
||||
}
|
||||
|
||||
~PeerAdditionDlg() {}
|
||||
|
||||
QString getIP() const {
|
||||
QHostAddress ip(lineIP->text());
|
||||
if (!ip.isNull()) {
|
||||
// QHostAddress::toString() cleans up the IP for libtorrent
|
||||
return ip.toString();
|
||||
PeerAdditionDlg(QWidget *parent=0)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(validateInput()));
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
unsigned short getPort() const {
|
||||
return spinPort->value();
|
||||
}
|
||||
|
||||
static libtorrent::asio::ip::tcp::endpoint askForPeerEndpoint() {
|
||||
libtorrent::asio::ip::tcp::endpoint ep;
|
||||
PeerAdditionDlg dlg;
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
QString ip = dlg.getIP();
|
||||
boost::system::error_code ec;
|
||||
libtorrent::address addr = libtorrent::address::from_string(qPrintable(ip), ec);
|
||||
if (ec) {
|
||||
qDebug("Unable to parse the provided IP: %s", qPrintable(ip));
|
||||
return ep;
|
||||
}
|
||||
qDebug("Provided IP is correct");
|
||||
ep = libtorrent::asio::ip::tcp::endpoint(addr, dlg.getPort());
|
||||
~PeerAdditionDlg()
|
||||
{
|
||||
}
|
||||
|
||||
QHostAddress getAddress() const
|
||||
{
|
||||
return QHostAddress(lineIP->text());
|
||||
}
|
||||
|
||||
ushort getPort() const
|
||||
{
|
||||
return spinPort->value();
|
||||
}
|
||||
|
||||
static BitTorrent::PeerAddress askForPeerAddress()
|
||||
{
|
||||
BitTorrent::PeerAddress addr;
|
||||
|
||||
PeerAdditionDlg dlg;
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
addr.ip = dlg.getAddress();
|
||||
if (addr.ip.isNull())
|
||||
qDebug("Unable to parse the provided IP.");
|
||||
else
|
||||
qDebug("Provided IP is correct");
|
||||
addr.port = dlg.getPort();
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
||||
protected slots:
|
||||
void validateInput() {
|
||||
if (getIP().isEmpty()) {
|
||||
QMessageBox::warning(this, tr("Invalid IP"),
|
||||
tr("The IP you provided is invalid."),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
accept();
|
||||
void validateInput() {
|
||||
if (getAddress().isNull())
|
||||
QMessageBox::warning(this, tr("Invalid IP"), tr("The IP you provided is invalid."), QMessageBox::Ok);
|
||||
else
|
||||
accept();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PEERADDITION_H
|
||||
|
||||
@@ -37,19 +37,17 @@
|
||||
#include "geoipmanager.h"
|
||||
#include "peeraddition.h"
|
||||
#include "speedlimitdlg.h"
|
||||
#include "iconprovider.h"
|
||||
#include "qtorrenthandle.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "core/bittorrent/peerinfo.h"
|
||||
#include "core/logger.h"
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QSet>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QClipboard>
|
||||
#include <vector>
|
||||
#include <libtorrent/peer_info.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
PeerListWidget::PeerListWidget(PropertiesWidget *parent):
|
||||
QTreeView(parent), m_properties(parent), m_displayFlags(false)
|
||||
@@ -149,8 +147,9 @@ void PeerListWidget::showPeerListMenu(const QPoint&)
|
||||
{
|
||||
QMenu menu;
|
||||
bool empty_menu = true;
|
||||
QTorrentHandle h = m_properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) return;
|
||||
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent();
|
||||
if (!torrent) return;
|
||||
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
QStringList selectedPeerIPs;
|
||||
QStringList selectedPeerIPPort;
|
||||
@@ -163,55 +162,34 @@ void PeerListWidget::showPeerListMenu(const QPoint&)
|
||||
}
|
||||
// Add Peer Action
|
||||
QAction *addPeerAct = 0;
|
||||
if (!h.is_queued() && !h.is_checking()) {
|
||||
addPeerAct = menu.addAction(IconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer..."));
|
||||
if (!torrent->isQueued() && !torrent->isChecking()) {
|
||||
addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer..."));
|
||||
empty_menu = false;
|
||||
}
|
||||
// Per Peer Speed limiting actions
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
QAction *upLimitAct = 0;
|
||||
QAction *dlLimitAct = 0;
|
||||
#endif
|
||||
QAction *banAct = 0;
|
||||
QAction *copyPeerAct = 0;
|
||||
if (!selectedPeerIPs.isEmpty()) {
|
||||
copyPeerAct = menu.addAction(IconProvider::instance()->getIcon("edit-copy"), tr("Copy selected"));
|
||||
copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy selected"));
|
||||
menu.addSeparator();
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
dlLimitAct = menu.addAction(QIcon(":/icons/skin/download.png"), tr("Limit download rate..."));
|
||||
upLimitAct = menu.addAction(QIcon(":/icons/skin/seeding.png"), tr("Limit upload rate..."));
|
||||
menu.addSeparator();
|
||||
#endif
|
||||
banAct = menu.addAction(IconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently"));
|
||||
banAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently"));
|
||||
empty_menu = false;
|
||||
}
|
||||
if (empty_menu) return;
|
||||
QAction *act = menu.exec(QCursor::pos());
|
||||
if (act == 0) return;
|
||||
if (act == addPeerAct) {
|
||||
boost::asio::ip::tcp::endpoint ep = PeerAdditionDlg::askForPeerEndpoint();
|
||||
if (ep != boost::asio::ip::tcp::endpoint()) {
|
||||
try {
|
||||
h.connect_peer(ep);
|
||||
BitTorrent::PeerAddress addr = PeerAdditionDlg::askForPeerAddress();
|
||||
if (!addr.ip.isNull()) {
|
||||
if (torrent->connectPeer(addr))
|
||||
QMessageBox::information(0, tr("Peer addition"), tr("The peer was added to this torrent."));
|
||||
} catch(std::exception) {
|
||||
else
|
||||
QMessageBox::critical(0, tr("Peer addition"), tr("The peer could not be added to this torrent."));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
qDebug("No peer was added");
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
if (act == upLimitAct) {
|
||||
limitUpRateSelectedPeers(selectedPeerIPs);
|
||||
return;
|
||||
}
|
||||
if (act == dlLimitAct) {
|
||||
limitDlRateSelectedPeers(selectedPeerIPs);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (act == banAct) {
|
||||
banSelectedPeers(selectedPeerIPs);
|
||||
return;
|
||||
@@ -237,84 +215,16 @@ void PeerListWidget::banSelectedPeers(const QStringList& peer_ips)
|
||||
foreach (const QString &ip, peer_ips) {
|
||||
qDebug("Banning peer %s...", ip.toLocal8Bit().data());
|
||||
Logger::instance()->addMessage(tr("Manually banning peer %1...").arg(ip));
|
||||
QBtSession::instance()->banIP(ip);
|
||||
BitTorrent::Session::instance()->banIP(ip);
|
||||
}
|
||||
// Refresh list
|
||||
loadPeers(m_properties->getCurrentTorrent());
|
||||
}
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
void PeerListWidget::limitUpRateSelectedPeers(const QStringList& peer_ips)
|
||||
{
|
||||
if (peer_ips.empty())
|
||||
return;
|
||||
QTorrentHandle h = m_properties->getCurrentTorrent();
|
||||
if (!h.is_valid())
|
||||
return;
|
||||
|
||||
bool ok = false;
|
||||
int cur_limit = -1;
|
||||
boost::asio::ip::tcp::endpoint first_ep = m_peerEndpoints.value(peer_ips.first(),
|
||||
boost::asio::ip::tcp::endpoint());
|
||||
if (first_ep != boost::asio::ip::tcp::endpoint())
|
||||
cur_limit = h.get_peer_upload_limit(first_ep);
|
||||
long limit = SpeedLimitDialog::askSpeedLimit(&ok,
|
||||
tr("Upload rate limiting"),
|
||||
cur_limit,
|
||||
Preferences::instance()->getGlobalUploadLimit()*1024.);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
foreach (const QString &ip, peer_ips) {
|
||||
boost::asio::ip::tcp::endpoint ep = m_peerEndpoints.value(ip, boost::asio::ip::tcp::endpoint());
|
||||
if (ep != boost::asio::ip::tcp::endpoint()) {
|
||||
qDebug("Settings Upload limit of %.1f Kb/s to peer %s", limit/1024., ip.toLocal8Bit().data());
|
||||
try {
|
||||
h.set_peer_upload_limit(ep, limit);
|
||||
} catch(std::exception) {
|
||||
std::cerr << "Impossible to apply upload limit to peer" << std::endl;
|
||||
}
|
||||
} else {
|
||||
qDebug("The selected peer no longer exists...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListWidget::limitDlRateSelectedPeers(const QStringList& peer_ips)
|
||||
{
|
||||
QTorrentHandle h = m_properties->getCurrentTorrent();
|
||||
if (!h.is_valid())
|
||||
return;
|
||||
bool ok = false;
|
||||
int cur_limit = -1;
|
||||
boost::asio::ip::tcp::endpoint first_ep = m_peerEndpoints.value(peer_ips.first(),
|
||||
boost::asio::ip::tcp::endpoint());
|
||||
if (first_ep != boost::asio::ip::tcp::endpoint())
|
||||
cur_limit = h.get_peer_download_limit(first_ep);
|
||||
long limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Download rate limiting"), cur_limit, Preferences::instance()->getGlobalDownloadLimit()*1024.);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
foreach (const QString &ip, peer_ips) {
|
||||
boost::asio::ip::tcp::endpoint ep = m_peerEndpoints.value(ip, boost::asio::ip::tcp::endpoint());
|
||||
if (ep != boost::asio::ip::tcp::endpoint()) {
|
||||
qDebug("Settings Download limit of %.1f Kb/s to peer %s", limit/1024., ip.toLocal8Bit().data());
|
||||
try {
|
||||
h.set_peer_download_limit(ep, limit);
|
||||
}catch(std::exception) {
|
||||
std::cerr << "Impossible to apply download limit to peer" << std::endl;
|
||||
}
|
||||
} else {
|
||||
qDebug("The selected peer no longer exists...");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void PeerListWidget::clear() {
|
||||
qDebug("clearing peer list");
|
||||
m_peerItems.clear();
|
||||
m_peerEndpoints.clear();
|
||||
m_peerAddresses.clear();
|
||||
m_missingFlags.clear();
|
||||
int nbrows = m_listModel->rowCount();
|
||||
if (nbrows > 0) {
|
||||
@@ -331,34 +241,28 @@ void PeerListWidget::saveSettings() const {
|
||||
Preferences::instance()->setPeerListState(header()->saveState());
|
||||
}
|
||||
|
||||
void PeerListWidget::loadPeers(const QTorrentHandle &h, bool force_hostname_resolution) {
|
||||
if (!h.is_valid())
|
||||
return;
|
||||
boost::system::error_code ec;
|
||||
libtorrent::torrent_status status = h.status(torrent_handle::query_pieces);
|
||||
std::vector<peer_info> peers;
|
||||
h.get_peer_info(peers);
|
||||
void PeerListWidget::loadPeers(BitTorrent::TorrentHandle *const torrent, bool force_hostname_resolution) {
|
||||
if (!torrent) return;
|
||||
|
||||
QList<BitTorrent::PeerInfo> peers = torrent->peers();
|
||||
QSet<QString> old_peers_set = m_peerItems.keys().toSet();
|
||||
|
||||
std::vector<peer_info>::const_iterator itr = peers.begin();
|
||||
std::vector<peer_info>::const_iterator itrend = peers.end();
|
||||
for ( ; itr != itrend; ++itr) {
|
||||
peer_info peer = *itr;
|
||||
std::string ip_str = peer.ip.address().to_string(ec);
|
||||
if (ec || ip_str.empty())
|
||||
continue;
|
||||
QString peer_ip = misc::toQString(ip_str);
|
||||
foreach (const BitTorrent::PeerInfo &peer, peers) {
|
||||
BitTorrent::PeerAddress addr = peer.address();
|
||||
if (addr.ip.isNull()) continue;
|
||||
|
||||
QString peer_ip = addr.ip.toString();
|
||||
if (m_peerItems.contains(peer_ip)) {
|
||||
// Update existing peer
|
||||
updatePeer(peer_ip, status, peer);
|
||||
updatePeer(peer_ip, torrent, peer);
|
||||
old_peers_set.remove(peer_ip);
|
||||
if (force_hostname_resolution && m_resolver) {
|
||||
m_resolver->resolve(peer_ip);
|
||||
}
|
||||
} else {
|
||||
// Add new peer
|
||||
m_peerItems[peer_ip] = addPeer(peer_ip, status, peer);
|
||||
m_peerEndpoints[peer_ip] = peer.ip;
|
||||
m_peerItems[peer_ip] = addPeer(peer_ip, torrent, peer);
|
||||
m_peerAddresses[peer_ip] = addr;
|
||||
// Resolve peer host name is asked
|
||||
if (m_resolver)
|
||||
m_resolver->resolve(peer_ip);
|
||||
@@ -369,70 +273,70 @@ void PeerListWidget::loadPeers(const QTorrentHandle &h, bool force_hostname_reso
|
||||
while(it.hasNext()) {
|
||||
const QString& ip = it.next();
|
||||
m_missingFlags.remove(ip);
|
||||
m_peerEndpoints.remove(ip);
|
||||
m_peerAddresses.remove(ip);
|
||||
QStandardItem *item = m_peerItems.take(ip);
|
||||
m_listModel->removeRow(item->row());
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItem* PeerListWidget::addPeer(const QString& ip, const libtorrent::torrent_status &status, const peer_info& peer) {
|
||||
QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) {
|
||||
int row = m_listModel->rowCount();
|
||||
// Adding Peer to peer list
|
||||
m_listModel->insertRow(row);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip, Qt::ToolTipRole);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.ip.port());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), ip);
|
||||
if (m_displayFlags) {
|
||||
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country);
|
||||
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country());
|
||||
if (!ico.isNull()) {
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole);
|
||||
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country);
|
||||
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole);
|
||||
} else {
|
||||
m_missingFlags.insert(ip);
|
||||
}
|
||||
}
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CONNECTION), getConnectionString(peer));
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CONNECTION), peer.connectionType());
|
||||
QString flags, tooltip;
|
||||
getFlags(peer, flags, tooltip);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), flags);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), tooltip, Qt::ToolTipRole);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), misc::toQStringU(peer.client));
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payload_down_speed);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payload_up_speed);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_DOWN), (qulonglong)peer.total_download);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_UP), (qulonglong)peer.total_upload);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), getPeerRelevance(status, peer));
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_DOWN), peer.totalDownload());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_UP), peer.totalUpload());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), getPeerRelevance(torrent->pieces(), peer.pieces()));
|
||||
return m_listModel->item(row, PeerListDelegate::IP);
|
||||
}
|
||||
|
||||
void PeerListWidget::updatePeer(const QString& ip, const libtorrent::torrent_status &status, const peer_info& peer) {
|
||||
void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) {
|
||||
QStandardItem *item = m_peerItems.value(ip);
|
||||
int row = item->row();
|
||||
if (m_displayFlags) {
|
||||
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country);
|
||||
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country());
|
||||
if (!ico.isNull()) {
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole);
|
||||
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country);
|
||||
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole);
|
||||
m_missingFlags.remove(ip);
|
||||
}
|
||||
}
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CONNECTION), getConnectionString(peer));
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CONNECTION), peer.connectionType());
|
||||
QString flags, tooltip;
|
||||
getFlags(peer, flags, tooltip);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.ip.port());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), flags);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), tooltip, Qt::ToolTipRole);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), misc::toQStringU(peer.client));
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payload_down_speed);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payload_up_speed);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_DOWN), (qulonglong)peer.total_download);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_UP), (qulonglong)peer.total_upload);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), getPeerRelevance(status, peer));
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_DOWN), peer.totalDownload());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_UP), peer.totalUpload());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), getPeerRelevance(torrent->pieces(), peer.pieces()));
|
||||
}
|
||||
|
||||
void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) {
|
||||
@@ -453,34 +357,11 @@ void PeerListWidget::handleSortColumnChanged(int col)
|
||||
}
|
||||
}
|
||||
|
||||
QString PeerListWidget::getConnectionString(const peer_info& peer)
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
if (peer.connection_type & peer_info::bittorrent_utp) {
|
||||
#else
|
||||
if (peer.flags & peer_info::utp_socket) {
|
||||
#endif
|
||||
return QString::fromUtf8("μTP");
|
||||
}
|
||||
|
||||
QString connection;
|
||||
switch(peer.connection_type) {
|
||||
case peer_info::http_seed:
|
||||
case peer_info::web_seed:
|
||||
connection = "Web";
|
||||
break;
|
||||
default:
|
||||
connection = "BT";
|
||||
break;
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
void PeerListWidget::getFlags(const peer_info& peer, QString& flags, QString& tooltip)
|
||||
void PeerListWidget::getFlags(const BitTorrent::PeerInfo &peer, QString& flags, QString& tooltip)
|
||||
{
|
||||
if (peer.flags & peer_info::interesting) {
|
||||
if (peer.isInteresting()) {
|
||||
//d = Your client wants to download, but peer doesn't want to send (interested and choked)
|
||||
if (peer.flags & peer_info::remote_choked) {
|
||||
if (peer.isRemoteChocked()) {
|
||||
flags += "d ";
|
||||
tooltip += tr("interested(local) and choked(peer)");
|
||||
tooltip += ", ";
|
||||
@@ -493,9 +374,9 @@ void PeerListWidget::getFlags(const peer_info& peer, QString& flags, QString& to
|
||||
}
|
||||
}
|
||||
|
||||
if (peer.flags & peer_info::remote_interested) {
|
||||
if (peer.isRemoteInterested()) {
|
||||
//u = Peer wants your client to upload, but your client doesn't want to (interested and choked)
|
||||
if (peer.flags & peer_info::choked) {
|
||||
if (peer.isChocked()) {
|
||||
flags += "u ";
|
||||
tooltip += tr("interested(peer) and choked(local)");
|
||||
tooltip += ", ";
|
||||
@@ -509,81 +390,78 @@ void PeerListWidget::getFlags(const peer_info& peer, QString& flags, QString& to
|
||||
}
|
||||
|
||||
//O = Optimistic unchoke
|
||||
if (peer.flags & peer_info::optimistic_unchoke) {
|
||||
if (peer.optimisticUnchoke()) {
|
||||
flags += "O ";
|
||||
tooltip += tr("optimistic unchoke");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//S = Peer is snubbed
|
||||
if (peer.flags & peer_info::snubbed) {
|
||||
if (peer.isSnubbed()) {
|
||||
flags += "S ";
|
||||
tooltip += tr("peer snubbed");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//I = Peer is an incoming connection
|
||||
if ((peer.flags & peer_info::local_connection) == 0 ) {
|
||||
if (!peer.isLocalConnection()) {
|
||||
flags += "I ";
|
||||
tooltip += tr("incoming connection");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//K = Peer is unchoking your client, but your client is not interested
|
||||
if (((peer.flags & peer_info::remote_choked) == 0) && ((peer.flags & peer_info::interesting) == 0)) {
|
||||
if (!peer.isRemoteChocked() && !peer.isInteresting()) {
|
||||
flags += "K ";
|
||||
tooltip += tr("not interested(local) and unchoked(peer)");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//? = Your client unchoked the peer but the peer is not interested
|
||||
if (((peer.flags & peer_info::choked) == 0) && ((peer.flags & peer_info::remote_interested) == 0)) {
|
||||
if (!peer.isChocked() && !peer.isRemoteInterested()) {
|
||||
flags += "? ";
|
||||
tooltip += tr("not interested(peer) and unchoked(local)");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//X = Peer was included in peerlists obtained through Peer Exchange (PEX)
|
||||
if (peer.source & peer_info::pex) {
|
||||
if (peer.fromPeX()) {
|
||||
flags += "X ";
|
||||
tooltip += tr("peer from PEX");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//H = Peer was obtained through DHT
|
||||
if (peer.source & peer_info::dht) {
|
||||
if (peer.fromDHT()) {
|
||||
flags += "H ";
|
||||
tooltip += tr("peer from DHT");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//E = Peer is using Protocol Encryption (all traffic)
|
||||
if (peer.flags & peer_info::rc4_encrypted) {
|
||||
if (peer.isRC4Encrypted()) {
|
||||
flags += "E ";
|
||||
tooltip += tr("encrypted traffic");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//e = Peer is using Protocol Encryption (handshake)
|
||||
if (peer.flags & peer_info::plaintext_encrypted) {
|
||||
if (peer.isPlaintextEncrypted()) {
|
||||
flags += "e ";
|
||||
tooltip += tr("encrypted handshake");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//P = Peer is using uTorrent uTP
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
if (peer.connection_type & peer_info::bittorrent_utp) {
|
||||
#else
|
||||
if (peer.flags & peer_info::utp_socket) {
|
||||
#endif
|
||||
|
||||
if (peer.useUTPSocket()) {
|
||||
flags += "P ";
|
||||
tooltip += QString::fromUtf8("μTP");
|
||||
tooltip += ", ";
|
||||
}
|
||||
|
||||
//L = Peer is local
|
||||
if (peer.source & peer_info::lsd) {
|
||||
if (peer.fromLSD()) {
|
||||
flags += "L";
|
||||
tooltip += tr("peer from LSD");
|
||||
}
|
||||
@@ -594,17 +472,15 @@ void PeerListWidget::getFlags(const peer_info& peer, QString& flags, QString& to
|
||||
tooltip.chop(1);
|
||||
}
|
||||
|
||||
double PeerListWidget::getPeerRelevance(const torrent_status& status, const libtorrent::peer_info &peer)
|
||||
qreal PeerListWidget::getPeerRelevance(const QBitArray &allPieces, const QBitArray &peerPieces)
|
||||
{
|
||||
int localMissing = 0;
|
||||
int remoteHaves = 0;
|
||||
libtorrent::bitfield local = status.pieces;
|
||||
libtorrent::bitfield remote = peer.pieces;
|
||||
|
||||
for (int i=0; i<local.size(); ++i) {
|
||||
if (!local[i]) {
|
||||
for (int i = 0; i < allPieces.size(); ++i) {
|
||||
if (!allPieces[i]) {
|
||||
++localMissing;
|
||||
if (remote[i])
|
||||
if (peerPieces[i])
|
||||
++remoteHaves;
|
||||
}
|
||||
}
|
||||
@@ -612,5 +488,5 @@ double PeerListWidget::getPeerRelevance(const torrent_status& status, const libt
|
||||
if (localMissing == 0)
|
||||
return 0.0;
|
||||
|
||||
return (double)remoteHaves/localMissing;
|
||||
return static_cast<qreal>(remoteHaves) / localMissing;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
namespace Net
|
||||
{
|
||||
@@ -45,7 +44,6 @@ namespace Net
|
||||
class PeerListDelegate;
|
||||
class PeerListSortModel;
|
||||
class PropertiesWidget;
|
||||
class QTorrentHandle;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QSortFilterProxyModel;
|
||||
@@ -53,18 +51,14 @@ class QStandardItem;
|
||||
class QStandardItemModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace libtorrent
|
||||
namespace BitTorrent
|
||||
{
|
||||
struct peer_info;
|
||||
struct torrent_status;
|
||||
}
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <libtorrent/asio/ip/tcp.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#endif
|
||||
class TorrentHandle;
|
||||
class PeerInfo;
|
||||
struct PeerAddress;
|
||||
|
||||
}
|
||||
|
||||
class PeerListWidget : public QTreeView {
|
||||
Q_OBJECT
|
||||
@@ -74,9 +68,9 @@ public:
|
||||
~PeerListWidget();
|
||||
|
||||
public slots:
|
||||
void loadPeers(const QTorrentHandle &h, bool force_hostname_resolution = false);
|
||||
QStandardItem* addPeer(const QString& ip, const libtorrent::torrent_status &status, const libtorrent::peer_info& peer);
|
||||
void updatePeer(const QString& ip, const libtorrent::torrent_status &status, const libtorrent::peer_info& peer);
|
||||
void loadPeers(BitTorrent::TorrentHandle *const torrent, bool force_hostname_resolution = false);
|
||||
QStandardItem *addPeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer);
|
||||
void updatePeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer);
|
||||
void handleResolved(const QString &ip, const QString &hostname);
|
||||
void updatePeerHostNameResolutionState();
|
||||
void updatePeerCountryResolutionState();
|
||||
@@ -86,26 +80,19 @@ protected slots:
|
||||
void loadSettings();
|
||||
void saveSettings() const;
|
||||
void showPeerListMenu(const QPoint&);
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
void limitUpRateSelectedPeers(const QStringList& peer_ips);
|
||||
void limitDlRateSelectedPeers(const QStringList& peer_ips);
|
||||
#endif
|
||||
|
||||
void banSelectedPeers(const QStringList& peer_ips);
|
||||
void handleSortColumnChanged(int col);
|
||||
|
||||
private:
|
||||
static QString getConnectionString(const libtorrent::peer_info &peer);
|
||||
static void getFlags(const libtorrent::peer_info& peer, QString& flags, QString& tooltip);
|
||||
double getPeerRelevance(const libtorrent::torrent_status &status, const libtorrent::peer_info &peer);
|
||||
static void getFlags(const BitTorrent::PeerInfo &peer, QString &flags, QString &tooltip);
|
||||
qreal getPeerRelevance(const QBitArray &allPieces, const QBitArray &peerPieces);
|
||||
|
||||
private:
|
||||
QStandardItemModel *m_listModel;
|
||||
PeerListDelegate *m_listDelegate;
|
||||
PeerListSortModel *m_proxyModel;
|
||||
QHash<QString, QStandardItem*> m_peerItems;
|
||||
QHash<QString, boost::asio::ip::tcp::endpoint> m_peerEndpoints;
|
||||
QHash<QString, BitTorrent::PeerAddress> m_peerAddresses;
|
||||
QSet<QString> m_missingFlags;
|
||||
QPointer<Net::ReverseResolution> m_resolver;
|
||||
PropertiesWidget *m_properties;
|
||||
|
||||
@@ -28,28 +28,25 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "pieceavailabilitybar.h"
|
||||
|
||||
//#include <QDebug>
|
||||
|
||||
PieceAvailabilityBar::PieceAvailabilityBar(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
setFixedHeight(BAR_HEIGHT);
|
||||
|
||||
bg_color = 0xffffff;
|
||||
border_color = palette().color(QPalette::Dark).rgb();
|
||||
piece_color = 0x0000ff;
|
||||
m_bgColor = 0xffffff;
|
||||
m_borderColor = palette().color(QPalette::Dark).rgb();
|
||||
m_pieceColor = 0x0000ff;
|
||||
|
||||
updatePieceColors();
|
||||
}
|
||||
|
||||
std::vector<float> PieceAvailabilityBar::intToFloatVector(const std::vector<int> &vecin, int reqSize)
|
||||
QVector<float> PieceAvailabilityBar::intToFloatVector(const QVector<int> &vecin, int reqSize)
|
||||
{
|
||||
std::vector<float> result(reqSize, 0.0);
|
||||
|
||||
if (vecin.empty())
|
||||
return result;
|
||||
QVector<float> result(reqSize, 0.0);
|
||||
if (vecin.isEmpty()) return result;
|
||||
|
||||
const float ratio = vecin.size() / (float)reqSize;
|
||||
|
||||
@@ -162,27 +159,27 @@ void PieceAvailabilityBar::updateImage()
|
||||
// qDebug() << "updateImageAv";
|
||||
QImage image2(width() - 2, 1, QImage::Format_RGB888);
|
||||
|
||||
if (pieces.empty()) {
|
||||
if (m_pieces.empty()) {
|
||||
image2.fill(0xffffff);
|
||||
image = image2;
|
||||
m_image = image2;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<float> scaled_pieces = intToFloatVector(pieces, image2.width());
|
||||
QVector<float> scaled_pieces = intToFloatVector(m_pieces, image2.width());
|
||||
|
||||
// filling image
|
||||
for (unsigned int x = 0; x < scaled_pieces.size(); ++x)
|
||||
for (int x = 0; x < scaled_pieces.size(); ++x)
|
||||
{
|
||||
float pieces2_val = scaled_pieces.at(x);
|
||||
image2.setPixel(x, 0, piece_colors[pieces2_val * 255]);
|
||||
image2.setPixel(x, 0, m_pieceColors[pieces2_val * 255]);
|
||||
}
|
||||
image = image2;
|
||||
m_image = image2;
|
||||
}
|
||||
|
||||
void PieceAvailabilityBar::setAvailability(const std::vector<int>& avail)
|
||||
void PieceAvailabilityBar::setAvailability(const QVector<int> &avail)
|
||||
{
|
||||
pieces = std::vector<int>(avail);
|
||||
m_pieces = avail;
|
||||
|
||||
updateImage();
|
||||
update();
|
||||
@@ -190,16 +187,16 @@ void PieceAvailabilityBar::setAvailability(const std::vector<int>& avail)
|
||||
|
||||
void PieceAvailabilityBar::updatePieceColors()
|
||||
{
|
||||
piece_colors = std::vector<int>(256);
|
||||
m_pieceColors = QVector<int>(256);
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
float ratio = (i / 255.0);
|
||||
piece_colors[i] = mixTwoColors(bg_color, piece_color, ratio);
|
||||
m_pieceColors[i] = mixTwoColors(m_bgColor, m_pieceColor, ratio);
|
||||
}
|
||||
}
|
||||
|
||||
void PieceAvailabilityBar::clear()
|
||||
{
|
||||
image = QImage();
|
||||
m_image = QImage();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -207,29 +204,29 @@ void PieceAvailabilityBar::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
QRect imageRect(1, 1, width() - 2, height() - 2);
|
||||
if (image.isNull())
|
||||
if (m_image.isNull())
|
||||
{
|
||||
painter.setBrush(Qt::white);
|
||||
painter.drawRect(imageRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (image.width() != imageRect.width())
|
||||
if (m_image.width() != imageRect.width())
|
||||
updateImage();
|
||||
painter.drawImage(imageRect, image);
|
||||
painter.drawImage(imageRect, m_image);
|
||||
}
|
||||
QPainterPath border;
|
||||
border.addRect(0, 0, width() - 1, height() - 1);
|
||||
|
||||
painter.setPen(border_color);
|
||||
painter.setPen(m_borderColor);
|
||||
painter.drawPath(border);
|
||||
}
|
||||
|
||||
void PieceAvailabilityBar::setColors(int background, int border, int available)
|
||||
{
|
||||
bg_color = background;
|
||||
border_color = border;
|
||||
piece_color = available;
|
||||
m_bgColor = background;
|
||||
m_borderColor = border;
|
||||
m_pieceColor = available;
|
||||
|
||||
updatePieceColors();
|
||||
updateImage();
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#define BAR_HEIGHT 18
|
||||
|
||||
@@ -44,25 +42,25 @@ class PieceAvailabilityBar: public QWidget {
|
||||
Q_DISABLE_COPY(PieceAvailabilityBar)
|
||||
|
||||
private:
|
||||
QImage image;
|
||||
QImage m_image;
|
||||
|
||||
// I used values, bacause it should be possible to change colors in runtime
|
||||
|
||||
// background color
|
||||
int bg_color;
|
||||
int m_bgColor;
|
||||
// border color
|
||||
int border_color;
|
||||
int m_borderColor;
|
||||
// complete piece color
|
||||
int piece_color;
|
||||
int m_pieceColor;
|
||||
// buffered 256 levels gradient from bg_color to piece_color
|
||||
std::vector<int> piece_colors;
|
||||
QVector<int> m_pieceColors;
|
||||
|
||||
// last used int vector, uses to better resize redraw
|
||||
// TODO: make a diff pieces to new pieces and update only changed pixels, speedup when update > 20x faster
|
||||
std::vector<int> pieces;
|
||||
QVector<int> m_pieces;
|
||||
|
||||
// scale int vector to float vector
|
||||
std::vector<float> intToFloatVector(const std::vector<int> &vecin, int reqSize);
|
||||
QVector<float> intToFloatVector(const QVector<int> &vecin, int reqSize);
|
||||
|
||||
// mix two colors by light model, ratio <0, 1>
|
||||
int mixTwoColors(int &rgb1, int &rgb2, float ratio);
|
||||
@@ -72,7 +70,7 @@ private:
|
||||
public:
|
||||
PieceAvailabilityBar(QWidget *parent);
|
||||
|
||||
void setAvailability(const std::vector<int>& avail);
|
||||
void setAvailability(const QVector<int> &avail);
|
||||
void updatePieceColors();
|
||||
void clear();
|
||||
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
#include <QMenu>
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <QBitArray>
|
||||
|
||||
#include "propertieswidget.h"
|
||||
#include "transferlistwidget.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "proplistdelegate.h"
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
@@ -55,20 +55,18 @@
|
||||
#include "pieceavailabilitybar.h"
|
||||
#include "core/preferences.h"
|
||||
#include "proptabbar.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "lineedit.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow* main_window, TransferListWidget *transferList):
|
||||
QWidget(parent), transferList(transferList), main_window(main_window) {
|
||||
QWidget(parent), transferList(transferList), main_window(main_window), m_torrent(0) {
|
||||
setupUi(this);
|
||||
|
||||
// Icons
|
||||
trackerUpButton->setIcon(IconProvider::instance()->getIcon("go-up"));
|
||||
trackerDownButton->setIcon(IconProvider::instance()->getIcon("go-down"));
|
||||
trackerUpButton->setIcon(GuiIconProvider::instance()->getIcon("go-up"));
|
||||
trackerDownButton->setIcon(GuiIconProvider::instance()->getIcon("go-down"));
|
||||
|
||||
state = VISIBLE;
|
||||
|
||||
@@ -92,11 +90,11 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow* main_window, Tra
|
||||
connect(filesList, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(openDoubleClickedFile(const QModelIndex &)));
|
||||
connect(PropListModel, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
||||
connect(listWebSeeds, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayWebSeedListMenu(const QPoint&)));
|
||||
connect(transferList, SIGNAL(currentTorrentChanged(QTorrentHandle)), this, SLOT(loadTorrentInfos(QTorrentHandle)));
|
||||
connect(transferList, SIGNAL(currentTorrentChanged(BitTorrent::TorrentHandle *const)), this, SLOT(loadTorrentInfos(BitTorrent::TorrentHandle *const)));
|
||||
connect(PropDelegate, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
||||
connect(stackedProperties, SIGNAL(currentChanged(int)), this, SLOT(loadDynamicData()));
|
||||
connect(QBtSession::instance(), SIGNAL(savePathChanged(QTorrentHandle)), this, SLOT(updateSavePath(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(metadataReceived(QTorrentHandle)), this, SLOT(updateTorrentInfos(QTorrentHandle)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentSavePathChanged(BitTorrent::TorrentHandle *const)), this, SLOT(updateSavePath(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle *const)), this, SLOT(updateTorrentInfos(BitTorrent::TorrentHandle *const)));
|
||||
connect(filesList->header(), SIGNAL(sectionMoved(int, int, int)), this, SLOT(saveSettings()));
|
||||
connect(filesList->header(), SIGNAL(sectionResized(int, int, int)), this, SLOT(saveSettings()));
|
||||
connect(filesList->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(saveSettings()));
|
||||
@@ -111,9 +109,6 @@ 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(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()));
|
||||
@@ -230,61 +225,56 @@ void PropertiesWidget::clear() {
|
||||
showPiecesDownloaded(false);
|
||||
}
|
||||
|
||||
QTorrentHandle PropertiesWidget::getCurrentTorrent() const {
|
||||
return h;
|
||||
BitTorrent::TorrentHandle *PropertiesWidget::getCurrentTorrent() const
|
||||
{
|
||||
return m_torrent;
|
||||
}
|
||||
|
||||
void PropertiesWidget::updateSavePath(const QTorrentHandle& _h) {
|
||||
if (h.is_valid() && h == _h) {
|
||||
save_path->setText(fsutils::toNativePath(h.save_path_parsed()));
|
||||
void PropertiesWidget::updateSavePath(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
if (m_torrent == torrent) {
|
||||
save_path->setText(m_torrent->savePathParsed());
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::loadTrackers(const QTorrentHandle &handle)
|
||||
void PropertiesWidget::loadTrackers(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
if (handle == h)
|
||||
if (torrent == m_torrent)
|
||||
trackerList->loadTrackers();
|
||||
}
|
||||
|
||||
void PropertiesWidget::updateTorrentInfos(const QTorrentHandle& _h) {
|
||||
if (h.is_valid() && h == _h) {
|
||||
loadTorrentInfos(h);
|
||||
}
|
||||
void PropertiesWidget::updateTorrentInfos(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
if (m_torrent == torrent)
|
||||
loadTorrentInfos(m_torrent);
|
||||
}
|
||||
|
||||
void PropertiesWidget::loadTorrentInfos(const QTorrentHandle& _h)
|
||||
void PropertiesWidget::loadTorrentInfos(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
clear();
|
||||
h = _h;
|
||||
if (!h.is_valid())
|
||||
return;
|
||||
m_torrent = torrent;
|
||||
if (!m_torrent) return;
|
||||
|
||||
try {
|
||||
// Save path
|
||||
updateSavePath(h);
|
||||
updateSavePath(m_torrent);
|
||||
// Hash
|
||||
hash_lbl->setText(h.hash());
|
||||
hash_lbl->setText(m_torrent->hash());
|
||||
PropListModel->model()->clear();
|
||||
if (h.has_metadata()) {
|
||||
if (m_torrent->hasMetadata()) {
|
||||
// Creation date
|
||||
lbl_creationDate->setText(h.creation_date());
|
||||
lbl_creationDate->setText(m_torrent->creationDate().toString());
|
||||
// Piece size
|
||||
pieceSize_lbl->setText(misc::friendlyUnit(h.piece_length()));
|
||||
pieceSize_lbl->setText(misc::friendlyUnit(m_torrent->pieceLength()));
|
||||
// Comment
|
||||
comment_text->setHtml(misc::parseHtmlLinks(h.comment()));
|
||||
comment_text->setHtml(misc::parseHtmlLinks(m_torrent->comment()));
|
||||
// URL seeds
|
||||
loadUrlSeeds();
|
||||
// List files in torrent
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
PropListModel->model()->setupModelData(h.get_torrent_info());
|
||||
#else
|
||||
PropListModel->model()->setupModelData(*h.torrent_file());
|
||||
#endif
|
||||
PropListModel->model()->setupModelData(m_torrent->info());
|
||||
filesList->setExpanded(PropListModel->index(0, 0), true);
|
||||
// Load file priorities
|
||||
PropListModel->model()->updateFilesPriorities(h.file_priorities());
|
||||
PropListModel->model()->updateFilesPriorities(m_torrent->filePriorities());
|
||||
}
|
||||
} catch(const invalid_handle& e) { }
|
||||
// Load dynamic data
|
||||
loadDynamicData();
|
||||
}
|
||||
@@ -338,55 +328,44 @@ void PropertiesWidget::reloadPreferences() {
|
||||
|
||||
void PropertiesWidget::loadDynamicData() {
|
||||
// Refresh only if the torrent handle is valid and if visible
|
||||
if (!h.is_valid() || main_window->getCurrentTabWidget() != transferList || state != VISIBLE) return;
|
||||
try {
|
||||
if (!m_torrent || (main_window->getCurrentTabWidget() != transferList) || (state != VISIBLE)) return;
|
||||
|
||||
// Transfer infos
|
||||
if (stackedProperties->currentIndex() == PropTabBar::MAIN_TAB) {
|
||||
libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters
|
||||
| torrent_handle::query_distributed_copies
|
||||
| torrent_handle::query_pieces);
|
||||
|
||||
wasted->setText(misc::friendlyUnit(status.total_failed_bytes+status.total_redundant_bytes));
|
||||
upTotal->setText(misc::friendlyUnit(status.all_time_upload) + " ("+misc::friendlyUnit(status.total_payload_upload)+" "+tr("this session")+")");
|
||||
dlTotal->setText(misc::friendlyUnit(status.all_time_download) + " ("+misc::friendlyUnit(status.total_payload_download)+" "+tr("this session")+")");
|
||||
lbl_uplimit->setText(h.upload_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)"));
|
||||
lbl_dllimit->setText(h.download_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)"));
|
||||
QString elapsed_txt = misc::userFriendlyDuration(status.active_time);
|
||||
if (h.is_seed(status)) {
|
||||
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(status.seeding_time))+")";
|
||||
wasted->setText(misc::friendlyUnit(m_torrent->wastedSize()));
|
||||
upTotal->setText(misc::friendlyUnit(m_torrent->totalUpload()) + " ("+misc::friendlyUnit(m_torrent->totalPayloadUpload())+" "+tr("this session")+")");
|
||||
dlTotal->setText(misc::friendlyUnit(m_torrent->totalDownload()) + " ("+misc::friendlyUnit(m_torrent->totalPayloadDownload())+" "+tr("this session")+")");
|
||||
lbl_uplimit->setText(m_torrent->uploadLimit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(m_torrent->uploadLimit())+tr("/s", "/second (i.e. per second)"));
|
||||
lbl_dllimit->setText(m_torrent->downloadLimit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(m_torrent->downloadLimit())+tr("/s", "/second (i.e. per second)"));
|
||||
QString elapsed_txt = misc::userFriendlyDuration(m_torrent->activeTime());
|
||||
if (m_torrent->isSeed()) {
|
||||
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(m_torrent->seedingTime()))+")";
|
||||
}
|
||||
lbl_elapsed->setText(elapsed_txt);
|
||||
if (status.connections_limit > 0)
|
||||
lbl_connections->setText(QString::number(status.num_connections)+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(status.connections_limit))+")");
|
||||
if (m_torrent->connectionsLimit() > 0)
|
||||
lbl_connections->setText(QString::number(m_torrent->connectionsCount())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(m_torrent->connectionsLimit()))+")");
|
||||
else
|
||||
lbl_connections->setText(QString::number(status.num_connections));
|
||||
lbl_connections->setText(QString::number(m_torrent->connectionsLimit()));
|
||||
// Update next announce time
|
||||
reannounce_lbl->setText(misc::userFriendlyDuration(status.next_announce.total_seconds()));
|
||||
reannounce_lbl->setText(misc::userFriendlyDuration(m_torrent->nextAnnounce()));
|
||||
// Update ratio info
|
||||
const qreal ratio = QBtSession::instance()->getRealRatio(status);
|
||||
shareRatio->setText(ratio > QBtSession::MAX_RATIO ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 2));
|
||||
if (!h.is_seed(status) && status.has_metadata) {
|
||||
const qreal ratio = m_torrent->realRatio();
|
||||
shareRatio->setText(ratio > BitTorrent::TorrentHandle::MAX_RATIO ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 2));
|
||||
if (!m_torrent->isSeed() && m_torrent->hasMetadata()) {
|
||||
showPiecesDownloaded(true);
|
||||
// Downloaded pieces
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
bitfield bf(h.get_torrent_info().num_pieces(), 0);
|
||||
#else
|
||||
bitfield bf(h.torrent_file()->num_pieces(), 0);
|
||||
#endif
|
||||
h.downloading_pieces(bf);
|
||||
downloaded_pieces->setProgress(status.pieces, bf);
|
||||
downloaded_pieces->setProgress(m_torrent->pieces(), m_torrent->downloadingPieces());
|
||||
// Pieces availability
|
||||
if (!h.is_paused(status) && !h.is_queued(status) && !h.is_checking(status)) {
|
||||
if (!m_torrent->isPaused() && !m_torrent->isQueued() && !m_torrent->isChecking()) {
|
||||
showPiecesAvailability(true);
|
||||
std::vector<int> avail;
|
||||
h.piece_availability(avail);
|
||||
pieces_availability->setAvailability(avail);
|
||||
avail_average_lbl->setText(misc::accurateDoubleToString(status.distributed_copies, 3));
|
||||
pieces_availability->setAvailability(m_torrent->pieceAvailability());
|
||||
avail_average_lbl->setText(misc::accurateDoubleToString(m_torrent->distributedCopies(), 3));
|
||||
} else {
|
||||
showPiecesAvailability(false);
|
||||
}
|
||||
// Progress
|
||||
qreal progress = h.progress(status)*100.;
|
||||
qreal progress = m_torrent->progress() * 100.;
|
||||
progress_lbl->setText(misc::accurateDoubleToString(progress, 1)+"%");
|
||||
} else {
|
||||
showPiecesAvailability(false);
|
||||
@@ -401,20 +380,15 @@ void PropertiesWidget::loadDynamicData() {
|
||||
}
|
||||
if (stackedProperties->currentIndex() == PropTabBar::PEERS_TAB) {
|
||||
// Load peers
|
||||
peersList->loadPeers(h);
|
||||
peersList->loadPeers(m_torrent);
|
||||
return;
|
||||
}
|
||||
if (stackedProperties->currentIndex() == PropTabBar::FILES_TAB) {
|
||||
libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters
|
||||
| torrent_handle::query_distributed_copies
|
||||
| torrent_handle::query_pieces);
|
||||
// Files progress
|
||||
if (h.is_valid() && status.has_metadata) {
|
||||
if (m_torrent->hasMetadata()) {
|
||||
qDebug("Updating priorities in files tab");
|
||||
filesList->setUpdatesEnabled(false);
|
||||
std::vector<size_type> fp;
|
||||
h.file_progress(fp);
|
||||
PropListModel->model()->updateFilesProgress(fp);
|
||||
PropListModel->model()->updateFilesProgress(m_torrent->filesProgress());
|
||||
// XXX: We don't update file priorities regularly for performance
|
||||
// reasons. This means that priorities will not be updated if
|
||||
// set from the Web UI.
|
||||
@@ -422,25 +396,22 @@ void PropertiesWidget::loadDynamicData() {
|
||||
filesList->setUpdatesEnabled(true);
|
||||
}
|
||||
}
|
||||
} catch(const invalid_handle& e) {
|
||||
qWarning() << "Caught exception in PropertiesWidget::loadDynamicData(): " << misc::toQStringU(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::loadUrlSeeds() {
|
||||
listWebSeeds->clear();
|
||||
qDebug("Loading URL seeds");
|
||||
const QStringList hc_seeds = h.url_seeds();
|
||||
const QList<QUrl> hc_seeds = m_torrent->urlSeeds();
|
||||
// Add url seeds
|
||||
foreach (const QString &hc_seed, hc_seeds) {
|
||||
qDebug("Loading URL seed: %s", qPrintable(hc_seed));
|
||||
new QListWidgetItem(hc_seed, listWebSeeds);
|
||||
foreach (const QUrl &hc_seed, hc_seeds) {
|
||||
qDebug("Loading URL seed: %s", qPrintable(hc_seed.toString()));
|
||||
new QListWidgetItem(hc_seed.toString(), listWebSeeds);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index) {
|
||||
if (!index.isValid()) return;
|
||||
if (!h.is_valid() || !h.has_metadata()) return;
|
||||
if (!m_torrent || !m_torrent->hasMetadata()) return;
|
||||
if (PropListModel->itemType(index) == TorrentContentModelItem::FileType)
|
||||
openFile(index);
|
||||
else
|
||||
@@ -449,12 +420,12 @@ void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index) {
|
||||
|
||||
void PropertiesWidget::openFile(const QModelIndex &index) {
|
||||
int i = PropListModel->getFileIndex(index);
|
||||
const QDir saveDir(h.save_path());
|
||||
const QString filename = h.filepath_at(i);
|
||||
const QDir saveDir(m_torrent->actualSavePath());
|
||||
const QString filename = m_torrent->filePath(i);
|
||||
const QString file_path = fsutils::expandPath(saveDir.absoluteFilePath(filename));
|
||||
qDebug("Trying to open file at %s", qPrintable(file_path));
|
||||
// Flush data
|
||||
h.flush_cache();
|
||||
m_torrent->flushCache();
|
||||
if (QFile::exists(file_path)) {
|
||||
if (file_path.startsWith("//"))
|
||||
QDesktopServices::openUrl(fsutils::toNativePath("file:" + file_path));
|
||||
@@ -484,24 +455,24 @@ void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_fold
|
||||
if (containing_folder)
|
||||
path_items.removeLast();
|
||||
#endif
|
||||
const QDir saveDir(h.save_path());
|
||||
const QDir saveDir(m_torrent->actualSavePath());
|
||||
const QString relative_path = path_items.join("/");
|
||||
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
||||
}
|
||||
else {
|
||||
int i = PropListModel->getFileIndex(index);
|
||||
const QDir saveDir(h.save_path());
|
||||
const QString relative_path = h.filepath_at(i);
|
||||
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
||||
int i = PropListModel->getFileIndex(index);
|
||||
const QDir saveDir(m_torrent->actualSavePath());
|
||||
const QString relative_path = m_torrent->filePath(i);
|
||||
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
||||
|
||||
#if !(defined(Q_OS_WIN) || (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)))
|
||||
if (containing_folder)
|
||||
absolute_path = fsutils::folderName(absolute_path);
|
||||
if (containing_folder)
|
||||
absolute_path = fsutils::folderName(absolute_path);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Flush data
|
||||
h.flush_cache();
|
||||
m_torrent->flushCache();
|
||||
if (!QFile::exists(absolute_path))
|
||||
return;
|
||||
qDebug("Trying to open folder at %s", qPrintable(absolute_path));
|
||||
@@ -544,8 +515,8 @@ void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_fold
|
||||
}
|
||||
|
||||
void PropertiesWidget::displayFilesListMenu(const QPoint&) {
|
||||
if (!h.is_valid())
|
||||
return;
|
||||
if (!m_torrent) return;
|
||||
|
||||
QModelIndexList selectedRows = filesList->selectionModel()->selectedRows(0);
|
||||
if (selectedRows.empty())
|
||||
return;
|
||||
@@ -554,13 +525,13 @@ void PropertiesWidget::displayFilesListMenu(const QPoint&) {
|
||||
QAction *actOpenContainingFolder = 0;
|
||||
QAction *actRename = 0;
|
||||
if (selectedRows.size() == 1) {
|
||||
actOpen = myFilesLlistMenu.addAction(IconProvider::instance()->getIcon("folder-documents"), tr("Open"));
|
||||
actOpenContainingFolder = myFilesLlistMenu.addAction(IconProvider::instance()->getIcon("inode-directory"), tr("Open Containing Folder"));
|
||||
actRename = myFilesLlistMenu.addAction(IconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
|
||||
actOpen = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("folder-documents"), tr("Open"));
|
||||
actOpenContainingFolder = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open Containing Folder"));
|
||||
actRename = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
|
||||
myFilesLlistMenu.addSeparator();
|
||||
}
|
||||
QMenu subMenu;
|
||||
if (!h.status(0x0).is_seeding) {
|
||||
if (!m_torrent->isSeed()) {
|
||||
subMenu.setTitle(tr("Priority"));
|
||||
subMenu.addAction(actionNot_downloaded);
|
||||
subMenu.addAction(actionNormal);
|
||||
@@ -603,20 +574,20 @@ void PropertiesWidget::displayFilesListMenu(const QPoint&) {
|
||||
}
|
||||
|
||||
void PropertiesWidget::displayWebSeedListMenu(const QPoint&) {
|
||||
if (!h.is_valid())
|
||||
return;
|
||||
if (!m_torrent) return;
|
||||
|
||||
QMenu seedMenu;
|
||||
QModelIndexList rows = listWebSeeds->selectionModel()->selectedRows();
|
||||
QAction *actAdd = seedMenu.addAction(IconProvider::instance()->getIcon("list-add"), tr("New Web seed"));
|
||||
QAction *actAdd = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New Web seed"));
|
||||
QAction *actDel = 0;
|
||||
QAction *actCpy = 0;
|
||||
QAction *actEdit = 0;
|
||||
|
||||
if (rows.size()) {
|
||||
actDel = seedMenu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed"));
|
||||
actDel = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed"));
|
||||
seedMenu.addSeparator();
|
||||
actCpy = seedMenu.addAction(IconProvider::instance()->getIcon("edit-copy"), tr("Copy Web seed URL"));
|
||||
actEdit = seedMenu.addAction(IconProvider::instance()->getIcon("edit-rename"), tr("Edit Web seed URL"));
|
||||
actCpy = seedMenu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy Web seed URL"));
|
||||
actEdit = seedMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Edit Web seed URL"));
|
||||
}
|
||||
|
||||
const QAction *act = seedMenu.exec(QCursor::pos());
|
||||
@@ -654,8 +625,8 @@ void PropertiesWidget::renameSelectedFile() {
|
||||
if (PropListModel->itemType(index) == TorrentContentModelItem::FileType) {
|
||||
// File renaming
|
||||
const int file_index = PropListModel->getFileIndex(index);
|
||||
if (!h.is_valid() || !h.has_metadata()) return;
|
||||
QString old_name = h.filepath_at(file_index);
|
||||
if (!m_torrent || !m_torrent->hasMetadata()) return;
|
||||
QString old_name = m_torrent->filePath(file_index);
|
||||
if (old_name.endsWith(".!qB") && !new_name_last.endsWith(".!qB")) {
|
||||
new_name_last += ".!qB";
|
||||
}
|
||||
@@ -669,12 +640,12 @@ void PropertiesWidget::renameSelectedFile() {
|
||||
}
|
||||
new_name = fsutils::expandPath(new_name);
|
||||
// Check if that name is already used
|
||||
for (int i=0; i<h.num_files(); ++i) {
|
||||
for (int i = 0; i < m_torrent->filesCount(); ++i) {
|
||||
if (i == file_index) continue;
|
||||
#if defined(Q_OS_UNIX) || defined(Q_WS_QWS)
|
||||
if (h.filepath_at(i).compare(new_name, Qt::CaseSensitive) == 0) {
|
||||
if (m_torrent->filePath(i).compare(new_name, Qt::CaseSensitive) == 0) {
|
||||
#else
|
||||
if (h.filepath_at(i).compare(new_name, Qt::CaseInsensitive) == 0) {
|
||||
if (m_torrent->filePath(i).compare(new_name, Qt::CaseInsensitive) == 0) {
|
||||
#endif
|
||||
// Display error message
|
||||
QMessageBox::warning(this, tr("The file could not be renamed"),
|
||||
@@ -683,11 +654,11 @@ void PropertiesWidget::renameSelectedFile() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const bool force_recheck = QFile::exists(h.save_path()+"/"+new_name);
|
||||
const bool force_recheck = QFile::exists(m_torrent->actualSavePath() + "/" + new_name);
|
||||
qDebug("Renaming %s to %s", qPrintable(old_name), qPrintable(new_name));
|
||||
h.rename_file(file_index, new_name);
|
||||
m_torrent->renameFile(file_index, new_name);
|
||||
// Force recheck
|
||||
if (force_recheck) h.force_recheck();
|
||||
if (force_recheck) m_torrent->forceRecheck();
|
||||
// Rename if torrent files model too
|
||||
if (new_name_last.endsWith(".!qB"))
|
||||
new_name_last.chop(4);
|
||||
@@ -707,9 +678,9 @@ void PropertiesWidget::renameSelectedFile() {
|
||||
QString new_path = path_items.join("/");
|
||||
if (!new_path.endsWith("/")) new_path += "/";
|
||||
// Check for overwriting
|
||||
const int num_files = h.num_files();
|
||||
const int num_files = m_torrent->filesCount();
|
||||
for (int i=0; i<num_files; ++i) {
|
||||
const QString current_name = h.filepath_at(i);
|
||||
const QString current_name = m_torrent->filePath(i);
|
||||
#if defined(Q_OS_UNIX) || defined(Q_WS_QWS)
|
||||
if (current_name.startsWith(new_path, Qt::CaseSensitive)) {
|
||||
#else
|
||||
@@ -724,23 +695,23 @@ void PropertiesWidget::renameSelectedFile() {
|
||||
bool force_recheck = false;
|
||||
// Replace path in all files
|
||||
for (int i=0; i<num_files; ++i) {
|
||||
const QString current_name = h.filepath_at(i);
|
||||
const QString current_name = m_torrent->filePath(i);
|
||||
if (current_name.startsWith(old_path)) {
|
||||
QString new_name = current_name;
|
||||
new_name.replace(0, old_path.length(), new_path);
|
||||
if (!force_recheck && QDir(h.save_path()).exists(new_name))
|
||||
if (!force_recheck && QDir(m_torrent->actualSavePath()).exists(new_name))
|
||||
force_recheck = true;
|
||||
new_name = fsutils::expandPath(new_name);
|
||||
qDebug("Rename %s to %s", qPrintable(current_name), qPrintable(new_name));
|
||||
h.rename_file(i, new_name);
|
||||
m_torrent->renameFile(i, new_name);
|
||||
}
|
||||
}
|
||||
// Force recheck
|
||||
if (force_recheck) h.force_recheck();
|
||||
if (force_recheck) m_torrent->forceRecheck();
|
||||
// Rename folder in torrent files model too
|
||||
PropListModel->setData(index, new_name_last);
|
||||
// Remove old folder
|
||||
const QDir old_folder(h.save_path()+"/"+old_path);
|
||||
const QDir old_folder(m_torrent->actualSavePath() + "/" + old_path);
|
||||
int timeout = 10;
|
||||
while(!QDir().rmpath(old_folder.absolutePath()) && timeout > 0) {
|
||||
// XXX: We should not sleep here (freezes the UI for 1 second)
|
||||
@@ -765,28 +736,23 @@ void PropertiesWidget::askWebSeed() {
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (h.is_valid())
|
||||
h.add_url_seed(url_seed);
|
||||
if (m_torrent)
|
||||
m_torrent->addUrlSeeds(QList<QUrl>() << url_seed);
|
||||
// Refresh the seeds list
|
||||
loadUrlSeeds();
|
||||
}
|
||||
|
||||
void PropertiesWidget::deleteSelectedUrlSeeds() {
|
||||
const QList<QListWidgetItem *> selectedItems = listWebSeeds->selectedItems();
|
||||
if (selectedItems.isEmpty())
|
||||
return;
|
||||
bool change = false;
|
||||
foreach (const QListWidgetItem *item, selectedItems) {
|
||||
QString url_seed = item->text();
|
||||
try {
|
||||
h.remove_url_seed(url_seed);
|
||||
change = true;
|
||||
} catch (invalid_handle&) {}
|
||||
}
|
||||
if (change) {
|
||||
// Refresh list
|
||||
loadUrlSeeds();
|
||||
}
|
||||
if (selectedItems.isEmpty()) return;
|
||||
|
||||
QList<QUrl> urlSeeds;
|
||||
foreach (const QListWidgetItem *item, selectedItems)
|
||||
urlSeeds << item->text();
|
||||
|
||||
m_torrent->removeUrlSeeds(urlSeeds);
|
||||
// Refresh list
|
||||
loadUrlSeeds();
|
||||
}
|
||||
|
||||
void PropertiesWidget::copySelectedWebSeedsToClipboard() const {
|
||||
@@ -822,31 +788,28 @@ void PropertiesWidget::editWebSeed() {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
h.remove_url_seed(old_seed);
|
||||
h.add_url_seed(new_seed);
|
||||
loadUrlSeeds();
|
||||
} catch (invalid_handle&) {}
|
||||
m_torrent->removeUrlSeeds(QList<QUrl>() << old_seed);
|
||||
m_torrent->addUrlSeeds(QList<QUrl>() << new_seed);
|
||||
loadUrlSeeds();
|
||||
}
|
||||
|
||||
bool PropertiesWidget::applyPriorities() {
|
||||
qDebug("Saving files priorities");
|
||||
const std::vector<int> priorities = PropListModel->model()->getFilesPriorities();
|
||||
const QVector<int> priorities = PropListModel->model()->getFilePriorities();
|
||||
// Save first/last piece first option state
|
||||
bool first_last_piece_first = h.first_last_piece_first();
|
||||
bool first_last_piece_first = m_torrent->hasFirstLastPiecePriority();
|
||||
// Prioritize the files
|
||||
qDebug("prioritize files: %d", priorities[0]);
|
||||
h.prioritize_files(priorities);
|
||||
m_torrent->prioritizeFiles(priorities);
|
||||
// Restore first/last piece first option if necessary
|
||||
if (first_last_piece_first)
|
||||
h.prioritize_first_last_piece(true);
|
||||
m_torrent->setFirstLastPiecePriority(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertiesWidget::filteredFilesChanged() {
|
||||
if (h.is_valid()) {
|
||||
if (m_torrent)
|
||||
applyPriorities();
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::filterText(const QString& filter) {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <QShortcut>
|
||||
#include <QWidget>
|
||||
#include "ui_propertieswidget.h"
|
||||
#include "qtorrenthandle.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
|
||||
|
||||
class TransferListWidget;
|
||||
@@ -64,23 +64,18 @@ public:
|
||||
public:
|
||||
PropertiesWidget(QWidget *parent, MainWindow* main_window, TransferListWidget *transferList);
|
||||
~PropertiesWidget();
|
||||
QTorrentHandle getCurrentTorrent() const;
|
||||
BitTorrent::TorrentHandle *getCurrentTorrent() const;
|
||||
TrackerList* getTrackerList() const { return trackerList; }
|
||||
PeerListWidget* getPeerList() const { return peersList; }
|
||||
QTreeView* getFilesList() const { return filesList; }
|
||||
|
||||
signals:
|
||||
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);
|
||||
bool applyPriorities();
|
||||
|
||||
protected slots:
|
||||
void loadTorrentInfos(const QTorrentHandle &h);
|
||||
void updateTorrentInfos(const QTorrentHandle &h);
|
||||
void loadTorrentInfos(BitTorrent::TorrentHandle *const torrent);
|
||||
void updateTorrentInfos(BitTorrent::TorrentHandle *const torrent);
|
||||
void loadUrlSeeds();
|
||||
void askWebSeed();
|
||||
void deleteSelectedUrlSeeds();
|
||||
@@ -101,8 +96,8 @@ public slots:
|
||||
void saveSettings();
|
||||
void reloadPreferences();
|
||||
void openDoubleClickedFile(const QModelIndex &);
|
||||
void updateSavePath(const QTorrentHandle& h);
|
||||
void loadTrackers(const QTorrentHandle &handle);
|
||||
void updateSavePath(BitTorrent::TorrentHandle *const torrent);
|
||||
void loadTrackers(BitTorrent::TorrentHandle *const torrent);
|
||||
|
||||
private:
|
||||
void openFile(const QModelIndex &index);
|
||||
@@ -111,7 +106,7 @@ private:
|
||||
private:
|
||||
TransferListWidget *transferList;
|
||||
MainWindow *main_window;
|
||||
QTorrentHandle h;
|
||||
BitTorrent::TorrentHandle *m_torrent;
|
||||
QTimer *refreshTimer;
|
||||
SlideState state;
|
||||
TorrentContentFilterModel *PropListModel;
|
||||
|
||||
@@ -154,8 +154,8 @@ public:
|
||||
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &index) const {
|
||||
if (index.column() != PRIORITY) return 0;
|
||||
if (properties) {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid() || !h.has_metadata() || h.status(0x0).is_seeding)
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent || !torrent->hasMetadata() || torrent->isSeed())
|
||||
return 0;
|
||||
}
|
||||
if (index.data().toInt() <= 0) {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <QKeySequence>
|
||||
|
||||
#include "proptabbar.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
|
||||
PropTabBar::PropTabBar(QWidget *parent) :
|
||||
QHBoxLayout(parent), m_currentIndex(-1)
|
||||
@@ -42,24 +42,24 @@ PropTabBar::PropTabBar(QWidget *parent) :
|
||||
setSpacing(2);
|
||||
m_btnGroup = new QButtonGroup(this);
|
||||
// General tab
|
||||
QPushButton *main_infos_button = new QPushButton(IconProvider::instance()->getIcon("document-properties"), tr("General"), parent);
|
||||
QPushButton *main_infos_button = new QPushButton(GuiIconProvider::instance()->getIcon("document-properties"), tr("General"), parent);
|
||||
main_infos_button->setShortcut(QKeySequence(QString::fromUtf8("Alt+P")));
|
||||
addWidget(main_infos_button);
|
||||
m_btnGroup->addButton(main_infos_button, MAIN_TAB);
|
||||
// Trackers tab
|
||||
QPushButton *trackers_button = new QPushButton(IconProvider::instance()->getIcon("network-server"), tr("Trackers"), parent);
|
||||
QPushButton *trackers_button = new QPushButton(GuiIconProvider::instance()->getIcon("network-server"), tr("Trackers"), parent);
|
||||
addWidget(trackers_button);
|
||||
m_btnGroup->addButton(trackers_button, TRACKERS_TAB);
|
||||
// Peers tab
|
||||
QPushButton *peers_button = new QPushButton(IconProvider::instance()->getIcon("edit-find-user"), tr("Peers"), parent);
|
||||
QPushButton *peers_button = new QPushButton(GuiIconProvider::instance()->getIcon("edit-find-user"), tr("Peers"), parent);
|
||||
addWidget(peers_button);
|
||||
m_btnGroup->addButton(peers_button, PEERS_TAB);
|
||||
// URL seeds tab
|
||||
QPushButton *urlseeds_button = new QPushButton(IconProvider::instance()->getIcon("network-server"), tr("HTTP Sources"), parent);
|
||||
QPushButton *urlseeds_button = new QPushButton(GuiIconProvider::instance()->getIcon("network-server"), tr("HTTP Sources"), parent);
|
||||
addWidget(urlseeds_button);
|
||||
m_btnGroup->addButton(urlseeds_button, URLSEEDS_TAB);
|
||||
// Files tab
|
||||
QPushButton *files_button = new QPushButton(IconProvider::instance()->getIcon("inode-directory"), tr("Content"), parent);
|
||||
QPushButton *files_button = new QPushButton(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Content"), parent);
|
||||
addWidget(files_button);
|
||||
m_btnGroup->addButton(files_button, FILES_TAB);
|
||||
// Spacer
|
||||
|
||||
@@ -36,19 +36,18 @@
|
||||
#include <QColor>
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/peer_info.hpp>
|
||||
#include "trackerlist.h"
|
||||
#include "propertieswidget.h"
|
||||
#include "trackersadditiondlg.h"
|
||||
#include "iconprovider.h"
|
||||
#include "qbtsession.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "core/bittorrent/peerinfo.h"
|
||||
#include "core/bittorrent/trackerentry.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/misc.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
TrackerList::TrackerList(PropertiesWidget *properties): QTreeWidget(), properties(properties) {
|
||||
// Graphical settings
|
||||
setRootIsDecorated(false);
|
||||
@@ -108,8 +107,8 @@ void TrackerList::setRowColor(int row, QColor color) {
|
||||
}
|
||||
|
||||
void TrackerList::moveSelectionUp() {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) {
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
@@ -131,23 +130,23 @@ void TrackerList::moveSelectionUp() {
|
||||
}
|
||||
setSelectionModel(selection);
|
||||
// Update torrent trackers
|
||||
std::vector<announce_entry> trackers;
|
||||
for (int i=NB_STICKY_ITEM; i<topLevelItemCount(); ++i) {
|
||||
QList<BitTorrent::TrackerEntry> trackers;
|
||||
for (int i = NB_STICKY_ITEM; i < topLevelItemCount(); ++i) {
|
||||
QString tracker_url = topLevelItem(i)->data(COL_URL, Qt::DisplayRole).toString();
|
||||
announce_entry e(tracker_url.toStdString());
|
||||
e.tier = i-NB_STICKY_ITEM;
|
||||
trackers.push_back(e);
|
||||
BitTorrent::TrackerEntry e(tracker_url);
|
||||
e.setTier(i - NB_STICKY_ITEM);
|
||||
trackers.append(e);
|
||||
}
|
||||
h.replace_trackers(trackers);
|
||||
|
||||
torrent->replaceTrackers(trackers);
|
||||
// Reannounce
|
||||
if (!h.is_paused())
|
||||
h.force_reannounce();
|
||||
loadTrackers();
|
||||
if (!torrent->isPaused())
|
||||
torrent->forceReannounce();
|
||||
}
|
||||
|
||||
void TrackerList::moveSelectionDown() {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) {
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
@@ -169,18 +168,18 @@ void TrackerList::moveSelectionDown() {
|
||||
}
|
||||
setSelectionModel(selection);
|
||||
// Update torrent trackers
|
||||
std::vector<announce_entry> trackers;
|
||||
for (int i=NB_STICKY_ITEM; i<topLevelItemCount(); ++i) {
|
||||
QList<BitTorrent::TrackerEntry> trackers;
|
||||
for (int i = NB_STICKY_ITEM; i < topLevelItemCount(); ++i) {
|
||||
QString tracker_url = topLevelItem(i)->data(COL_URL, Qt::DisplayRole).toString();
|
||||
announce_entry e(tracker_url.toStdString());
|
||||
e.tier = i-NB_STICKY_ITEM;
|
||||
trackers.push_back(e);
|
||||
BitTorrent::TrackerEntry e(tracker_url);
|
||||
e.setTier(i - NB_STICKY_ITEM);
|
||||
trackers.append(e);
|
||||
}
|
||||
h.replace_trackers(trackers);
|
||||
|
||||
torrent->replaceTrackers(trackers);
|
||||
// Reannounce
|
||||
if (!h.is_paused())
|
||||
h.force_reannounce();
|
||||
loadTrackers();
|
||||
if (!torrent->isPaused())
|
||||
torrent->forceReannounce();
|
||||
}
|
||||
|
||||
void TrackerList::clear() {
|
||||
@@ -197,29 +196,29 @@ void TrackerList::clear() {
|
||||
lsd_item->setText(COL_MSG, "");
|
||||
}
|
||||
|
||||
void TrackerList::loadStickyItems(const QTorrentHandle &h) {
|
||||
void TrackerList::loadStickyItems(BitTorrent::TorrentHandle *const torrent) {
|
||||
QString working = tr("Working");
|
||||
QString disabled = tr("Disabled");
|
||||
|
||||
// load DHT information
|
||||
if (QBtSession::instance()->isDHTEnabled() && !h.priv())
|
||||
if (BitTorrent::Session::instance()->isDHTEnabled() && !torrent->isPrivate())
|
||||
dht_item->setText(COL_STATUS, working);
|
||||
else
|
||||
dht_item->setText(COL_STATUS, disabled);
|
||||
|
||||
// Load PeX Information
|
||||
if (QBtSession::instance()->isPexEnabled() && !h.priv())
|
||||
if (BitTorrent::Session::instance()->isPexEnabled() && !torrent->isPrivate())
|
||||
pex_item->setText(COL_STATUS, working);
|
||||
else
|
||||
pex_item->setText(COL_STATUS, disabled);
|
||||
|
||||
// Load LSD Information
|
||||
if (QBtSession::instance()->isLSDEnabled() && !h.priv())
|
||||
if (BitTorrent::Session::instance()->isLSDEnabled() && !torrent->isPrivate())
|
||||
lsd_item->setText(COL_STATUS, working);
|
||||
else
|
||||
lsd_item->setText(COL_STATUS, disabled);
|
||||
|
||||
if (h.priv()) {
|
||||
if (torrent->isPrivate()) {
|
||||
QString privateMsg = tr("This torrent is private");
|
||||
dht_item->setText(COL_MSG, privateMsg);
|
||||
pex_item->setText(COL_MSG, privateMsg);
|
||||
@@ -229,16 +228,12 @@ void TrackerList::loadStickyItems(const QTorrentHandle &h) {
|
||||
// XXX: libtorrent should provide this info...
|
||||
// Count peers from DHT, LSD, PeX
|
||||
uint nb_dht = 0, nb_lsd = 0, nb_pex = 0;
|
||||
std::vector<peer_info> peers;
|
||||
h.get_peer_info(peers);
|
||||
std::vector<peer_info>::iterator it = peers.begin();
|
||||
std::vector<peer_info>::iterator end = peers.end();
|
||||
for ( ; it != end; ++it) {
|
||||
if (it->source & peer_info::dht)
|
||||
foreach (const BitTorrent::PeerInfo &peer, torrent->peers()) {
|
||||
if (peer.fromDHT())
|
||||
++nb_dht;
|
||||
if (it->source & peer_info::lsd)
|
||||
if (peer.fromLSD())
|
||||
++nb_lsd;
|
||||
if (it->source & peer_info::pex)
|
||||
if (peer.fromPeX())
|
||||
++nb_pex;
|
||||
}
|
||||
dht_item->setText(COL_PEERS, QString::number(nb_dht));
|
||||
@@ -248,47 +243,47 @@ void TrackerList::loadStickyItems(const QTorrentHandle &h) {
|
||||
|
||||
void TrackerList::loadTrackers() {
|
||||
// Load trackers from torrent handle
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) return;
|
||||
loadStickyItems(h);
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) return;
|
||||
|
||||
loadStickyItems(torrent);
|
||||
// Load actual trackers information
|
||||
QHash<QString, TrackerInfos> trackers_data = QBtSession::instance()->getTrackersInfo(h.hash());
|
||||
QHash<QString, BitTorrent::TrackerInfo> trackers_data = torrent->trackerInfos();
|
||||
QStringList old_trackers_urls = tracker_items.keys();
|
||||
const std::vector<announce_entry> trackers = h.trackers();
|
||||
std::vector<announce_entry>::const_iterator it = trackers.begin();
|
||||
std::vector<announce_entry>::const_iterator end = trackers.end();
|
||||
for ( ; it != end; ++it) {
|
||||
QString tracker_url = misc::toQString(it->url);
|
||||
QTreeWidgetItem *item = tracker_items.value(tracker_url, 0);
|
||||
foreach (const BitTorrent::TrackerEntry &entry, torrent->trackers()) {
|
||||
QString trackerUrl = entry.url();
|
||||
QTreeWidgetItem *item = tracker_items.value(trackerUrl, 0);
|
||||
if (!item) {
|
||||
item = new QTreeWidgetItem();
|
||||
item->setText(COL_URL, tracker_url);
|
||||
item->setText(COL_URL, trackerUrl);
|
||||
addTopLevelItem(item);
|
||||
tracker_items[tracker_url] = item;
|
||||
tracker_items[trackerUrl] = item;
|
||||
} else {
|
||||
old_trackers_urls.removeOne(tracker_url);
|
||||
old_trackers_urls.removeOne(trackerUrl);
|
||||
}
|
||||
item->setText(COL_TIER, QString::number(it->tier));
|
||||
TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||
QString error_message = data.last_message.trimmed();
|
||||
if (it->verified) {
|
||||
item->setText(COL_STATUS, tr("Working"));
|
||||
item->setText(COL_MSG, "");
|
||||
} else {
|
||||
if (it->updating && it->fails == 0) {
|
||||
item->setText(COL_TIER, QString::number(entry.tier()));
|
||||
BitTorrent::TrackerInfo data = trackers_data.value(trackerUrl);
|
||||
QString error_message = data.lastMessage.trimmed();
|
||||
switch (entry.status()) {
|
||||
case BitTorrent::TrackerEntry::Working:
|
||||
item->setText(COL_STATUS, tr("Working"));
|
||||
item->setText(COL_MSG, "");
|
||||
break;
|
||||
case BitTorrent::TrackerEntry::Updating:
|
||||
item->setText(COL_STATUS, tr("Updating..."));
|
||||
item->setText(COL_MSG, "");
|
||||
} else {
|
||||
if (it->fails > 0) {
|
||||
item->setText(COL_STATUS, tr("Not working"));
|
||||
item->setText(COL_MSG, error_message);
|
||||
} else {
|
||||
item->setText(COL_STATUS, tr("Not contacted yet"));
|
||||
item->setText(COL_MSG, "");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BitTorrent::TrackerEntry::NotWorking:
|
||||
item->setText(COL_STATUS, tr("Not working"));
|
||||
item->setText(COL_MSG, error_message);
|
||||
break;
|
||||
case BitTorrent::TrackerEntry::NotContacted:
|
||||
item->setText(COL_STATUS, tr("Not contacted yet"));
|
||||
item->setText(COL_MSG, "");
|
||||
break;
|
||||
}
|
||||
item->setText(COL_PEERS, QString::number(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers));
|
||||
|
||||
item->setText(COL_PEERS, QString::number(trackers_data.value(trackerUrl).numPeers));
|
||||
}
|
||||
// Remove old trackers
|
||||
foreach (const QString &tracker, old_trackers_urls) {
|
||||
@@ -298,12 +293,13 @@ void TrackerList::loadTrackers() {
|
||||
|
||||
// Ask the user for new trackers and add them to the torrent
|
||||
void TrackerList::askForTrackers() {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) return;
|
||||
QString hash = h.hash();
|
||||
QStringList trackers = TrackersAdditionDlg::askForTrackers(h);
|
||||
QBtSession::instance()->addTrackersAndUrlSeeds(hash, trackers, QStringList());
|
||||
loadTrackers();
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) return;
|
||||
|
||||
QList<BitTorrent::TrackerEntry> trackers;
|
||||
foreach (const QString &tracker, TrackersAdditionDlg::askForTrackers(torrent))
|
||||
trackers << tracker;
|
||||
torrent->addTrackers(trackers);
|
||||
}
|
||||
|
||||
void TrackerList::copyTrackerUrl() {
|
||||
@@ -320,14 +316,15 @@ void TrackerList::copyTrackerUrl() {
|
||||
|
||||
|
||||
void TrackerList::deleteSelectedTrackers() {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) {
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
QString hash = h.hash();
|
||||
|
||||
QList<QTreeWidgetItem *> selected_items = getSelectedTrackerItems();
|
||||
if (selected_items.isEmpty()) return;
|
||||
|
||||
QStringList urls_to_remove;
|
||||
foreach (QTreeWidgetItem *item, selected_items) {
|
||||
QString tracker_url = item->data(COL_URL, Qt::DisplayRole).toString();
|
||||
@@ -335,32 +332,26 @@ void TrackerList::deleteSelectedTrackers() {
|
||||
tracker_items.remove(tracker_url);
|
||||
delete item;
|
||||
}
|
||||
// Iterate of trackers and remove selected ones
|
||||
std::vector<announce_entry> remaining_trackers;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
|
||||
std::vector<announce_entry>::iterator it = trackers.begin();
|
||||
std::vector<announce_entry>::iterator itend = trackers.end();
|
||||
for ( ; it != itend; ++it) {
|
||||
if (!urls_to_remove.contains(misc::toQString((*it).url))) {
|
||||
remaining_trackers.push_back(*it);
|
||||
// Iterate of trackers and remove selected ones
|
||||
QList<BitTorrent::TrackerEntry> remaining_trackers;
|
||||
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||
foreach (const BitTorrent::TrackerEntry &entry, trackers) {
|
||||
if (!urls_to_remove.contains(entry.url())) {
|
||||
remaining_trackers.push_back(entry);
|
||||
}
|
||||
}
|
||||
h.replace_trackers(remaining_trackers);
|
||||
if (!urls_to_remove.empty())
|
||||
emit trackersRemoved(urls_to_remove, hash);
|
||||
if (remaining_trackers.empty())
|
||||
emit trackerlessChange(true, hash);
|
||||
if (!h.is_paused())
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
|
||||
torrent->replaceTrackers(remaining_trackers);
|
||||
if (!torrent->isPaused())
|
||||
torrent->forceReannounce();
|
||||
}
|
||||
|
||||
void TrackerList::editSelectedTracker() {
|
||||
try {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
QString hash = h.hash();
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) return;
|
||||
|
||||
QString hash = torrent->hash();
|
||||
|
||||
QList<QTreeWidgetItem *> selected_items = getSelectedTrackerItems();
|
||||
if (selected_items.isEmpty())
|
||||
@@ -381,91 +372,78 @@ void TrackerList::editSelectedTracker() {
|
||||
if (new_tracker_url == tracker_url)
|
||||
return;
|
||||
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
std::vector<announce_entry>::iterator it = trackers.begin();
|
||||
std::vector<announce_entry>::iterator itend = trackers.end();
|
||||
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||
bool match = false;
|
||||
|
||||
for ( ; it != itend; ++it) {
|
||||
if (new_tracker_url == QUrl(misc::toQString(it->url))) {
|
||||
for (int i = 0; i < trackers.size(); ++i) {
|
||||
BitTorrent::TrackerEntry &entry = trackers[i];
|
||||
if (new_tracker_url == QUrl(entry.url())) {
|
||||
QMessageBox::warning(this, tr("Tracker editing failed"), tr("The tracker URL already exists."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (tracker_url == QUrl(misc::toQStringU(it->url)) && !match) {
|
||||
announce_entry new_entry(new_tracker_url.toString().toUtf8().constData());
|
||||
new_entry.tier = it->tier;
|
||||
if (tracker_url == QUrl(entry.url()) && !match) {
|
||||
BitTorrent::TrackerEntry new_entry(new_tracker_url.toString());
|
||||
new_entry.setTier(entry.tier());
|
||||
match = true;
|
||||
*it = new_entry;
|
||||
emit trackersRemoved(QStringList(tracker_url.toString()), hash);
|
||||
emit trackersAdded(QStringList(new_tracker_url.toString()), hash);
|
||||
entry = new_entry;
|
||||
}
|
||||
}
|
||||
|
||||
h.replace_trackers(trackers);
|
||||
if (!h.is_paused()) {
|
||||
h.force_reannounce();
|
||||
h.force_dht_announce();
|
||||
torrent->replaceTrackers(trackers);
|
||||
if (!torrent->isPaused()) {
|
||||
torrent->forceReannounce();
|
||||
torrent->forceDHTAnnounce();
|
||||
}
|
||||
} catch(invalid_handle&) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadTrackers();
|
||||
}
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 10000
|
||||
void TrackerList::reannounceSelected() {
|
||||
try {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) return;
|
||||
|
||||
QList<QTreeWidgetItem *> selected_items = getSelectedTrackerItems();
|
||||
if (selected_items.isEmpty())
|
||||
return;
|
||||
if (selected_items.isEmpty()) return;
|
||||
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
for (size_t i = 0; i < trackers.size(); ++i) {
|
||||
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||
for (int i = 0; i < trackers.size(); ++i) {
|
||||
foreach (QTreeWidgetItem* w, selected_items) {
|
||||
if (w->text(COL_URL) == misc::toQString(trackers[i].url)) {
|
||||
h.force_reannounce(0, i);
|
||||
if (w->text(COL_URL) == trackers[i].url()) {
|
||||
torrent->forceReannounce(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(invalid_handle&) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadTrackers();
|
||||
loadTrackers();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void TrackerList::showTrackerListMenu(QPoint) {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) return;
|
||||
BitTorrent::TorrentHandle *const torrent = properties->getCurrentTorrent();
|
||||
if (!torrent) return;
|
||||
//QList<QTreeWidgetItem*> selected_items = getSelectedTrackerItems();
|
||||
QMenu menu;
|
||||
// Add actions
|
||||
QAction *addAct = menu.addAction(IconProvider::instance()->getIcon("list-add"), tr("Add a new tracker..."));
|
||||
QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add a new tracker..."));
|
||||
QAction *copyAct = 0;
|
||||
QAction *delAct = 0;
|
||||
QAction *editAct = 0;
|
||||
if (!getSelectedTrackerItems().isEmpty()) {
|
||||
delAct = menu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove tracker"));
|
||||
copyAct = menu.addAction(IconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker url"));
|
||||
editAct = menu.addAction(IconProvider::instance()->getIcon("edit-rename"),tr("Edit selected tracker URL"));
|
||||
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker"));
|
||||
copyAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker url"));
|
||||
editAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit selected tracker URL"));
|
||||
}
|
||||
#if LIBTORRENT_VERSION_NUM >= 10000
|
||||
QAction *reannounceSelAct = NULL;
|
||||
#endif
|
||||
QAction *reannounceAct = NULL;
|
||||
if (!h.is_paused()) {
|
||||
if (!torrent->isPaused()) {
|
||||
#if LIBTORRENT_VERSION_NUM >= 10000
|
||||
reannounceSelAct = menu.addAction(IconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers"));
|
||||
reannounceSelAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers"));
|
||||
#endif
|
||||
menu.addSeparator();
|
||||
reannounceAct = menu.addAction(IconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers"));
|
||||
reannounceAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers"));
|
||||
}
|
||||
QAction *act = menu.exec(QCursor::pos());
|
||||
if (act == 0) return;
|
||||
@@ -488,7 +466,7 @@ void TrackerList::showTrackerListMenu(QPoint) {
|
||||
}
|
||||
#endif
|
||||
if (act == reannounceAct) {
|
||||
properties->getCurrentTorrent().force_reannounce();
|
||||
properties->getCurrentTorrent()->forceReannounce();
|
||||
return;
|
||||
}
|
||||
if (act == editAct) {
|
||||
|
||||
@@ -37,12 +37,16 @@
|
||||
#include <QClipboard>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include "qtorrenthandle.h"
|
||||
#include "propertieswidget.h"
|
||||
|
||||
enum TrackerListColumn {COL_TIER, COL_URL, COL_STATUS, COL_PEERS, COL_MSG};
|
||||
#define NB_STICKY_ITEM 3
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentHandle;
|
||||
}
|
||||
|
||||
class TrackerList: public QTreeWidget {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TrackerList)
|
||||
@@ -60,11 +64,6 @@ public:
|
||||
TrackerList(PropertiesWidget *properties);
|
||||
~TrackerList();
|
||||
|
||||
signals:
|
||||
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<QTreeWidgetItem*> getSelectedTrackerItems() const;
|
||||
|
||||
@@ -75,7 +74,7 @@ public slots:
|
||||
void moveSelectionDown();
|
||||
|
||||
void clear();
|
||||
void loadStickyItems(const QTorrentHandle &h);
|
||||
void loadStickyItems(BitTorrent::TorrentHandle *const torrent);
|
||||
void loadTrackers();
|
||||
void askForTrackers();
|
||||
void copyTrackerUrl();
|
||||
|
||||
@@ -36,24 +36,26 @@
|
||||
#include <QMessageBox>
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/misc.h"
|
||||
#include "ui_trackersadditiondlg.h"
|
||||
#include "core/downloadthread.h"
|
||||
#include "qtorrenthandle.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "core/net/downloadhandler.h"
|
||||
#include "core/bittorrent/trackerentry.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "core/fs_utils.h"
|
||||
|
||||
class TrackersAdditionDlg : public QDialog, private Ui::TrackersAdditionDlg{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QTorrentHandle h;
|
||||
BitTorrent::TorrentHandle *const m_torrent;
|
||||
|
||||
public:
|
||||
TrackersAdditionDlg(QTorrentHandle h, QWidget *parent=0): QDialog(parent), h(h) {
|
||||
TrackersAdditionDlg(BitTorrent::TorrentHandle *const torrent, QWidget *parent = 0): QDialog(parent), m_torrent(torrent) {
|
||||
setupUi(this);
|
||||
// Icons
|
||||
uTorrentListButton->setIcon(IconProvider::instance()->getIcon("download"));
|
||||
uTorrentListButton->setIcon(GuiIconProvider::instance()->getIcon("download"));
|
||||
}
|
||||
|
||||
~TrackersAdditionDlg() {}
|
||||
@@ -65,41 +67,33 @@ public:
|
||||
public slots:
|
||||
void on_uTorrentListButton_clicked() {
|
||||
uTorrentListButton->setEnabled(false);
|
||||
DownloadThread *d = new DownloadThread(this);
|
||||
connect(d, SIGNAL(downloadFinished(QString,QString)), SLOT(parseUTorrentList(QString,QString)));
|
||||
connect(d, SIGNAL(downloadFailure(QString,QString)), SLOT(getTrackerError(QString,QString)));
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()));
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString)));
|
||||
//Just to show that it takes times
|
||||
setCursor(Qt::WaitCursor);
|
||||
d->downloadUrl("http://www.torrentz.com/announce_"+h.hash());
|
||||
}
|
||||
|
||||
void parseUTorrentList(QString, QString path) {
|
||||
void parseUTorrentList(const QString &, const QString &path) {
|
||||
QFile list_file(path);
|
||||
if (!list_file.open(QFile::ReadOnly)) {
|
||||
QMessageBox::warning(this, tr("I/O Error"), tr("Error while trying to open the downloaded file."), QMessageBox::Ok);
|
||||
setCursor(Qt::ArrowCursor);
|
||||
uTorrentListButton->setEnabled(true);
|
||||
sender()->deleteLater();
|
||||
fsutils::forceRemove(path);
|
||||
return;
|
||||
}
|
||||
QList<QUrl> existingTrackers;
|
||||
// Load from torrent handle
|
||||
std::vector<libtorrent::announce_entry> tor_trackers = h.trackers();
|
||||
|
||||
std::vector<libtorrent::announce_entry>::iterator itr = tor_trackers.begin();
|
||||
std::vector<libtorrent::announce_entry>::iterator itrend = tor_trackers.end();
|
||||
while(itr != itrend) {
|
||||
existingTrackers << QUrl(misc::toQString(itr->url));
|
||||
++itr;
|
||||
}
|
||||
// Load from torrent handle
|
||||
QList<BitTorrent::TrackerEntry> existingTrackers = m_torrent->trackers();
|
||||
// Load from current user list
|
||||
QStringList tmp = trackers_list->toPlainText().split("\n");
|
||||
foreach (const QString &user_url_str, tmp) {
|
||||
QUrl user_url(user_url_str);
|
||||
if (!existingTrackers.contains(user_url))
|
||||
existingTrackers << user_url;
|
||||
foreach (const QString &user_url, tmp) {
|
||||
BitTorrent::TrackerEntry userTracker(user_url);
|
||||
if (!existingTrackers.contains(userTracker))
|
||||
existingTrackers << userTracker;
|
||||
}
|
||||
|
||||
// Add new trackers to the list
|
||||
if (!trackers_list->toPlainText().isEmpty() && !trackers_list->toPlainText().endsWith("\n"))
|
||||
trackers_list->insertPlainText("\n");
|
||||
@@ -107,8 +101,8 @@ public slots:
|
||||
while (!list_file.atEnd()) {
|
||||
const QByteArray line = list_file.readLine().trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
QUrl url(line);
|
||||
if (!existingTrackers.contains(url)) {
|
||||
BitTorrent::TrackerEntry newTracker(line);
|
||||
if (!existingTrackers.contains(newTracker)) {
|
||||
trackers_list->insertPlainText(line + "\n");
|
||||
++nb;
|
||||
}
|
||||
@@ -123,22 +117,20 @@ public slots:
|
||||
if (nb == 0) {
|
||||
QMessageBox::information(this, tr("No change"), tr("No additional trackers were found."), QMessageBox::Ok);
|
||||
}
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void getTrackerError(const QString&, const QString &error) {
|
||||
void getTrackerError(const QString &, const QString &error) {
|
||||
//To restore the cursor ...
|
||||
setCursor(Qt::ArrowCursor);
|
||||
uTorrentListButton->setEnabled(true);
|
||||
QMessageBox::warning(this, tr("Download error"), tr("The trackers list could not be downloaded, reason: %1").arg(error), QMessageBox::Ok);
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static QStringList askForTrackers(QTorrentHandle h) {
|
||||
static QStringList askForTrackers(BitTorrent::TorrentHandle *const torrent) {
|
||||
QStringList trackers;
|
||||
TrackersAdditionDlg dlg(h);
|
||||
TrackersAdditionDlg dlg(torrent);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
return dlg.newTrackers();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "core/preferences.h"
|
||||
#include "rssmanager.h"
|
||||
#include "rssfeed.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "core/fs_utils.h"
|
||||
|
||||
@@ -51,8 +51,8 @@ AutomatedRssDownloader::AutomatedRssDownloader(const QWeakPointer<RssManager>& m
|
||||
{
|
||||
ui->setupUi(this);
|
||||
// Icons
|
||||
ui->removeRuleBtn->setIcon(IconProvider::instance()->getIcon("list-remove"));
|
||||
ui->addRuleBtn->setIcon(IconProvider::instance()->getIcon("list-add"));
|
||||
ui->removeRuleBtn->setIcon(GuiIconProvider::instance()->getIcon("list-remove"));
|
||||
ui->addRuleBtn->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
||||
|
||||
// Ui Settings
|
||||
ui->listRules->setSortingEnabled(true);
|
||||
@@ -436,17 +436,17 @@ void AutomatedRssDownloader::displayRulesListMenu(const QPoint &pos)
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
QMenu menu;
|
||||
QAction *addAct = menu.addAction(IconProvider::instance()->getIcon("list-add"), tr("Add new rule..."));
|
||||
QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add new rule..."));
|
||||
QAction *delAct = 0;
|
||||
QAction *renameAct = 0;
|
||||
const QList<QListWidgetItem*> selection = ui->listRules->selectedItems();
|
||||
if (!selection.isEmpty()) {
|
||||
if (selection.count() == 1) {
|
||||
delAct = menu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Delete rule"));
|
||||
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete rule"));
|
||||
menu.addSeparator();
|
||||
renameAct = menu.addAction(IconProvider::instance()->getIcon("edit-rename"), tr("Rename rule..."));
|
||||
renameAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename rule..."));
|
||||
} else {
|
||||
delAct = menu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Delete selected rules"));
|
||||
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete selected rules"));
|
||||
}
|
||||
}
|
||||
QAction *act = menu.exec(QCursor::pos());
|
||||
@@ -557,7 +557,7 @@ void AutomatedRssDownloader::addFeedArticlesToTree(const RssFeedPtr& feed, const
|
||||
QFont f = treeFeedItem->font(0);
|
||||
f.setBold(true);
|
||||
treeFeedItem->setFont(0, f);
|
||||
treeFeedItem->setData(0, Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory"));
|
||||
treeFeedItem->setData(0, Qt::DecorationRole, GuiIconProvider::instance()->getIcon("inode-directory"));
|
||||
treeFeedItem->setData(0, Qt::UserRole, feed->url());
|
||||
ui->treeMatchingArticles->addTopLevelItem(treeFeedItem);
|
||||
}
|
||||
@@ -606,7 +606,7 @@ void AutomatedRssDownloader::updateMustLineValidity()
|
||||
ui->lbl_must_stat->setPixmap(QPixmap());
|
||||
} else {
|
||||
ui->lineContains->setStyleSheet("QLineEdit { color: #ff0000; }");
|
||||
ui->lbl_must_stat->setPixmap(IconProvider::instance()->getIcon("task-attention").pixmap(16, 16));
|
||||
ui->lbl_must_stat->setPixmap(GuiIconProvider::instance()->getIcon("task-attention").pixmap(16, 16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ void AutomatedRssDownloader::updateMustNotLineValidity()
|
||||
ui->lbl_mustnot_stat->setPixmap(QPixmap());
|
||||
} else {
|
||||
ui->lineNotContains->setStyleSheet("QLineEdit { color: #ff0000; }");
|
||||
ui->lbl_mustnot_stat->setPixmap(IconProvider::instance()->getIcon("task-attention").pixmap(16, 16));
|
||||
ui->lbl_mustnot_stat->setPixmap(GuiIconProvider::instance()->getIcon("task-attention").pixmap(16, 16));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "cookiesdlg.h"
|
||||
#include "ui_cookiesdlg.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
|
||||
#include <QNetworkCookie>
|
||||
|
||||
@@ -42,8 +42,8 @@ CookiesDlg::CookiesDlg(QWidget *parent, const QList<QByteArray> &raw_cookies) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
// Icons
|
||||
ui->add_btn->setIcon(IconProvider::instance()->getIcon("list-add"));
|
||||
ui->del_btn->setIcon(IconProvider::instance()->getIcon("list-remove"));
|
||||
ui->add_btn->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
||||
ui->del_btn->setIcon(GuiIconProvider::instance()->getIcon("list-remove"));
|
||||
|
||||
ui->infos_lbl->setText(tr("Common keys for cookies are : '%1', '%2'.\nYou should get this information from your Web browser preferences.").arg("uid").arg("pass"));
|
||||
foreach (const QByteArray &raw_cookie, raw_cookies) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "feedlistwidget.h"
|
||||
#include "rssmanager.h"
|
||||
#include "rssfeed.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
|
||||
FeedListWidget::FeedListWidget(QWidget *parent, const RssManagerPtr& rssmanager): QTreeWidget(parent), m_rssManager(rssmanager) {
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
@@ -41,7 +41,7 @@ FeedListWidget::FeedListWidget(QWidget *parent, const RssManagerPtr& rssmanager)
|
||||
headerItem()->setText(0, tr("RSS feeds"));
|
||||
m_unreadStickyItem = new QTreeWidgetItem(this);
|
||||
m_unreadStickyItem->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->unreadCount())+ QString(")"));
|
||||
m_unreadStickyItem->setData(0,Qt::DecorationRole, IconProvider::instance()->getIcon("mail-folder-inbox"));
|
||||
m_unreadStickyItem->setData(0,Qt::DecorationRole, GuiIconProvider::instance()->getIcon("mail-folder-inbox"));
|
||||
itemAdded(m_unreadStickyItem, rssmanager);
|
||||
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
||||
setCurrentItem(m_unreadStickyItem);
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
|
||||
#include "rss_imp.h"
|
||||
#include "feedlistwidget.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "cookiesdlg.h"
|
||||
#include "core/preferences.h"
|
||||
#include "rsssettingsdlg.h"
|
||||
@@ -49,8 +50,9 @@
|
||||
#include "rssparser.h"
|
||||
#include "rssfeed.h"
|
||||
#include "automatedrssdownloader.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "addnewtorrentdialog.h"
|
||||
|
||||
namespace Article
|
||||
{
|
||||
@@ -140,6 +142,7 @@ void RSSImp::on_actionManage_cookies_triggered()
|
||||
if (ok) {
|
||||
qDebug() << "Settings cookies for host name: " << feed_hostname;
|
||||
pref->setHostNameCookies(feed_hostname, raw_cookies);
|
||||
Net::DownloadManager::instance()->setCookiesFromUrl(pref->getHostNameQNetworkCookies(feed_hostname), feed_hostname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,17 +346,10 @@ void RSSImp::downloadSelectedTorrents()
|
||||
|
||||
QString torrentLink = article->torrentUrl();
|
||||
// Check if it is a magnet link
|
||||
if (torrentLink.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
QBtSession::instance()->addMagnetInteractive(torrentLink);
|
||||
}
|
||||
else {
|
||||
// Load possible cookies
|
||||
QString feed_url = m_feedList->getItemID(m_feedList->selectedItems().first());
|
||||
QString feed_hostname = QUrl::fromEncoded(feed_url.toUtf8()).host();
|
||||
QList<QNetworkCookie> cookies = Preferences::instance()->getHostNameQNetworkCookies(feed_hostname);
|
||||
qDebug("Loaded %d cookies for RSS item\n", cookies.size());
|
||||
QBtSession::instance()->downloadFromUrl(torrentLink, cookies);
|
||||
}
|
||||
if (torrentLink.startsWith("magnet:", Qt::CaseInsensitive) && Preferences::instance()->useAdditionDialog())
|
||||
AddNewTorrentDialog::show(torrentLink);
|
||||
else
|
||||
BitTorrent::Session::instance()->addTorrent(torrentLink);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,22 +696,22 @@ RSSImp::RSSImp(QWidget *parent):
|
||||
{
|
||||
setupUi(this);
|
||||
// Icons
|
||||
actionCopy_feed_URL->setIcon(IconProvider::instance()->getIcon("edit-copy"));
|
||||
actionDelete->setIcon(IconProvider::instance()->getIcon("edit-delete"));
|
||||
actionDownload_torrent->setIcon(IconProvider::instance()->getIcon("download"));
|
||||
actionManage_cookies->setIcon(IconProvider::instance()->getIcon("preferences-web-browser-cookies"));
|
||||
actionMark_items_read->setIcon(IconProvider::instance()->getIcon("mail-mark-read"));
|
||||
actionNew_folder->setIcon(IconProvider::instance()->getIcon("folder-new"));
|
||||
actionNew_subscription->setIcon(IconProvider::instance()->getIcon("list-add"));
|
||||
actionOpen_news_URL->setIcon(IconProvider::instance()->getIcon("application-x-mswinurl"));
|
||||
actionRename->setIcon(IconProvider::instance()->getIcon("edit-rename"));
|
||||
actionUpdate->setIcon(IconProvider::instance()->getIcon("view-refresh"));
|
||||
actionUpdate_all_feeds->setIcon(IconProvider::instance()->getIcon("view-refresh"));
|
||||
newFeedButton->setIcon(IconProvider::instance()->getIcon("list-add"));
|
||||
markReadButton->setIcon(IconProvider::instance()->getIcon("mail-mark-read"));
|
||||
updateAllButton->setIcon(IconProvider::instance()->getIcon("view-refresh"));
|
||||
rssDownloaderBtn->setIcon(IconProvider::instance()->getIcon("download"));
|
||||
settingsButton->setIcon(IconProvider::instance()->getIcon("preferences-system"));
|
||||
actionCopy_feed_URL->setIcon(GuiIconProvider::instance()->getIcon("edit-copy"));
|
||||
actionDelete->setIcon(GuiIconProvider::instance()->getIcon("edit-delete"));
|
||||
actionDownload_torrent->setIcon(GuiIconProvider::instance()->getIcon("download"));
|
||||
actionManage_cookies->setIcon(GuiIconProvider::instance()->getIcon("preferences-web-browser-cookies"));
|
||||
actionMark_items_read->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read"));
|
||||
actionNew_folder->setIcon(GuiIconProvider::instance()->getIcon("folder-new"));
|
||||
actionNew_subscription->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
||||
actionOpen_news_URL->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl"));
|
||||
actionRename->setIcon(GuiIconProvider::instance()->getIcon("edit-rename"));
|
||||
actionUpdate->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
|
||||
actionUpdate_all_feeds->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
|
||||
newFeedButton->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
||||
markReadButton->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read"));
|
||||
updateAllButton->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
|
||||
rssDownloaderBtn->setIcon(GuiIconProvider::instance()->getIcon("download"));
|
||||
settingsButton->setIcon(GuiIconProvider::instance()->getIcon("preferences-system"));
|
||||
|
||||
m_feedList = new FeedListWidget(splitter_h, m_rssManager);
|
||||
splitter_h->insertWidget(0, m_feedList);
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <QDebug>
|
||||
#include "rssfeed.h"
|
||||
#include "rssmanager.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "rssfolder.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/qinisettings.h"
|
||||
@@ -39,7 +39,8 @@
|
||||
#include "rssparser.h"
|
||||
#include "core/misc.h"
|
||||
#include "rssdownloadrulelist.h"
|
||||
#include "core/downloadthread.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "core/net/downloadhandler.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/logger.h"
|
||||
|
||||
@@ -60,15 +61,15 @@ RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString& url):
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << m_url;
|
||||
// Listen for new RSS downloads
|
||||
connect(manager->rssDownloader(), SIGNAL(downloadFinished(QString,QString)), SLOT(handleFinishedDownload(QString,QString)));
|
||||
connect(manager->rssDownloader(), SIGNAL(downloadFailure(QString,QString)), SLOT(handleDownloadFailure(QString,QString)));
|
||||
connect(manager->rssParser(), SIGNAL(feedTitle(QString,QString)), SLOT(handleFeedTitle(QString,QString)));
|
||||
connect(manager->rssParser(), SIGNAL(newArticle(QString,QVariantHash)), SLOT(handleNewArticle(QString,QVariantHash)));
|
||||
connect(manager->rssParser(), SIGNAL(feedParsingFinished(QString,QString)), SLOT(handleFeedParsingFinished(QString,QString)));
|
||||
|
||||
// Download the RSS Feed icon
|
||||
m_iconUrl = iconUrl();
|
||||
manager->rssDownloader()->downloadUrl(m_iconUrl);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl());
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
m_iconUrl = handler->url();
|
||||
|
||||
// Load old RSS articles
|
||||
loadItemsFromDisk();
|
||||
@@ -159,12 +160,6 @@ void RssFeed::addArticle(const RssArticlePtr& article) {
|
||||
}
|
||||
}
|
||||
|
||||
QList<QNetworkCookie> RssFeed::feedCookies() const
|
||||
{
|
||||
QString feed_hostname = QUrl::fromEncoded(m_url.toUtf8()).host();
|
||||
return Preferences::instance()->getHostNameQNetworkCookies(feed_hostname);
|
||||
}
|
||||
|
||||
bool RssFeed::refresh()
|
||||
{
|
||||
if (m_loading) {
|
||||
@@ -173,7 +168,10 @@ bool RssFeed::refresh()
|
||||
}
|
||||
m_loading = true;
|
||||
// Download the RSS again
|
||||
m_manager->rssDownloader()->downloadUrl(m_url, feedCookies());
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
m_url = handler->url(); // sync URL encoding
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -307,7 +305,7 @@ QString RssFeed::iconUrl() const
|
||||
}
|
||||
|
||||
// read and store the downloaded rss' informations
|
||||
void RssFeed::handleFinishedDownload(const QString& url, const QString& filePath)
|
||||
void RssFeed::handleFinishedDownload(const QString &url, const QString &filePath)
|
||||
{
|
||||
if (url == m_url) {
|
||||
qDebug() << Q_FUNC_INFO << "Successfully downloaded RSS feed at" << url;
|
||||
@@ -320,10 +318,9 @@ void RssFeed::handleFinishedDownload(const QString& url, const QString& filePath
|
||||
}
|
||||
}
|
||||
|
||||
void RssFeed::handleDownloadFailure(const QString& url, const QString& error)
|
||||
void RssFeed::handleDownloadFailure(const QString &url, const QString &error)
|
||||
{
|
||||
if (url != m_url)
|
||||
return;
|
||||
if (url != m_url) return;
|
||||
|
||||
m_inErrorState = true;
|
||||
m_loading = false;
|
||||
@@ -369,12 +366,17 @@ void RssFeed::downloadArticleTorrentIfMatching(RssDownloadRuleList* rules, const
|
||||
// Download the torrent
|
||||
const QString& torrent_url = article->torrentUrl();
|
||||
Logger::instance()->addMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(article->title()).arg(displayName()));
|
||||
connect(QBtSession::instance(), SIGNAL(newDownloadedTorrentFromRss(QString)), article.data(), SLOT(handleTorrentDownloadSuccess(const QString&)), Qt::UniqueConnection);
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(downloadFromUrlFinished(QString)), article.data(), SLOT(handleTorrentDownloadSuccess(const QString&)), Qt::UniqueConnection);
|
||||
connect(article.data(), SIGNAL(articleWasRead()), SLOT(handleArticleStateChanged()), Qt::UniqueConnection);
|
||||
if (torrent_url.startsWith("magnet:", Qt::CaseInsensitive))
|
||||
QBtSession::instance()->addMagnetSkipAddDlg(torrent_url, matching_rule->savePath(), matching_rule->label(), matching_rule->addPaused());
|
||||
else
|
||||
QBtSession::instance()->downloadUrlAndSkipDialog(torrent_url, matching_rule->savePath(), matching_rule->label(), feedCookies(), matching_rule->addPaused());
|
||||
|
||||
BitTorrent::AddTorrentParams params;
|
||||
params.savePath = matching_rule->savePath();
|
||||
params.label = matching_rule->label();
|
||||
if (matching_rule->addPaused() == RssDownloadRule::ALWAYS_PAUSED)
|
||||
params.addPaused = TriStateBool::True;
|
||||
else if (matching_rule->addPaused() == RssDownloadRule::NEVER_PAUSED)
|
||||
params.addPaused = TriStateBool::False;
|
||||
BitTorrent::Session::instance()->addTorrent(torrent_url, params);
|
||||
}
|
||||
|
||||
void RssFeed::recheckRssItemsForDownload()
|
||||
@@ -426,7 +428,8 @@ void RssFeed::handleFeedParsingFinished(const QString& feedUrl, const QString& e
|
||||
saveItemsToDisk();
|
||||
}
|
||||
|
||||
void RssFeed::handleArticleStateChanged() {
|
||||
void RssFeed::handleArticleStateChanged()
|
||||
{
|
||||
m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ public:
|
||||
void recheckRssItemsForDownload();
|
||||
|
||||
private slots:
|
||||
void handleFinishedDownload(const QString& url, const QString &file_path);
|
||||
void handleDownloadFailure(const QString &url, const QString& error);
|
||||
void handleFinishedDownload(const QString &url, const QString &filePath);
|
||||
void handleDownloadFailure(const QString &url, const QString &error);
|
||||
void handleFeedTitle(const QString& feedUrl, const QString& title);
|
||||
void handleNewArticle(const QString& feedUrl, const QVariantHash& article);
|
||||
void handleFeedParsingFinished(const QString& feedUrl, const QString& error);
|
||||
@@ -93,7 +93,6 @@ private:
|
||||
void loadItemsFromDisk();
|
||||
void addArticle(const RssArticlePtr& article);
|
||||
void downloadArticleTorrentIfMatching(RssDownloadRuleList* rules, const RssArticlePtr& article);
|
||||
QList<QNetworkCookie> feedCookies() const;
|
||||
|
||||
private:
|
||||
RssManager* m_manager;
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "rssfolder.h"
|
||||
#include "rssarticle.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "rssmanager.h"
|
||||
#include "rssfeed.h"
|
||||
|
||||
@@ -233,7 +233,7 @@ QString RssFolder::id() const
|
||||
|
||||
QIcon RssFolder::icon() const
|
||||
{
|
||||
return IconProvider::instance()->getIcon("inode-directory");
|
||||
return GuiIconProvider::instance()->getIcon("inode-directory");
|
||||
}
|
||||
|
||||
bool RssFolder::hasChild(const QString &childId) {
|
||||
|
||||
@@ -31,17 +31,15 @@
|
||||
#include <QDebug>
|
||||
#include "rssmanager.h"
|
||||
#include "core/preferences.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "rssfeed.h"
|
||||
#include "rssarticle.h"
|
||||
#include "rssdownloadrulelist.h"
|
||||
#include "rssparser.h"
|
||||
#include "core/downloadthread.h"
|
||||
|
||||
static const int MSECS_PER_MIN = 60000;
|
||||
|
||||
RssManager::RssManager():
|
||||
m_rssDownloader(new DownloadThread(this)),
|
||||
m_downloadRules(new RssDownloadRuleList),
|
||||
m_rssParser(new RssParser(this))
|
||||
{
|
||||
@@ -60,11 +58,6 @@ RssManager::~RssManager()
|
||||
qDebug("RSSManager deleted");
|
||||
}
|
||||
|
||||
DownloadThread* RssManager::rssDownloader() const
|
||||
{
|
||||
return m_rssDownloader;
|
||||
}
|
||||
|
||||
RssParser* RssManager::rssParser() const
|
||||
{
|
||||
return m_rssParser;
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
#include "rssfolder.h"
|
||||
|
||||
class DownloadThread;
|
||||
class RssDownloadRuleList;
|
||||
class RssParser;
|
||||
|
||||
@@ -50,7 +49,6 @@ public:
|
||||
RssManager();
|
||||
virtual ~RssManager();
|
||||
|
||||
DownloadThread* rssDownloader() const;
|
||||
RssParser* rssParser() const;
|
||||
RssDownloadRuleList* downloadRules() const;
|
||||
|
||||
@@ -71,7 +69,6 @@ signals:
|
||||
private:
|
||||
QTimer m_refreshTimer;
|
||||
uint m_refreshInterval;
|
||||
DownloadThread* m_rssDownloader;
|
||||
RssDownloadRuleList* m_downloadRules;
|
||||
RssParser* m_rssParser;
|
||||
};
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
*/
|
||||
|
||||
#include "rssparser.h"
|
||||
#include "core/downloadthread.h"
|
||||
#include "core/fs_utils.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QRegExp>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
ShutdownConfirmDlg::ShutdownConfirmDlg(const shutDownAction &action)
|
||||
ShutdownConfirmDlg::ShutdownConfirmDlg(const ShutDownAction &action)
|
||||
: m_exitNow(0)
|
||||
, m_timeout(15)
|
||||
, m_action(action)
|
||||
@@ -71,7 +71,7 @@ void ShutdownConfirmDlg::showEvent(QShowEvent *event)
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
bool ShutdownConfirmDlg::askForConfirmation(const shutDownAction &action)
|
||||
bool ShutdownConfirmDlg::askForConfirmation(const ShutDownAction &action)
|
||||
{
|
||||
ShutdownConfirmDlg dlg(action);
|
||||
dlg.exec();
|
||||
|
||||
@@ -40,10 +40,10 @@ class ShutdownConfirmDlg : public QMessageBox
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ShutdownConfirmDlg(const shutDownAction &action);
|
||||
ShutdownConfirmDlg(const ShutDownAction &action);
|
||||
bool shutdown() const;
|
||||
|
||||
static bool askForConfirmation(const shutDownAction &action);
|
||||
static bool askForConfirmation(const ShutDownAction &action);
|
||||
|
||||
QAbstractButton *getExit_now() const;
|
||||
void setExit_now(QAbstractButton *value);
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
QAbstractButton *m_exitNow;
|
||||
QTimer m_timer;
|
||||
int m_timeout;
|
||||
shutDownAction m_action;
|
||||
ShutDownAction m_action;
|
||||
};
|
||||
|
||||
#endif // SHUTDOWNCONFIRM_H
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <QList>
|
||||
#include "ui_bandwidth_limit.h"
|
||||
#include "core/misc.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
|
||||
class SpeedLimitDialog : public QDialog, private Ui_bandwidth_dlg {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -32,14 +32,18 @@
|
||||
#include "ui_statsdialog.h"
|
||||
|
||||
#include "core/misc.h"
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/disk_io_thread.hpp>
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/sessionstatus.h"
|
||||
#include "core/bittorrent/cachestatus.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
|
||||
StatsDialog::StatsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::StatsDialog) {
|
||||
StatsDialog::StatsDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::StatsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(ui->buttonOK, SIGNAL(clicked()), SLOT(close()));
|
||||
session = QBtSession::instance();
|
||||
updateUI();
|
||||
t = new QTimer(this);
|
||||
t->setInterval(1500);
|
||||
@@ -55,17 +59,16 @@ StatsDialog::~StatsDialog() {
|
||||
}
|
||||
|
||||
void StatsDialog::updateUI() {
|
||||
libtorrent::session* s = session->getSession();
|
||||
libtorrent::cache_status cache = s->get_cache_status();
|
||||
libtorrent::session_status ss = s->status();
|
||||
BitTorrent::SessionStatus ss = BitTorrent::Session::instance()->status();
|
||||
BitTorrent::CacheStatus cs = BitTorrent::Session::instance()->cacheStatus();
|
||||
|
||||
// Alltime DL/UL
|
||||
quint64 atd = session->getAlltimeDL();
|
||||
quint64 atu = session->getAlltimeUL();
|
||||
quint64 atd = BitTorrent::Session::instance()->getAlltimeDL();
|
||||
quint64 atu = BitTorrent::Session::instance()->getAlltimeUL();
|
||||
ui->labelAlltimeDL->setText(misc::friendlyUnit(atd));
|
||||
ui->labelAlltimeUL->setText(misc::friendlyUnit(atu));
|
||||
// Total waste (this session)
|
||||
ui->labelWaste->setText(misc::friendlyUnit(ss.total_redundant_bytes + ss.total_failed_bytes));
|
||||
ui->labelWaste->setText(misc::friendlyUnit(ss.totalWasted()));
|
||||
// Global ratio
|
||||
ui->labelGlobalRatio->setText(
|
||||
( atd > 0 && atu > 0 ) ?
|
||||
@@ -73,39 +76,30 @@ void StatsDialog::updateUI() {
|
||||
"-"
|
||||
);
|
||||
// Cache hits
|
||||
ui->labelCacheHits->setText(
|
||||
( cache.blocks_read > 0 && cache.blocks_read_hit > 0 ) ?
|
||||
misc::accurateDoubleToString(100. * (qreal)cache.blocks_read_hit / (qreal)cache.blocks_read, 2) :
|
||||
"-"
|
||||
);
|
||||
qreal readRatio = cs.readRatio();
|
||||
ui->labelCacheHits->setText((readRatio >= 0) ? misc::accurateDoubleToString(100 * readRatio, 2) : "-");
|
||||
// Buffers size
|
||||
ui->labelTotalBuf->setText(misc::friendlyUnit(cache.total_used_buffers * 16 * 1024));
|
||||
ui->labelTotalBuf->setText(misc::friendlyUnit(cs.totalUsedBuffers() * 16 * 1024));
|
||||
// Disk overload (100%) equivalent
|
||||
// From lt manual: disk_write_queue and disk_read_queue are the number of peers currently waiting on a disk write or disk read
|
||||
// to complete before it receives or sends any more data on the socket. It'a a metric of how disk bound you are.
|
||||
|
||||
// num_peers is not reliable (adds up peers, which didn't even overcome tcp handshake)
|
||||
const std::vector<libtorrent::torrent_handle> torrents = session->getTorrents();
|
||||
std::vector<libtorrent::torrent_handle>::const_iterator iBegin = torrents.begin();
|
||||
std::vector<libtorrent::torrent_handle>::const_iterator iEnd = torrents.end();
|
||||
quint32 peers = 0;
|
||||
for ( ; iBegin < iEnd ; ++iBegin)
|
||||
peers += (*iBegin).status().num_peers;
|
||||
ui->labelWriteStarve->setText(
|
||||
( ss.disk_write_queue > 0 && peers > 0 ) ?
|
||||
misc::accurateDoubleToString(100. * (qreal)ss.disk_write_queue / (qreal)peers, 2) + "%" :
|
||||
QString("0\%")
|
||||
);
|
||||
ui->labelReadStarve->setText(
|
||||
( ss.disk_read_queue > 0 && peers > 0 ) ?
|
||||
misc::accurateDoubleToString(100. * (qreal)ss.disk_read_queue / (qreal)peers, 2) + "%" :
|
||||
QString("0\%")
|
||||
);
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||
peers += torrent->peersCount();
|
||||
|
||||
ui->labelWriteStarve->setText(QString("%1%").arg(((ss.diskWriteQueue() > 0) && (peers > 0))
|
||||
? misc::accurateDoubleToString((100. * ss.diskWriteQueue()) / peers, 2)
|
||||
: "0"));
|
||||
ui->labelReadStarve->setText(QString("%1%").arg(((ss.diskReadQueue() > 0) && (peers > 0))
|
||||
? misc::accurateDoubleToString((100. * ss.diskReadQueue()) / peers, 2)
|
||||
: "0"));
|
||||
// Disk queues
|
||||
ui->labelQueuedJobs->setText(QString::number(cache.job_queue_length));
|
||||
ui->labelJobsTime->setText(QString::number(cache.average_job_time));
|
||||
ui->labelQueuedBytes->setText(misc::friendlyUnit(cache.queued_bytes));
|
||||
ui->labelQueuedJobs->setText(QString::number(cs.jobQueueLength()));
|
||||
ui->labelJobsTime->setText(QString::number(cs.averageJobTime()));
|
||||
ui->labelQueuedBytes->setText(misc::friendlyUnit(cs.queuedBytes()));
|
||||
|
||||
// Total connected peers
|
||||
ui->labelPeers->setText(QString::number(ss.num_peers));
|
||||
ui->labelPeers->setText(QString::number(ss.peersCount()));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
#include "qbtsession.h"
|
||||
|
||||
namespace Ui {
|
||||
class StatsDialog;
|
||||
@@ -51,7 +50,6 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::StatsDialog *ui;
|
||||
QBtSession* session;
|
||||
QTimer* t;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,21 +33,19 @@
|
||||
#include <QFontMetrics>
|
||||
#include <QDebug>
|
||||
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/sessionstatus.h"
|
||||
#include "speedlimitdlg.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/logger.h"
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/session_status.hpp>
|
||||
|
||||
StatusBar::StatusBar(QStatusBar *bar)
|
||||
: m_bar(bar)
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
connect(QBtSession::instance(), SIGNAL(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(speedLimitModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
|
||||
container = new QWidget(bar);
|
||||
layout = new QHBoxLayout(container);
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
@@ -159,12 +157,12 @@ void StatusBar::stopTimer() {
|
||||
|
||||
void StatusBar::refreshStatusBar() {
|
||||
// Update connection status
|
||||
const libtorrent::session_status sessionStatus = QBtSession::instance()->getSessionStatus();
|
||||
if (!QBtSession::instance()->getSession()->is_listening()) {
|
||||
const BitTorrent::SessionStatus sessionStatus = BitTorrent::Session::instance()->status();
|
||||
if (!BitTorrent::Session::instance()->isListening()) {
|
||||
connecStatusLblIcon->setIcon(QIcon(QString::fromUtf8(":/icons/skin/disconnected.png")));
|
||||
connecStatusLblIcon->setToolTip(QString::fromUtf8("<b>")+tr("Connection Status:")+QString::fromUtf8("</b><br>")+tr("Offline. This usually means that qBittorrent failed to listen on the selected port for incoming connections."));
|
||||
} else {
|
||||
if (sessionStatus.has_incoming_connections) {
|
||||
if (sessionStatus.hasIncomingConnections()) {
|
||||
// Connection OK
|
||||
connecStatusLblIcon->setIcon(QIcon(QString::fromUtf8(":/icons/skin/connected.png")));
|
||||
connecStatusLblIcon->setToolTip(QString::fromUtf8("<b>")+tr("Connection Status:")+QString::fromUtf8("</b><br>")+tr("Online"));
|
||||
@@ -174,22 +172,22 @@ void StatusBar::refreshStatusBar() {
|
||||
}
|
||||
}
|
||||
// Update Number of DHT nodes
|
||||
if (QBtSession::instance()->isDHTEnabled()) {
|
||||
if (BitTorrent::Session::instance()->isDHTEnabled()) {
|
||||
DHTLbl->setVisible(true);
|
||||
//statusSep1->setVisible(true);
|
||||
DHTLbl->setText(tr("DHT: %1 nodes").arg(QString::number(sessionStatus.dht_nodes)));
|
||||
DHTLbl->setText(tr("DHT: %1 nodes").arg(QString::number(sessionStatus.dhtNodes())));
|
||||
} else {
|
||||
DHTLbl->setVisible(false);
|
||||
//statusSep1->setVisible(false);
|
||||
}
|
||||
// Update speed labels
|
||||
QString speedLbl = misc::friendlyUnit(sessionStatus.payload_download_rate, true)+" ("+misc::friendlyUnit(sessionStatus.total_payload_download)+")";
|
||||
int speedLimit = QBtSession::instance()->getSession()->settings().download_rate_limit;
|
||||
QString speedLbl = misc::friendlyUnit(sessionStatus.payloadDownloadRate(), true)+" ("+misc::friendlyUnit(sessionStatus.totalPayloadDownload())+")";
|
||||
int speedLimit = BitTorrent::Session::instance()->downloadRateLimit();
|
||||
if (speedLimit)
|
||||
speedLbl = "["+misc::friendlyUnit(speedLimit, true)+"] " + speedLbl;
|
||||
dlSpeedLbl->setText(speedLbl);
|
||||
speedLimit = QBtSession::instance()->getSession()->settings().upload_rate_limit;
|
||||
speedLbl = misc::friendlyUnit(sessionStatus.payload_upload_rate, true)+" ("+misc::friendlyUnit(sessionStatus.total_payload_upload)+")";
|
||||
speedLimit = BitTorrent::Session::instance()->uploadRateLimit();
|
||||
speedLbl = misc::friendlyUnit(sessionStatus.payloadUploadRate(), true)+" ("+misc::friendlyUnit(sessionStatus.totalPayloadUpload())+")";
|
||||
if (speedLimit)
|
||||
speedLbl = "["+misc::friendlyUnit(speedLimit, true)+"] " + speedLbl;
|
||||
upSpeedLbl->setText(speedLbl);
|
||||
@@ -214,26 +212,26 @@ void StatusBar::toggleAlternativeSpeeds() {
|
||||
pref->setSchedulerEnabled(false);
|
||||
m_bar->showMessage(tr("Manual change of rate limits mode. The scheduler is disabled."), 5000);
|
||||
}
|
||||
QBtSession::instance()->useAlternativeSpeedsLimit(!pref->isAltBandwidthEnabled());
|
||||
BitTorrent::Session::instance()->changeSpeedLimitMode(!pref->isAltBandwidthEnabled());
|
||||
}
|
||||
|
||||
void StatusBar::capDownloadSpeed() {
|
||||
bool ok = false;
|
||||
int cur_limit = QBtSession::instance()->getSession()->settings().download_rate_limit;
|
||||
int cur_limit = BitTorrent::Session::instance()->downloadRateLimit();
|
||||
long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Global Download Speed Limit"), cur_limit);
|
||||
if (ok) {
|
||||
Preferences* const pref = Preferences::instance();
|
||||
bool alt = pref->isAltBandwidthEnabled();
|
||||
if (new_limit <= 0) {
|
||||
qDebug("Setting global download rate limit to Unlimited");
|
||||
QBtSession::instance()->setDownloadRateLimit(-1);
|
||||
BitTorrent::Session::instance()->setDownloadRateLimit(-1);
|
||||
if (!alt)
|
||||
pref->setGlobalDownloadLimit(-1);
|
||||
else
|
||||
pref->setAltGlobalDownloadLimit(-1);
|
||||
} else {
|
||||
qDebug("Setting global download rate limit to %.1fKb/s", new_limit/1024.);
|
||||
QBtSession::instance()->setDownloadRateLimit(new_limit);
|
||||
BitTorrent::Session::instance()->setDownloadRateLimit(new_limit);
|
||||
if (!alt)
|
||||
pref->setGlobalDownloadLimit(new_limit/1024.);
|
||||
else
|
||||
@@ -245,21 +243,21 @@ void StatusBar::capDownloadSpeed() {
|
||||
|
||||
void StatusBar::capUploadSpeed() {
|
||||
bool ok = false;
|
||||
int cur_limit = QBtSession::instance()->getSession()->settings().upload_rate_limit;
|
||||
int cur_limit = BitTorrent::Session::instance()->uploadRateLimit();
|
||||
long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Global Upload Speed Limit"), cur_limit);
|
||||
if (ok) {
|
||||
Preferences* const pref = Preferences::instance();
|
||||
bool alt = pref->isAltBandwidthEnabled();
|
||||
if (new_limit <= 0) {
|
||||
qDebug("Setting global upload rate limit to Unlimited");
|
||||
QBtSession::instance()->setUploadRateLimit(-1);
|
||||
BitTorrent::Session::instance()->setUploadRateLimit(-1);
|
||||
if (!alt)
|
||||
Preferences::instance()->setGlobalUploadLimit(-1);
|
||||
else
|
||||
Preferences::instance()->setAltGlobalUploadLimit(-1);
|
||||
} else {
|
||||
qDebug("Setting global upload rate limit to %.1fKb/s", new_limit/1024.);
|
||||
QBtSession::instance()->setUploadRateLimit(new_limit);
|
||||
BitTorrent::Session::instance()->setUploadRateLimit(new_limit);
|
||||
if (!alt)
|
||||
Preferences::instance()->setGlobalUploadLimit(new_limit/1024.);
|
||||
else
|
||||
|
||||
@@ -28,23 +28,25 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "iconprovider.h"
|
||||
#include <QDir>
|
||||
#include <QIcon>
|
||||
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "torrentcontentmodelitem.h"
|
||||
#include "torrentcontentmodelfolder.h"
|
||||
#include "torrentcontentmodelfile.h"
|
||||
#include <QDir>
|
||||
|
||||
namespace {
|
||||
QIcon get_directory_icon() {
|
||||
static QIcon cached = IconProvider::instance()->getIcon("inode-directory");
|
||||
static QIcon cached = GuiIconProvider::instance()->getIcon("inode-directory");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QIcon get_file_icon() {
|
||||
static QIcon cached = IconProvider::instance()->getIcon("text-plain");
|
||||
static QIcon cached = GuiIconProvider::instance()->getIcon("text-plain");
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
@@ -61,15 +63,14 @@ TorrentContentModel::~TorrentContentModel()
|
||||
delete m_rootItem;
|
||||
}
|
||||
|
||||
void TorrentContentModel::updateFilesProgress(const std::vector<libtorrent::size_type>& fp)
|
||||
void TorrentContentModel::updateFilesProgress(const QVector<qreal> &fp)
|
||||
{
|
||||
Q_ASSERT(m_filesIndex.size() == (int)fp.size());
|
||||
Q_ASSERT(m_filesIndex.size() == fp.size());
|
||||
// XXX: Why is this necessary?
|
||||
if (m_filesIndex.size() != (int)fp.size())
|
||||
return;
|
||||
if (m_filesIndex.size() != fp.size()) return;
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
for (uint i = 0; i < fp.size(); ++i) {
|
||||
for (int i = 0; i < fp.size(); ++i) {
|
||||
m_filesIndex[i]->setProgress(fp[i]);
|
||||
}
|
||||
// Update folders progress in the tree
|
||||
@@ -77,7 +78,7 @@ void TorrentContentModel::updateFilesProgress(const std::vector<libtorrent::size
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void TorrentContentModel::updateFilesPriorities(const std::vector<int>& fprio)
|
||||
void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio)
|
||||
{
|
||||
Q_ASSERT(m_filesIndex.size() == (int)fprio.size());
|
||||
// XXX: Why is this necessary?
|
||||
@@ -85,15 +86,15 @@ void TorrentContentModel::updateFilesPriorities(const std::vector<int>& fprio)
|
||||
return;
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
for (uint i = 0; i < fprio.size(); ++i) {
|
||||
for (int i = 0; i < fprio.size(); ++i) {
|
||||
m_filesIndex[i]->setPriority(fprio[i]);
|
||||
}
|
||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
std::vector<int> TorrentContentModel::getFilesPriorities() const
|
||||
QVector<int> TorrentContentModel::getFilePriorities() const
|
||||
{
|
||||
std::vector<int> prio;
|
||||
QVector<int> prio;
|
||||
prio.reserve(m_filesIndex.size());
|
||||
foreach (const TorrentContentModelFile* file, m_filesIndex) {
|
||||
prio.push_back(file->priority());
|
||||
@@ -280,23 +281,22 @@ void TorrentContentModel::clear()
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void TorrentContentModel::setupModelData(const libtorrent::torrent_info& t)
|
||||
void TorrentContentModel::setupModelData(const BitTorrent::TorrentInfo &info)
|
||||
{
|
||||
qDebug("setup model data called");
|
||||
if (t.num_files() == 0)
|
||||
if (info.filesCount() == 0)
|
||||
return;
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
// Initialize files_index array
|
||||
qDebug("Torrent contains %d files", t.num_files());
|
||||
m_filesIndex.reserve(t.num_files());
|
||||
qDebug("Torrent contains %d files", info.filesCount());
|
||||
m_filesIndex.reserve(info.filesCount());
|
||||
|
||||
TorrentContentModelFolder* current_parent;
|
||||
// Iterate over files
|
||||
for (int i = 0; i < t.num_files(); ++i) {
|
||||
const libtorrent::file_entry& fentry = t.file_at(i);
|
||||
for (int i = 0; i < info.filesCount(); ++i) {
|
||||
current_parent = m_rootItem;
|
||||
QString path = fsutils::fromNativePath(misc::toQStringU(fentry.path));
|
||||
QString path = fsutils::fromNativePath(info.filePath(i));
|
||||
// Iterate of parts of the path to create necessary folders
|
||||
QStringList pathFolders = path.split("/", QString::SkipEmptyParts);
|
||||
pathFolders.removeLast();
|
||||
@@ -311,7 +311,7 @@ void TorrentContentModel::setupModelData(const libtorrent::torrent_info& t)
|
||||
current_parent = new_parent;
|
||||
}
|
||||
// Actually create the file
|
||||
TorrentContentModelFile* fileItem = new TorrentContentModelFile(fentry, current_parent, i);
|
||||
TorrentContentModelFile* fileItem = new TorrentContentModelFile(info.fileName(i), info.fileSize(i), current_parent, i);
|
||||
current_parent->appendChild(fileItem);
|
||||
m_filesIndex.push_back(fileItem);
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
#include "core/bittorrent/torrentinfo.h"
|
||||
#include "torrentcontentmodelitem.h"
|
||||
|
||||
class TorrentContentModelFile;
|
||||
@@ -49,9 +48,9 @@ public:
|
||||
TorrentContentModel(QObject *parent = 0);
|
||||
~TorrentContentModel();
|
||||
|
||||
void updateFilesProgress(const std::vector<libtorrent::size_type>& fp);
|
||||
void updateFilesPriorities(const std::vector<int> &fprio);
|
||||
std::vector<int> getFilesPriorities() const;
|
||||
void updateFilesProgress(const QVector<qreal> &fp);
|
||||
void updateFilesPriorities(const QVector<int> &fprio);
|
||||
QVector<int> getFilePriorities() const;
|
||||
bool allFiltered() const;
|
||||
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
|
||||
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
||||
@@ -64,7 +63,7 @@ public:
|
||||
virtual QModelIndex parent(const QModelIndex& index) const;
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
void clear();
|
||||
void setupModelData(const libtorrent::torrent_info& t);
|
||||
void setupModelData(const BitTorrent::TorrentInfo &info);
|
||||
|
||||
signals:
|
||||
void filteredFilesChanged();
|
||||
|
||||
@@ -30,24 +30,21 @@
|
||||
|
||||
#include "torrentcontentmodelfile.h"
|
||||
#include "torrentcontentmodelfolder.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
|
||||
TorrentContentModelFile::TorrentContentModelFile(const libtorrent::file_entry& f,
|
||||
TorrentContentModelFolder* parent,
|
||||
int file_index)
|
||||
TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulonglong fileSize,
|
||||
TorrentContentModelFolder* parent, int file_index)
|
||||
: TorrentContentModelItem(parent)
|
||||
, m_fileIndex(file_index)
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
|
||||
m_name = fsutils::fileName(misc::toQStringU(f.path.c_str()));
|
||||
m_name = fileName;
|
||||
|
||||
// Do not display incomplete extensions
|
||||
if (m_name.endsWith(".!qB"))
|
||||
m_name.chop(4);
|
||||
|
||||
m_size = (qulonglong)f.size;
|
||||
m_size = fileSize;
|
||||
}
|
||||
|
||||
int TorrentContentModelFile::fileIndex() const
|
||||
@@ -69,8 +66,8 @@ void TorrentContentModelFile::setPriority(int new_prio, bool update_parent)
|
||||
m_parentItem->updatePriority();
|
||||
}
|
||||
|
||||
void TorrentContentModelFile::setProgress(qulonglong done)
|
||||
void TorrentContentModelFile::setProgress(qreal progress)
|
||||
{
|
||||
m_totalDone = done;
|
||||
Q_ASSERT(m_totalDone <= m_size);
|
||||
m_progress = progress;
|
||||
Q_ASSERT(m_progress <= 1.);
|
||||
}
|
||||
|
||||
@@ -36,13 +36,12 @@
|
||||
class TorrentContentModelFile : public TorrentContentModelItem
|
||||
{
|
||||
public:
|
||||
TorrentContentModelFile(const libtorrent::file_entry& f,
|
||||
TorrentContentModelFolder* parent,
|
||||
int file_index);
|
||||
TorrentContentModelFile(const QString &fileName, qulonglong fileSize,
|
||||
TorrentContentModelFolder* parent, int file_index);
|
||||
|
||||
int fileIndex() const;
|
||||
void setPriority(int new_prio, bool update_parent = true);
|
||||
void setProgress(qulonglong done);
|
||||
void setProgress(qreal progress);
|
||||
ItemType itemType() const { return FileType; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include "torrentcontentmodelfolder.h"
|
||||
|
||||
TorrentContentModelFolder::TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent)
|
||||
@@ -135,18 +136,20 @@ void TorrentContentModelFolder::setPriority(int new_prio, bool update_parent)
|
||||
|
||||
void TorrentContentModelFolder::recalculateProgress()
|
||||
{
|
||||
qulonglong totalDone = 0;
|
||||
qreal progress = 0;
|
||||
int count = 0;
|
||||
foreach (TorrentContentModelItem* child, m_childItems) {
|
||||
if (child->priority() != prio::IGNORED) {
|
||||
if (child->itemType() == FolderType)
|
||||
static_cast<TorrentContentModelFolder*>(child)->recalculateProgress();
|
||||
totalDone += child->totalDone();
|
||||
progress += child->progress();
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRootItem()) {
|
||||
m_totalDone = totalDone;
|
||||
Q_ASSERT(m_totalDone <= m_size);
|
||||
if (!isRootItem() && (count > 0)) {
|
||||
m_progress = progress / count;
|
||||
Q_ASSERT(m_progress <= 1.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder* pare
|
||||
: m_parentItem(parent)
|
||||
, m_size(0)
|
||||
, m_priority(prio::NORMAL)
|
||||
, m_totalDone(0)
|
||||
, m_progress(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,21 +65,14 @@ qulonglong TorrentContentModelItem::size() const
|
||||
return m_size;
|
||||
}
|
||||
|
||||
qulonglong TorrentContentModelItem::totalDone() const
|
||||
qreal TorrentContentModelItem::progress() const
|
||||
{
|
||||
Q_ASSERT(!isRootItem());
|
||||
return m_totalDone;
|
||||
}
|
||||
Q_ASSERT(!isRootItem());
|
||||
if (m_priority == prio::IGNORED) return 0;
|
||||
|
||||
float TorrentContentModelItem::progress() const
|
||||
{
|
||||
Q_ASSERT(!isRootItem());
|
||||
if (m_priority == prio::IGNORED)
|
||||
return 0;
|
||||
if (m_size > 0) return m_progress;
|
||||
|
||||
if (m_size > 0)
|
||||
return m_totalDone / (double) m_size;
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TorrentContentModelItem::priority() const
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
namespace prio {
|
||||
enum FilePriority {IGNORED=0, NORMAL=1, HIGH=2, MAXIMUM=7, MIXED=-1};
|
||||
}
|
||||
@@ -58,9 +56,7 @@ public:
|
||||
void setName(const QString& name);
|
||||
|
||||
qulonglong size() const;
|
||||
qulonglong totalDone() const;
|
||||
|
||||
float progress() const;
|
||||
qreal progress() const;
|
||||
|
||||
int priority() const;
|
||||
virtual void setPriority(int new_prio, bool update_parent = true) = 0;
|
||||
@@ -77,7 +73,7 @@ protected:
|
||||
QString m_name;
|
||||
qulonglong m_size;
|
||||
int m_priority;
|
||||
qulonglong m_totalDone;
|
||||
qreal m_progress;
|
||||
};
|
||||
|
||||
#endif // TORRENTCONTENTMODELITEM_H
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
FORMS += $$PWD/createtorrent.ui
|
||||
|
||||
HEADERS += $$PWD/torrentcreatordlg.h \
|
||||
$$PWD/torrentcreatorthread.h
|
||||
|
||||
SOURCES += $$PWD/torrentcreatordlg.cpp \
|
||||
$$PWD/torrentcreatorthread.cpp
|
||||
|
||||
@@ -32,41 +32,39 @@
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "torrentcreatordlg.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/preferences.h"
|
||||
#include "torrentcreatorthread.h"
|
||||
#include "iconprovider.h"
|
||||
#include "qbtsession.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/torrentinfo.h"
|
||||
#include "core/bittorrent/torrentcreatorthread.h"
|
||||
|
||||
const uint NB_PIECES_MIN = 1200;
|
||||
const uint NB_PIECES_MAX = 2200;
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent): QDialog(parent), creatorThread(0) {
|
||||
TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent): QDialog(parent), m_creatorThread(0) {
|
||||
setupUi(this);
|
||||
// Icons
|
||||
addFile_button->setIcon(IconProvider::instance()->getIcon("document-new"));
|
||||
addFolder_button->setIcon(IconProvider::instance()->getIcon("folder-new"));
|
||||
createButton->setIcon(IconProvider::instance()->getIcon("document-save"));
|
||||
cancelButton->setIcon(IconProvider::instance()->getIcon("dialog-cancel"));
|
||||
addFile_button->setIcon(GuiIconProvider::instance()->getIcon("document-new"));
|
||||
addFolder_button->setIcon(GuiIconProvider::instance()->getIcon("folder-new"));
|
||||
createButton->setIcon(GuiIconProvider::instance()->getIcon("document-save"));
|
||||
cancelButton->setIcon(GuiIconProvider::instance()->getIcon("dialog-cancel"));
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setModal(true);
|
||||
showProgressBar(false);
|
||||
loadTrackerList();
|
||||
// Piece sizes
|
||||
m_piece_sizes << 32 << 64 << 128 << 256 << 512 << 1024 << 2048 << 4096;
|
||||
m_pieceSizes << 32 << 64 << 128 << 256 << 512 << 1024 << 2048 << 4096;
|
||||
loadSettings();
|
||||
show();
|
||||
}
|
||||
|
||||
TorrentCreatorDlg::~TorrentCreatorDlg() {
|
||||
if (creatorThread)
|
||||
delete creatorThread;
|
||||
if (m_creatorThread)
|
||||
delete m_creatorThread;
|
||||
}
|
||||
|
||||
void TorrentCreatorDlg::on_addFolder_button_clicked() {
|
||||
@@ -96,7 +94,7 @@ void TorrentCreatorDlg::on_addFile_button_clicked() {
|
||||
}
|
||||
|
||||
int TorrentCreatorDlg::getPieceSize() const {
|
||||
return m_piece_sizes.at(comboPieceSize->currentIndex())*1024;
|
||||
return m_pieceSizes.at(comboPieceSize->currentIndex())*1024;
|
||||
}
|
||||
|
||||
// Main function that create a .torrent file
|
||||
@@ -132,11 +130,11 @@ void TorrentCreatorDlg::on_createButton_clicked() {
|
||||
QStringList url_seeds = URLSeeds_list->toPlainText().split("\n");
|
||||
QString comment = txt_comment->toPlainText();
|
||||
// Create the creator thread
|
||||
creatorThread = new TorrentCreatorThread(this);
|
||||
connect(creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString)));
|
||||
connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
|
||||
connect(creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
|
||||
creatorThread->create(input, destination, trackers, url_seeds, comment, check_private->isChecked(), getPieceSize());
|
||||
m_creatorThread = new BitTorrent::TorrentCreatorThread(this);
|
||||
connect(m_creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString)));
|
||||
connect(m_creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
|
||||
connect(m_creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
|
||||
m_creatorThread->create(input, destination, trackers, url_seeds, comment, check_private->isChecked(), getPieceSize());
|
||||
}
|
||||
|
||||
void TorrentCreatorDlg::handleCreationFailure(QString msg) {
|
||||
@@ -152,33 +150,31 @@ void TorrentCreatorDlg::handleCreationSuccess(QString path, QString branch_path)
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
if (checkStartSeeding->isChecked()) {
|
||||
// Create save path temp data
|
||||
boost::intrusive_ptr<torrent_info> t;
|
||||
try {
|
||||
t = new torrent_info(fsutils::toNativePath(path).toUtf8().data());
|
||||
} catch(std::exception&) {
|
||||
BitTorrent::TorrentInfo t = BitTorrent::TorrentInfo::loadFromFile(fsutils::toNativePath(path));
|
||||
if (!t.isValid()) {
|
||||
QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
|
||||
return;
|
||||
}
|
||||
QString hash = misc::toQString(t->info_hash());
|
||||
QString save_path = branch_path;
|
||||
TorrentTempData::setSavePath(hash, save_path);
|
||||
// Enable seeding mode (do not recheck the files)
|
||||
TorrentTempData::setSeedingMode(hash, true);
|
||||
emit torrent_to_seed(path);
|
||||
if (checkIgnoreShareLimits->isChecked())
|
||||
QBtSession::instance()->setMaxRatioPerTorrent(hash, -1);
|
||||
|
||||
BitTorrent::AddTorrentParams params;
|
||||
params.savePath = branch_path;
|
||||
params.skipChecking = true;
|
||||
params.ignoreShareRatio = checkIgnoreShareLimits->isChecked();
|
||||
|
||||
BitTorrent::Session::instance()->addTorrent(t, params);
|
||||
}
|
||||
|
||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+fsutils::toNativePath(path));
|
||||
close();
|
||||
}
|
||||
|
||||
void TorrentCreatorDlg::on_cancelButton_clicked() {
|
||||
// End torrent creation thread
|
||||
if (creatorThread && creatorThread->isRunning()) {
|
||||
creatorThread->abortCreation();
|
||||
creatorThread->terminate();
|
||||
if (m_creatorThread && m_creatorThread->isRunning()) {
|
||||
m_creatorThread->abortCreation();
|
||||
m_creatorThread->terminate();
|
||||
// Wait for termination
|
||||
creatorThread->wait();
|
||||
m_creatorThread->wait();
|
||||
}
|
||||
// Close the dialog
|
||||
close();
|
||||
@@ -227,7 +223,7 @@ void TorrentCreatorDlg::updateOptimalPieceSize()
|
||||
int i = 0;
|
||||
qulonglong nb_pieces = 0;
|
||||
do {
|
||||
nb_pieces = (double)torrent_size/(m_piece_sizes.at(i)*1024.);
|
||||
nb_pieces = (double)torrent_size/(m_pieceSizes.at(i)*1024.);
|
||||
qDebug("nb_pieces=%lld with piece_size=%s", nb_pieces, qPrintable(comboPieceSize->itemText(i)));
|
||||
if (nb_pieces <= NB_PIECES_MIN) {
|
||||
if (i > 1)
|
||||
@@ -239,7 +235,7 @@ void TorrentCreatorDlg::updateOptimalPieceSize()
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}while(i<(m_piece_sizes.size()-1));
|
||||
}while(i<(m_pieceSizes.size()-1));
|
||||
comboPieceSize->setCurrentIndex(i);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
|
||||
#include "ui_createtorrent.h"
|
||||
|
||||
class TorrentCreatorThread;
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentCreatorThread;
|
||||
}
|
||||
|
||||
class TorrentCreatorDlg : public QDialog, private Ui::createTorrentDialog{
|
||||
Q_OBJECT
|
||||
@@ -43,9 +46,6 @@ public:
|
||||
~TorrentCreatorDlg();
|
||||
int getPieceSize() const;
|
||||
|
||||
signals:
|
||||
void torrent_to_seed(QString path);
|
||||
|
||||
public slots:
|
||||
void updateProgressBar(int progress);
|
||||
void on_cancelButton_clicked();
|
||||
@@ -71,8 +71,8 @@ private:
|
||||
void loadSettings();
|
||||
|
||||
private:
|
||||
TorrentCreatorThread *creatorThread;
|
||||
QList<int> m_piece_sizes;
|
||||
BitTorrent::TorrentCreatorThread *m_creatorThread;
|
||||
QList<int> m_pieceSizes;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -35,22 +35,20 @@
|
||||
#include "torrentimportdlg.h"
|
||||
#include "ui_torrentimportdlg.h"
|
||||
#include "core/preferences.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "iconprovider.h"
|
||||
#include "core/bittorrent/infohash.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/fs_utils.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
TorrentImportDlg::TorrentImportDlg(QWidget *parent):
|
||||
QDialog(parent),
|
||||
ui(new Ui::TorrentImportDlg)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
// Icons
|
||||
ui->lbl_info->setPixmap(IconProvider::instance()->getIcon("dialog-information").pixmap(ui->lbl_info->height()));
|
||||
ui->lbl_info->setPixmap(GuiIconProvider::instance()->getIcon("dialog-information").pixmap(ui->lbl_info->height()));
|
||||
ui->lbl_info->setFixedWidth(ui->lbl_info->height());
|
||||
ui->importBtn->setIcon(IconProvider::instance()->getIcon("document-import"));
|
||||
ui->importBtn->setIcon(GuiIconProvider::instance()->getIcon("document-import"));
|
||||
// Libtorrent < 0.15 does not support skipping file checking
|
||||
loadSettings();
|
||||
}
|
||||
@@ -74,13 +72,14 @@ void TorrentImportDlg::on_browseTorrentBtn_clicked()
|
||||
void TorrentImportDlg::on_browseContentBtn_clicked()
|
||||
{
|
||||
const QString default_dir = Preferences::instance()->getTorImportLastContentDir();
|
||||
bool multifile = t->num_files() > 1;
|
||||
if (!multifile && (fsutils::fromNativePath(misc::toQStringU(t->file_at(0).path)).indexOf('/') != -1))
|
||||
bool multifile = (m_torrentInfo.filesCount() > 1);
|
||||
QString filePath = fsutils::fromNativePath(m_torrentInfo.filePath(0));
|
||||
if (!multifile && (filePath.indexOf('/') != -1))
|
||||
multifile = true;
|
||||
|
||||
if (!multifile) {
|
||||
// Single file torrent
|
||||
const QString file_name = fsutils::fileName(misc::toQStringU(t->file_at(0).path));
|
||||
const QString file_name = fsutils::fileName(filePath);
|
||||
qDebug("Torrent has only one file: %s", qPrintable(file_name));
|
||||
QString extension = fsutils::fileExtension(file_name);
|
||||
qDebug("File extension is : %s", qPrintable(extension));
|
||||
@@ -100,7 +99,7 @@ void TorrentImportDlg::on_browseContentBtn_clicked()
|
||||
ui->lineContent->setText(fsutils::toNativePath(m_contentPath));
|
||||
// Check file size
|
||||
const qint64 file_size = QFile(m_contentPath).size();
|
||||
if (t->file_at(0).size == file_size) {
|
||||
if (m_torrentInfo.fileSize(0) == file_size) {
|
||||
qDebug("The file size matches, allowing fast seeding...");
|
||||
ui->checkSkipCheck->setEnabled(true);
|
||||
}
|
||||
@@ -122,7 +121,7 @@ void TorrentImportDlg::on_browseContentBtn_clicked()
|
||||
}
|
||||
else {
|
||||
// multiple files torrent
|
||||
m_contentPath = QFileDialog::getExistingDirectory(this, tr("Please point to the location of the torrent: %1").arg(misc::toQStringU(t->name())),
|
||||
m_contentPath = QFileDialog::getExistingDirectory(this, tr("Please point to the location of the torrent: %1").arg(m_torrentInfo.name()),
|
||||
default_dir);
|
||||
if (m_contentPath.isEmpty() || !QDir(m_contentPath).exists()) {
|
||||
m_contentPath = QString::null;
|
||||
@@ -136,13 +135,13 @@ void TorrentImportDlg::on_browseContentBtn_clicked()
|
||||
QDir content_dir(m_contentPath);
|
||||
content_dir.cdUp();
|
||||
// Check file sizes
|
||||
for (int i = 0; i<t->num_files(); ++i) {
|
||||
const QString rel_path = misc::toQStringU(t->file_at(i).path);
|
||||
if (QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size() != t->file_at(i).size) {
|
||||
for (int i = 0; i < m_torrentInfo.filesCount(); ++i) {
|
||||
const QString rel_path = m_torrentInfo.filePath(i);
|
||||
if (QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size() != m_torrentInfo.fileSize(i)) {
|
||||
qDebug("%s is %lld",
|
||||
qPrintable(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))), (long long int) QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size());
|
||||
qDebug("%s is %lld",
|
||||
qPrintable(rel_path), (long long int)t->file_at(i).size);
|
||||
qPrintable(rel_path), (long long int)m_torrentInfo.fileSize(i));
|
||||
size_mismatch = true;
|
||||
break;
|
||||
}
|
||||
@@ -184,63 +183,57 @@ void TorrentImportDlg::importTorrent()
|
||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||
TorrentImportDlg dlg;
|
||||
if (dlg.exec()) {
|
||||
BitTorrent::AddTorrentParams params;
|
||||
qDebug() << "Loading the torrent file...";
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> t = dlg.torrent();
|
||||
if (!t->is_valid())
|
||||
return;
|
||||
QString torrent_path = dlg.getTorrentPath();
|
||||
QString content_path = dlg.getContentPath();
|
||||
if (torrent_path.isEmpty() || content_path.isEmpty() || !QFile(torrent_path).exists()) {
|
||||
qWarning() << "Incorrect input, aborting." << torrent_path << content_path;
|
||||
BitTorrent::TorrentInfo torrentInfo = dlg.torrent();
|
||||
if (!torrentInfo.isValid()) return;
|
||||
|
||||
QString torrentPath = dlg.getTorrentPath();
|
||||
QString contentPath = dlg.getContentPath();
|
||||
if (torrentPath.isEmpty() || contentPath.isEmpty() || !QFile(torrentPath).exists()) {
|
||||
qWarning() << "Incorrect input, aborting." << torrentPath << contentPath;
|
||||
return;
|
||||
}
|
||||
const QString hash = misc::toQString(t->info_hash());
|
||||
|
||||
const QString hash = torrentInfo.hash();
|
||||
qDebug() << "Torrent hash is" << hash;
|
||||
TorrentTempData::setSavePath(hash, content_path);
|
||||
TorrentTempData::setSeedingMode(hash, dlg.skipFileChecking());
|
||||
params.savePath = contentPath;
|
||||
params.skipChecking = dlg.skipFileChecking();
|
||||
params.disableTempPath = true;
|
||||
qDebug("Adding the torrent to the session...");
|
||||
QBtSession::instance()->addTorrent(torrent_path, false, QString(), false, true);
|
||||
BitTorrent::Session::instance()->addTorrent(torrentInfo, params);
|
||||
// Remember the last opened folder
|
||||
Preferences* const pref = Preferences::instance();
|
||||
pref->setMainLastDir(fsutils::fromNativePath(torrent_path));
|
||||
pref->setTorImportLastContentDir(fsutils::fromNativePath(content_path));
|
||||
pref->setMainLastDir(fsutils::fromNativePath(torrentPath));
|
||||
pref->setTorImportLastContentDir(fsutils::fromNativePath(contentPath));
|
||||
return;
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||
return;
|
||||
}
|
||||
|
||||
void TorrentImportDlg::loadTorrent(const QString &torrent_path)
|
||||
void TorrentImportDlg::loadTorrent(const QString &torrentPath)
|
||||
{
|
||||
// Load the torrent file
|
||||
try {
|
||||
std::vector<char> buffer;
|
||||
lazy_entry entry;
|
||||
libtorrent::error_code ec;
|
||||
misc::loadBencodedFile(torrent_path, buffer, entry, ec);
|
||||
t = new torrent_info(entry);
|
||||
if (!t->is_valid() || t->num_files() == 0)
|
||||
throw std::exception();
|
||||
}
|
||||
catch(std::exception&) {
|
||||
m_torrentInfo = BitTorrent::TorrentInfo::loadFromFile(torrentPath);
|
||||
if (!m_torrentInfo.isValid()) {
|
||||
ui->browseContentBtn->setEnabled(false);
|
||||
ui->lineTorrent->clear();
|
||||
QMessageBox::warning(this, tr("Invalid torrent file"), tr("This is not a valid torrent file."));
|
||||
return;
|
||||
}
|
||||
// Update display
|
||||
ui->lineTorrent->setText(fsutils::toNativePath(torrent_path));
|
||||
ui->browseContentBtn->setEnabled(true);
|
||||
// Load the file names
|
||||
initializeFilesPath();
|
||||
else {
|
||||
// Update display
|
||||
ui->lineTorrent->setText(fsutils::toNativePath(torrentPath));
|
||||
ui->browseContentBtn->setEnabled(true);
|
||||
// Load the file names
|
||||
initializeFilesPath();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImportDlg::initializeFilesPath()
|
||||
{
|
||||
m_filesPath.clear();
|
||||
// Loads files path in the torrent
|
||||
for (int i = 0; i<t->num_files(); ++i)
|
||||
m_filesPath << fsutils::fromNativePath(misc::toQStringU(t->file_at(i).path));
|
||||
m_filesPath = m_torrentInfo.filePaths();
|
||||
}
|
||||
|
||||
bool TorrentImportDlg::fileRenamed() const
|
||||
@@ -249,9 +242,9 @@ bool TorrentImportDlg::fileRenamed() const
|
||||
}
|
||||
|
||||
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> TorrentImportDlg::torrent() const
|
||||
BitTorrent::TorrentInfo TorrentImportDlg::torrent() const
|
||||
{
|
||||
return t;
|
||||
return m_torrentInfo;
|
||||
}
|
||||
|
||||
bool TorrentImportDlg::skipFileChecking() const
|
||||
|
||||
@@ -34,16 +34,12 @@
|
||||
#include <QDialog>
|
||||
#include <QStringList>
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
#include "core/bittorrent/torrentinfo.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
namespace Ui
|
||||
{
|
||||
class TorrentImportDlg;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class QBtSession;
|
||||
|
||||
class TorrentImportDlg: public QDialog
|
||||
{
|
||||
@@ -52,22 +48,22 @@ class TorrentImportDlg: public QDialog
|
||||
public:
|
||||
explicit TorrentImportDlg(QWidget *parent = 0);
|
||||
~TorrentImportDlg();
|
||||
|
||||
static void importTorrent();
|
||||
|
||||
QString getTorrentPath() const;
|
||||
QString getContentPath() const;
|
||||
bool fileRenamed() const;
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> torrent() const;
|
||||
BitTorrent::TorrentInfo torrent() const;
|
||||
bool skipFileChecking() const;
|
||||
|
||||
protected slots:
|
||||
void loadTorrent(const QString &torrent_path);
|
||||
void loadTorrent(const QString &torrentPath);
|
||||
void initializeFilesPath();
|
||||
|
||||
private slots:
|
||||
void on_browseTorrentBtn_clicked();
|
||||
|
||||
void on_browseContentBtn_clicked();
|
||||
|
||||
void on_importBtn_clicked();
|
||||
|
||||
protected:
|
||||
@@ -79,7 +75,8 @@ private:
|
||||
|
||||
private:
|
||||
Ui::TorrentImportDlg *ui;
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> t;
|
||||
BitTorrent::TorrentInfo m_torrentInfo;
|
||||
// NOTE: Where do we use it?
|
||||
QStringList m_filesPath;
|
||||
QString m_contentPath;
|
||||
QString m_torrentPath;
|
||||
|
||||
@@ -31,15 +31,12 @@
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include <QPalette>
|
||||
#include <QIcon>
|
||||
|
||||
#include "torrentmodel.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/torrentfilter.h"
|
||||
#include "core/fs_utils.h"
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
#include "torrentmodel.h"
|
||||
|
||||
namespace {
|
||||
QIcon get_paused_icon() {
|
||||
@@ -96,110 +93,43 @@ bool isDarkTheme()
|
||||
}
|
||||
}
|
||||
|
||||
TorrentStatusReport::TorrentStatusReport()
|
||||
: nb_downloading(0)
|
||||
, nb_seeding(0)
|
||||
, nb_completed(0)
|
||||
, nb_active(0)
|
||||
, nb_inactive(0)
|
||||
, nb_paused(0)
|
||||
TorrentModelItem::TorrentModelItem(BitTorrent::TorrentHandle *torrent)
|
||||
: m_torrent(torrent)
|
||||
{
|
||||
}
|
||||
|
||||
TorrentModelItem::TorrentModelItem(const QTorrentHandle &h)
|
||||
: m_torrent(h)
|
||||
, m_lastStatus(h.status(torrent_handle::query_accurate_download_counters))
|
||||
, m_addedTime(TorrentPersistentData::instance()->getAddedDate(h.hash()))
|
||||
, m_label(TorrentPersistentData::instance()->getLabel(h.hash()))
|
||||
, m_name(TorrentPersistentData::instance()->getName(h.hash()))
|
||||
, m_hash(h.hash())
|
||||
BitTorrent::TorrentState TorrentModelItem::state() const
|
||||
{
|
||||
if (m_name.isEmpty())
|
||||
m_name = h.name();
|
||||
// If name is empty show the hash. This happens when magnet isn't retrieved.
|
||||
if (m_name.isEmpty())
|
||||
m_name = h.hash();
|
||||
return m_torrent->state();
|
||||
}
|
||||
|
||||
void TorrentModelItem::refreshStatus(libtorrent::torrent_status const& status) {
|
||||
m_lastStatus = status;
|
||||
}
|
||||
|
||||
TorrentModelItem::State TorrentModelItem::state() const {
|
||||
try {
|
||||
// Pause or Queued
|
||||
if (m_torrent.is_paused(m_lastStatus)) {
|
||||
if (TorrentPersistentData::instance()->getHasMissingFiles(misc::toQString(m_lastStatus.info_hash)))
|
||||
return STATE_PAUSED_MISSING;
|
||||
else
|
||||
return m_torrent.is_seed(m_lastStatus) ? STATE_PAUSED_UP : STATE_PAUSED_DL;
|
||||
}
|
||||
|
||||
if (m_torrent.is_queued(m_lastStatus)
|
||||
&& m_lastStatus.state != torrent_status::queued_for_checking
|
||||
&& m_lastStatus.state != torrent_status::checking_resume_data
|
||||
&& m_lastStatus.state != torrent_status::checking_files)
|
||||
return m_torrent.is_seed(m_lastStatus) ? STATE_QUEUED_UP : STATE_QUEUED_DL;
|
||||
|
||||
// Other states
|
||||
switch(m_lastStatus.state) {
|
||||
case torrent_status::allocating:
|
||||
return STATE_ALLOCATING;
|
||||
case torrent_status::downloading_metadata:
|
||||
return STATE_DOWNLOADING_META;
|
||||
case torrent_status::downloading:
|
||||
if (!m_torrent.is_forced(m_lastStatus))
|
||||
return m_lastStatus.download_payload_rate > 0 ? STATE_DOWNLOADING : STATE_STALLED_DL;
|
||||
else
|
||||
return STATE_FORCED_DL;
|
||||
case torrent_status::finished:
|
||||
case torrent_status::seeding:
|
||||
if (!m_torrent.is_forced(m_lastStatus))
|
||||
return m_lastStatus.upload_payload_rate > 0 ? STATE_SEEDING : STATE_STALLED_UP;
|
||||
else
|
||||
return STATE_FORCED_UP;
|
||||
case torrent_status::queued_for_checking:
|
||||
return STATE_QUEUED_CHECK;
|
||||
case torrent_status::checking_resume_data:
|
||||
return STATE_QUEUED_FASTCHECK;
|
||||
case torrent_status::checking_files:
|
||||
return m_torrent.is_seed(m_lastStatus) ? STATE_CHECKING_UP : STATE_CHECKING_DL;
|
||||
default:
|
||||
return STATE_INVALID;
|
||||
}
|
||||
} catch(invalid_handle&) {
|
||||
return STATE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
QIcon TorrentModelItem::getIconByState(State state) {
|
||||
QIcon TorrentModelItem::getIconByState(BitTorrent::TorrentState state)
|
||||
{
|
||||
switch (state) {
|
||||
case STATE_DOWNLOADING:
|
||||
case STATE_DOWNLOADING_META:
|
||||
case STATE_FORCED_DL:
|
||||
case BitTorrent::TorrentState::Downloading:
|
||||
case BitTorrent::TorrentState::ForcedDownloading:
|
||||
case BitTorrent::TorrentState::DownloadingMetadata:
|
||||
return get_downloading_icon();
|
||||
case STATE_ALLOCATING:
|
||||
case STATE_STALLED_DL:
|
||||
case BitTorrent::TorrentState::Allocating:
|
||||
case BitTorrent::TorrentState::StalledDownloading:
|
||||
return get_stalled_downloading_icon();
|
||||
case STATE_STALLED_UP:
|
||||
case BitTorrent::TorrentState::StalledUploading:
|
||||
return get_stalled_uploading_icon();
|
||||
case STATE_SEEDING:
|
||||
case STATE_FORCED_UP:
|
||||
case BitTorrent::TorrentState::Uploading:
|
||||
case BitTorrent::TorrentState::ForcedUploading:
|
||||
return get_uploading_icon();
|
||||
case STATE_PAUSED_DL:
|
||||
case BitTorrent::TorrentState::PausedDownloading:
|
||||
return get_paused_icon();
|
||||
case STATE_PAUSED_UP:
|
||||
case BitTorrent::TorrentState::PausedUploading:
|
||||
return get_completed_icon();
|
||||
case STATE_QUEUED_DL:
|
||||
case STATE_QUEUED_UP:
|
||||
case BitTorrent::TorrentState::QueuedDownloading:
|
||||
case BitTorrent::TorrentState::QueuedUploading:
|
||||
return get_queued_icon();
|
||||
case STATE_CHECKING_UP:
|
||||
case STATE_CHECKING_DL:
|
||||
case STATE_QUEUED_CHECK:
|
||||
case STATE_QUEUED_FASTCHECK:
|
||||
case BitTorrent::TorrentState::CheckingDownloading:
|
||||
case BitTorrent::TorrentState::CheckingUploading:
|
||||
return get_checking_icon();
|
||||
case STATE_INVALID:
|
||||
case STATE_PAUSED_MISSING:
|
||||
case BitTorrent::TorrentState::Unknown:
|
||||
case BitTorrent::TorrentState::Error:
|
||||
return get_error_icon();
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
@@ -207,43 +137,43 @@ QIcon TorrentModelItem::getIconByState(State state) {
|
||||
}
|
||||
}
|
||||
|
||||
QColor TorrentModelItem::getColorByState(State state) {
|
||||
QColor TorrentModelItem::getColorByState(BitTorrent::TorrentState state)
|
||||
{
|
||||
bool dark = isDarkTheme();
|
||||
|
||||
switch (state) {
|
||||
case STATE_DOWNLOADING:
|
||||
case STATE_DOWNLOADING_META:
|
||||
case STATE_FORCED_DL:
|
||||
case BitTorrent::TorrentState::Downloading:
|
||||
case BitTorrent::TorrentState::ForcedDownloading:
|
||||
case BitTorrent::TorrentState::DownloadingMetadata:
|
||||
return QColor(34, 139, 34); // Forest Green
|
||||
case STATE_ALLOCATING:
|
||||
case STATE_STALLED_DL:
|
||||
case STATE_STALLED_UP:
|
||||
case BitTorrent::TorrentState::Allocating:
|
||||
case BitTorrent::TorrentState::StalledDownloading:
|
||||
case BitTorrent::TorrentState::StalledUploading:
|
||||
if (!dark)
|
||||
return QColor(0, 0, 0); // Black
|
||||
else
|
||||
return QColor(255, 255, 255); // White
|
||||
case STATE_SEEDING:
|
||||
case STATE_FORCED_UP:
|
||||
case BitTorrent::TorrentState::Uploading:
|
||||
case BitTorrent::TorrentState::ForcedUploading:
|
||||
if (!dark)
|
||||
return QColor(65, 105, 225); // Royal Blue
|
||||
else
|
||||
return QColor(100, 149, 237); // Cornflower Blue
|
||||
case STATE_PAUSED_DL:
|
||||
case BitTorrent::TorrentState::PausedDownloading:
|
||||
return QColor(250, 128, 114); // Salmon
|
||||
case STATE_PAUSED_UP:
|
||||
case BitTorrent::TorrentState::PausedUploading:
|
||||
if (!dark)
|
||||
return QColor(0, 0, 139); // Dark Blue
|
||||
else
|
||||
return QColor(65, 105, 225); // Royal Blue
|
||||
case STATE_PAUSED_MISSING:
|
||||
case BitTorrent::TorrentState::Error:
|
||||
return QColor(255, 0, 0); // red
|
||||
case STATE_QUEUED_DL:
|
||||
case STATE_QUEUED_UP:
|
||||
case STATE_CHECKING_UP:
|
||||
case STATE_CHECKING_DL:
|
||||
case STATE_QUEUED_CHECK:
|
||||
case STATE_QUEUED_FASTCHECK:
|
||||
case BitTorrent::TorrentState::QueuedDownloading:
|
||||
case BitTorrent::TorrentState::QueuedUploading:
|
||||
case BitTorrent::TorrentState::CheckingDownloading:
|
||||
case BitTorrent::TorrentState::CheckingUploading:
|
||||
return QColor(0, 128, 128); // Teal
|
||||
case STATE_INVALID:
|
||||
case BitTorrent::TorrentState::Unknown:
|
||||
return QColor(255, 0, 0); // red
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
@@ -255,18 +185,17 @@ bool TorrentModelItem::setData(int column, const QVariant &value, int role)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << column << value;
|
||||
if (role != Qt::DisplayRole) return false;
|
||||
|
||||
// Label, seed date and Name columns can be edited
|
||||
switch(column) {
|
||||
case TR_NAME:
|
||||
m_name = value.toString();
|
||||
TorrentPersistentData::instance()->saveName(m_torrent.hash(), m_name);
|
||||
m_torrent->setName(value.toString());
|
||||
return true;
|
||||
case TR_LABEL: {
|
||||
QString new_label = value.toString();
|
||||
if (m_label != new_label) {
|
||||
QString old_label = m_label;
|
||||
m_label = new_label;
|
||||
TorrentPersistentData::instance()->saveLabel(m_torrent.hash(), new_label);
|
||||
if (m_torrent->label() != new_label) {
|
||||
QString old_label = m_torrent->label();
|
||||
m_torrent->setLabel(new_label);
|
||||
emit labelChanged(old_label, new_label);
|
||||
}
|
||||
return true;
|
||||
@@ -279,136 +208,118 @@ bool TorrentModelItem::setData(int column, const QVariant &value, int role)
|
||||
|
||||
QVariant TorrentModelItem::data(int column, int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole && column == TR_NAME) {
|
||||
if ((role == Qt::DecorationRole) && (column == TR_NAME))
|
||||
return getIconByState(state());
|
||||
}
|
||||
if (role == Qt::ForegroundRole) {
|
||||
|
||||
if (role == Qt::ForegroundRole)
|
||||
return getColorByState(state());
|
||||
}
|
||||
if (role != Qt::DisplayRole && role != Qt::UserRole) return QVariant();
|
||||
|
||||
if ((role != Qt::DisplayRole) && (role != Qt::UserRole))
|
||||
return QVariant();
|
||||
|
||||
switch(column) {
|
||||
case TR_NAME:
|
||||
return m_name.isEmpty() ? m_torrent.name() : m_name;
|
||||
case TR_PRIORITY: {
|
||||
int pos = m_torrent.queue_position(m_lastStatus);
|
||||
if (pos > -1)
|
||||
return pos - HiddenData::getSize();
|
||||
else
|
||||
return pos;
|
||||
}
|
||||
return m_torrent->name();
|
||||
case TR_PRIORITY:
|
||||
return m_torrent->queuePosition();
|
||||
case TR_SIZE:
|
||||
return m_lastStatus.has_metadata ? static_cast<qlonglong>(m_lastStatus.total_wanted) : -1;
|
||||
return m_torrent->hasMetadata() ? m_torrent->wantedSize() : -1;
|
||||
case TR_PROGRESS:
|
||||
return m_torrent.progress(m_lastStatus);
|
||||
return m_torrent->progress();
|
||||
case TR_STATUS:
|
||||
return state();
|
||||
case TR_SEEDS: {
|
||||
return (role == Qt::DisplayRole) ? m_lastStatus.num_seeds : m_lastStatus.num_complete;
|
||||
}
|
||||
case TR_PEERS: {
|
||||
return (role == Qt::DisplayRole) ? (m_lastStatus.num_peers-m_lastStatus.num_seeds) : m_lastStatus.num_incomplete;
|
||||
}
|
||||
return static_cast<int>(m_torrent->state());
|
||||
case TR_SEEDS:
|
||||
return (role == Qt::DisplayRole) ? m_torrent->seedsCount() : m_torrent->completeCount();
|
||||
case TR_PEERS:
|
||||
return (role == Qt::DisplayRole) ? (m_torrent->peersCount() - m_torrent->seedsCount()) : m_torrent->incompleteCount();
|
||||
case TR_DLSPEED:
|
||||
return m_lastStatus.download_payload_rate;
|
||||
return m_torrent->downloadPayloadRate();
|
||||
case TR_UPSPEED:
|
||||
return m_lastStatus.upload_payload_rate;
|
||||
case TR_ETA: {
|
||||
// XXX: Is this correct?
|
||||
if (m_torrent.is_paused(m_lastStatus) || m_torrent.is_queued(m_lastStatus)) return MAX_ETA;
|
||||
return QBtSession::instance()->getETA(m_hash, m_lastStatus);
|
||||
}
|
||||
return m_torrent->uploadPayloadRate();
|
||||
case TR_ETA:
|
||||
return m_torrent->eta();
|
||||
case TR_RATIO:
|
||||
return QBtSession::instance()->getRealRatio(m_lastStatus);
|
||||
return m_torrent->realRatio();
|
||||
case TR_LABEL:
|
||||
return m_label;
|
||||
return m_torrent->label();
|
||||
case TR_ADD_DATE:
|
||||
return m_addedTime;
|
||||
return m_torrent->addedTime();
|
||||
case TR_SEED_DATE:
|
||||
return m_lastStatus.completed_time ? QDateTime::fromTime_t(m_lastStatus.completed_time) : QDateTime();
|
||||
return m_torrent->completedTime();
|
||||
case TR_TRACKER:
|
||||
return misc::toQString(m_lastStatus.current_tracker);
|
||||
return m_torrent->currentTracker();
|
||||
case TR_DLLIMIT:
|
||||
return m_torrent.download_limit();
|
||||
return m_torrent->downloadLimit();
|
||||
case TR_UPLIMIT:
|
||||
return m_torrent.upload_limit();
|
||||
return m_torrent->uploadLimit();
|
||||
case TR_AMOUNT_DOWNLOADED:
|
||||
return static_cast<qlonglong>(m_lastStatus.all_time_download);
|
||||
return m_torrent->totalDownload();
|
||||
case TR_AMOUNT_UPLOADED:
|
||||
return static_cast<qlonglong>(m_lastStatus.all_time_upload);
|
||||
return m_torrent->totalUpload();
|
||||
case TR_AMOUNT_DOWNLOADED_SESSION:
|
||||
return static_cast<qlonglong>(m_lastStatus.total_payload_download);
|
||||
return m_torrent->totalPayloadDownload();
|
||||
case TR_AMOUNT_UPLOADED_SESSION:
|
||||
return static_cast<qlonglong>(m_lastStatus.total_payload_upload);
|
||||
return m_torrent->totalPayloadUpload();
|
||||
case TR_AMOUNT_LEFT:
|
||||
return static_cast<qlonglong>(m_lastStatus.total_wanted - m_lastStatus.total_wanted_done);
|
||||
return m_torrent->incompletedSize();
|
||||
case TR_TIME_ELAPSED:
|
||||
return (role == Qt::DisplayRole) ? m_lastStatus.active_time : m_lastStatus.seeding_time;
|
||||
return (role == Qt::DisplayRole) ? m_torrent->activeTime() : m_torrent->seedingTime();
|
||||
case TR_SAVE_PATH:
|
||||
return fsutils::toNativePath(m_torrent.save_path_parsed());
|
||||
return m_torrent->savePathParsed();
|
||||
case TR_COMPLETED:
|
||||
return static_cast<qlonglong>(m_lastStatus.total_wanted_done);
|
||||
case TR_RATIO_LIMIT: {
|
||||
QString hash = misc::toQString(m_lastStatus.info_hash);
|
||||
return QBtSession::instance()->getMaxRatioPerTorrent(hash, NULL);
|
||||
}
|
||||
return m_torrent->completedSize();
|
||||
case TR_RATIO_LIMIT:
|
||||
return m_torrent->maxRatio();
|
||||
case TR_SEEN_COMPLETE_DATE:
|
||||
return m_lastStatus.last_seen_complete ? QDateTime::fromTime_t(m_lastStatus.last_seen_complete) : QDateTime();
|
||||
return m_torrent->lastSeenComplete();
|
||||
case TR_LAST_ACTIVITY:
|
||||
if (m_torrent.is_paused(m_lastStatus) || m_torrent.is_checking(m_lastStatus))
|
||||
if (m_torrent->isPaused() || m_torrent->isChecking())
|
||||
return -1;
|
||||
if (m_lastStatus.time_since_upload < m_lastStatus.time_since_download)
|
||||
return m_lastStatus.time_since_upload;
|
||||
if (m_torrent->timeSinceUpload() < m_torrent->timeSinceDownload())
|
||||
return m_torrent->timeSinceUpload();
|
||||
else
|
||||
return m_lastStatus.time_since_download;
|
||||
return m_torrent->timeSinceDownload();
|
||||
case TR_TOTAL_SIZE:
|
||||
return m_lastStatus.has_metadata ? static_cast<qlonglong>(m_torrent.total_size()) : -1;
|
||||
return m_torrent->hasMetadata() ? m_torrent->totalSize() : -1;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QTorrentHandle TorrentModelItem::torrentHandle() const
|
||||
BitTorrent::TorrentHandle *TorrentModelItem::torrentHandle() const
|
||||
{
|
||||
return m_torrent;
|
||||
}
|
||||
|
||||
// TORRENT MODEL
|
||||
|
||||
TorrentModel::TorrentModel(QObject *parent) :
|
||||
QAbstractListModel(parent), m_refreshInterval(2000)
|
||||
TorrentModel::TorrentModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void TorrentModel::populate() {
|
||||
void TorrentModel::populate()
|
||||
{
|
||||
// Load the torrents
|
||||
std::vector<torrent_handle> torrents = QBtSession::instance()->getSession()->get_torrents();
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||
addTorrent(torrent);
|
||||
|
||||
std::vector<torrent_handle>::const_iterator it = torrents.begin();
|
||||
std::vector<torrent_handle>::const_iterator itend = torrents.end();
|
||||
for ( ; it != itend; ++it) {
|
||||
const QTorrentHandle h(*it);
|
||||
if (HiddenData::hasData(h.hash()))
|
||||
continue;
|
||||
addTorrent(h);
|
||||
}
|
||||
// Refresh timer
|
||||
connect(&m_refreshTimer, SIGNAL(timeout()), SLOT(forceModelRefresh()));
|
||||
m_refreshTimer.start(m_refreshInterval);
|
||||
// Listen for torrent changes
|
||||
connect(QBtSession::instance(), SIGNAL(addedTorrent(QTorrentHandle)), SLOT(addTorrent(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(torrentAboutToBeRemoved(QTorrentHandle)), SLOT(handleTorrentAboutToBeRemoved(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(finishedTorrent(QTorrentHandle)), SLOT(handleFinishedTorrent(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(metadataReceived(QTorrentHandle)), SLOT(handleTorrentUpdate(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(resumedTorrent(QTorrentHandle)), SLOT(handleTorrentUpdate(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(pausedTorrent(QTorrentHandle)), SLOT(handleTorrentUpdate(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(torrentFinishedChecking(QTorrentHandle)), SLOT(handleTorrentUpdate(QTorrentHandle)));
|
||||
connect(QBtSession::instance(), SIGNAL(stateUpdate(std::vector<libtorrent::torrent_status>)), SLOT(stateUpdated(std::vector<libtorrent::torrent_status>)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentAdded(BitTorrent::TorrentHandle *const)), SLOT(addTorrent(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentStatusUpdated(BitTorrent::TorrentHandle *const)), this, SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentResumed(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentPaused(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinishedChecking(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
}
|
||||
|
||||
TorrentModel::~TorrentModel() {
|
||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||
qDeleteAll(m_torrents);
|
||||
m_torrents.clear();
|
||||
qDeleteAll(m_items);
|
||||
m_items.clear();
|
||||
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||
}
|
||||
|
||||
@@ -485,49 +396,47 @@ QVariant TorrentModel::headerData(int section, Qt::Orientation orientation,
|
||||
QVariant TorrentModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) return QVariant();
|
||||
try {
|
||||
if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount())
|
||||
return m_torrents[index.row()]->data(index.column(), role);
|
||||
} catch(invalid_handle&) {}
|
||||
|
||||
if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount())
|
||||
return m_items[index.row()]->data(index.column(), role);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool TorrentModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << value;
|
||||
if (!index.isValid() || role != Qt::DisplayRole) return false;
|
||||
if (!index.isValid() || (role != Qt::DisplayRole)) return false;
|
||||
|
||||
qDebug("Index is valid and role is DisplayRole");
|
||||
try {
|
||||
if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount()) {
|
||||
bool change = m_torrents[index.row()]->setData(index.column(), value, role);
|
||||
if (change)
|
||||
notifyTorrentChanged(index.row());
|
||||
return change;
|
||||
}
|
||||
} catch(invalid_handle&) {}
|
||||
if ((index.row() >= 0) && (index.row() < rowCount()) && (index.column() >= 0) && (index.column() < columnCount())) {
|
||||
bool change = m_items[index.row()]->setData(index.column(), value, role);
|
||||
if (change)
|
||||
notifyTorrentChanged(index.row());
|
||||
return change;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int TorrentModel::torrentRow(const QString &hash) const
|
||||
int TorrentModel::torrentRow(const BitTorrent::InfoHash &hash) const
|
||||
{
|
||||
int row = 0;
|
||||
|
||||
QList<TorrentModelItem*>::const_iterator it = m_torrents.constBegin();
|
||||
QList<TorrentModelItem*>::const_iterator itend = m_torrents.constEnd();
|
||||
for ( ; it != itend; ++it) {
|
||||
if ((*it)->hash() == hash) return row;
|
||||
foreach (TorrentModelItem *const item, m_items) {
|
||||
if (item->hash() == hash) return row;
|
||||
++row;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void TorrentModel::addTorrent(const QTorrentHandle &h)
|
||||
void TorrentModel::addTorrent(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
if (torrentRow(h.hash()) < 0) {
|
||||
beginInsertTorrent(m_torrents.size());
|
||||
TorrentModelItem *item = new TorrentModelItem(h);
|
||||
connect(item, SIGNAL(labelChanged(QString,QString)), SLOT(handleTorrentLabelChange(QString,QString)));
|
||||
m_torrents << item;
|
||||
if (torrentRow(torrent->hash()) < 0) {
|
||||
beginInsertTorrent(m_items.size());
|
||||
TorrentModelItem *item = new TorrentModelItem(torrent);
|
||||
connect(item, SIGNAL(labelChanged(QString, QString)), SLOT(handleTorrentLabelChange(QString, QString)));
|
||||
m_items << item;
|
||||
emit torrentAdded(item);
|
||||
endInsertTorrent();
|
||||
}
|
||||
@@ -553,95 +462,9 @@ void TorrentModel::endRemoveTorrent()
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentUpdate(const QTorrentHandle &h)
|
||||
{
|
||||
const int row = torrentRow(h.hash());
|
||||
if (row >= 0) {
|
||||
// This line changes the torrent name when magnet is retrieved.
|
||||
// When magnet link is added, "dn" parameter is used as name, but when metadata is retrieved
|
||||
// we change the name with the retrieved torrent name.
|
||||
m_torrents[row]->setData(TorrentModelItem::TR_NAME, h.name(), Qt::DisplayRole);
|
||||
|
||||
m_torrents[row]->refreshStatus(h.status(torrent_handle::query_accurate_download_counters));
|
||||
notifyTorrentChanged(row);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentModel::handleFinishedTorrent(const QTorrentHandle& h)
|
||||
{
|
||||
const int row = torrentRow(h.hash());
|
||||
if (row < 0)
|
||||
return;
|
||||
|
||||
// Update completion date
|
||||
m_torrents[row]->refreshStatus(h.status(torrent_handle::query_accurate_download_counters));
|
||||
notifyTorrentChanged(row);
|
||||
}
|
||||
|
||||
void TorrentModel::notifyTorrentChanged(int row)
|
||||
{
|
||||
emit dataChanged(index(row, 0), index(row, columnCount()-1));
|
||||
}
|
||||
|
||||
void TorrentModel::setRefreshInterval(int refreshInterval)
|
||||
{
|
||||
if (m_refreshInterval != refreshInterval) {
|
||||
m_refreshInterval = refreshInterval;
|
||||
m_refreshTimer.stop();
|
||||
m_refreshTimer.start(m_refreshInterval);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentModel::forceModelRefresh()
|
||||
{
|
||||
QBtSession::instance()->postTorrentUpdate();
|
||||
}
|
||||
|
||||
TorrentStatusReport TorrentModel::getTorrentStatusReport() const
|
||||
{
|
||||
TorrentStatusReport report;
|
||||
|
||||
QList<TorrentModelItem*>::const_iterator it = m_torrents.constBegin();
|
||||
QList<TorrentModelItem*>::const_iterator itend = m_torrents.constEnd();
|
||||
for ( ; it != itend; ++it) {
|
||||
switch((*it)->state()) {
|
||||
case TorrentModelItem::STATE_DOWNLOADING:
|
||||
case TorrentModelItem::STATE_FORCED_DL:
|
||||
++report.nb_active;
|
||||
++report.nb_downloading;
|
||||
break;
|
||||
case TorrentModelItem::STATE_DOWNLOADING_META:
|
||||
++report.nb_downloading;
|
||||
break;
|
||||
case TorrentModelItem::STATE_PAUSED_DL:
|
||||
case TorrentModelItem::STATE_PAUSED_MISSING:
|
||||
++report.nb_paused;
|
||||
case TorrentModelItem::STATE_STALLED_DL:
|
||||
case TorrentModelItem::STATE_CHECKING_DL:
|
||||
case TorrentModelItem::STATE_QUEUED_DL: {
|
||||
++report.nb_inactive;
|
||||
++report.nb_downloading;
|
||||
break;
|
||||
}
|
||||
case TorrentModelItem::STATE_SEEDING:
|
||||
case TorrentModelItem::STATE_FORCED_UP:
|
||||
++report.nb_active;
|
||||
++report.nb_seeding;
|
||||
++report.nb_completed;
|
||||
break;
|
||||
case TorrentModelItem::STATE_STALLED_UP:
|
||||
case TorrentModelItem::STATE_CHECKING_UP:
|
||||
case TorrentModelItem::STATE_QUEUED_UP:
|
||||
++report.nb_seeding;
|
||||
case TorrentModelItem::STATE_PAUSED_UP:
|
||||
++report.nb_completed;
|
||||
++report.nb_inactive;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return report;
|
||||
emit dataChanged(index(row, 0), index(row, columnCount() - 1));
|
||||
}
|
||||
|
||||
Qt::ItemFlags TorrentModel::flags(const QModelIndex &index) const
|
||||
@@ -660,57 +483,34 @@ void TorrentModel::handleTorrentLabelChange(QString previous, QString current)
|
||||
QString TorrentModel::torrentHash(int row) const
|
||||
{
|
||||
if (row >= 0 && row < rowCount())
|
||||
return m_torrents.at(row)->hash();
|
||||
return m_items.at(row)->hash();
|
||||
return QString();
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentAboutToBeRemoved(const QTorrentHandle &h)
|
||||
BitTorrent::TorrentHandle *TorrentModel::torrentHandle(const QModelIndex &index) const
|
||||
{
|
||||
const int row = torrentRow(h.hash());
|
||||
if (index.isValid() && (index.row() >= 0) && (index.row() < rowCount()))
|
||||
return m_items[index.row()]->torrentHandle();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
const int row = torrentRow(torrent->hash());
|
||||
qDebug() << Q_FUNC_INFO << row;
|
||||
if (row >= 0) {
|
||||
emit torrentAboutToBeRemoved(m_torrents.at(row));
|
||||
emit torrentAboutToBeRemoved(m_items.at(row));
|
||||
|
||||
beginRemoveTorrent(row);
|
||||
delete m_torrents[row];
|
||||
m_torrents.removeAt(row);
|
||||
delete m_items.takeAt(row);
|
||||
endRemoveTorrent();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentModel::stateUpdated(const std::vector<libtorrent::torrent_status> &statuses) {
|
||||
typedef std::vector<libtorrent::torrent_status> statuses_t;
|
||||
|
||||
for (statuses_t::const_iterator i = statuses.begin(), end = statuses.end(); i != end; ++i) {
|
||||
libtorrent::torrent_status const& status = *i;
|
||||
|
||||
const int row = torrentRow(misc::toQString(status.info_hash));
|
||||
if (row >= 0) {
|
||||
m_torrents[row]->refreshStatus(status);
|
||||
notifyTorrentChanged(row);
|
||||
}
|
||||
}
|
||||
|
||||
emit modelRefreshed();
|
||||
}
|
||||
|
||||
bool TorrentModel::inhibitSystem()
|
||||
void TorrentModel::handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
QList<TorrentModelItem*>::const_iterator it = m_torrents.constBegin();
|
||||
QList<TorrentModelItem*>::const_iterator itend = m_torrents.constEnd();
|
||||
for ( ; it != itend; ++it) {
|
||||
switch((*it)->data(TorrentModelItem::TR_STATUS).toInt()) {
|
||||
case TorrentModelItem::STATE_DOWNLOADING:
|
||||
case TorrentModelItem::STATE_DOWNLOADING_META:
|
||||
case TorrentModelItem::STATE_FORCED_DL:
|
||||
case TorrentModelItem::STATE_STALLED_DL:
|
||||
case TorrentModelItem::STATE_SEEDING:
|
||||
case TorrentModelItem::STATE_FORCED_UP:
|
||||
case TorrentModelItem::STATE_STALLED_UP:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
const int row = torrentRow(torrent->hash());
|
||||
if (row >= 0)
|
||||
notifyTorrentChanged(row);
|
||||
}
|
||||
|
||||
@@ -33,53 +33,35 @@
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QList>
|
||||
#include <QDateTime>
|
||||
#include <QIcon>
|
||||
#include <QTimer>
|
||||
|
||||
#include "qtorrenthandle.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
|
||||
struct TorrentStatusReport {
|
||||
TorrentStatusReport();
|
||||
uint nb_downloading;
|
||||
uint nb_seeding;
|
||||
uint nb_completed;
|
||||
uint nb_active;
|
||||
uint nb_inactive;
|
||||
uint nb_paused;
|
||||
};
|
||||
class QIcon;
|
||||
|
||||
class TorrentModelItem : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum State {STATE_DOWNLOADING, STATE_DOWNLOADING_META, STATE_ALLOCATING, STATE_STALLED_DL, STATE_SEEDING, STATE_STALLED_UP, STATE_QUEUED_DL, STATE_QUEUED_UP, STATE_CHECKING_UP, STATE_CHECKING_DL, STATE_QUEUED_CHECK, STATE_QUEUED_FASTCHECK, STATE_PAUSED_DL, STATE_PAUSED_UP, STATE_PAUSED_MISSING, STATE_FORCED_DL, STATE_FORCED_UP, STATE_INVALID};
|
||||
enum Column {TR_NAME, TR_PRIORITY, TR_SIZE, TR_TOTAL_SIZE, TR_PROGRESS, TR_STATUS, TR_SEEDS, TR_PEERS, TR_DLSPEED, TR_UPSPEED, TR_ETA, TR_RATIO, TR_LABEL, TR_ADD_DATE, TR_SEED_DATE, TR_TRACKER, TR_DLLIMIT, TR_UPLIMIT, TR_AMOUNT_DOWNLOADED, TR_AMOUNT_UPLOADED, TR_AMOUNT_LEFT, TR_TIME_ELAPSED, TR_SAVE_PATH, TR_COMPLETED, TR_RATIO_LIMIT, TR_SEEN_COMPLETE_DATE, TR_LAST_ACTIVITY, TR_AMOUNT_DOWNLOADED_SESSION, TR_AMOUNT_UPLOADED_SESSION, NB_COLUMNS};
|
||||
|
||||
public:
|
||||
TorrentModelItem(const QTorrentHandle& h);
|
||||
void refreshStatus(libtorrent::torrent_status const& status);
|
||||
TorrentModelItem(BitTorrent::TorrentHandle *torrent);
|
||||
inline int columnCount() const { return NB_COLUMNS; }
|
||||
QVariant data(int column, int role = Qt::DisplayRole) const;
|
||||
bool setData(int column, const QVariant &value, int role = Qt::DisplayRole);
|
||||
inline QString const& hash() const { return m_hash; }
|
||||
State state() const;
|
||||
QTorrentHandle torrentHandle() const;
|
||||
inline BitTorrent::InfoHash hash() const { return m_torrent->hash(); }
|
||||
BitTorrent::TorrentState state() const;
|
||||
BitTorrent::TorrentHandle *torrentHandle() const;
|
||||
|
||||
signals:
|
||||
void labelChanged(QString previous, QString current);
|
||||
|
||||
private:
|
||||
static QIcon getIconByState(State state);
|
||||
static QColor getColorByState(State state);
|
||||
static QIcon getIconByState(BitTorrent::TorrentState state);
|
||||
static QColor getColorByState(BitTorrent::TorrentState state);
|
||||
|
||||
private:
|
||||
QTorrentHandle m_torrent;
|
||||
libtorrent::torrent_status m_lastStatus;
|
||||
QDateTime m_addedTime;
|
||||
QString m_label;
|
||||
QString m_name;
|
||||
QString m_hash; // Cached for safety reasons
|
||||
BitTorrent::TorrentHandle *m_torrent;
|
||||
};
|
||||
|
||||
class TorrentModel : public QAbstractListModel
|
||||
@@ -90,34 +72,28 @@ class TorrentModel : public QAbstractListModel
|
||||
public:
|
||||
explicit TorrentModel(QObject *parent = 0);
|
||||
~TorrentModel();
|
||||
inline int rowCount(const QModelIndex& index = QModelIndex()) const { Q_UNUSED(index); return m_torrents.size(); }
|
||||
inline int rowCount(const QModelIndex& index = QModelIndex()) const { Q_UNUSED(index); return m_items.size(); }
|
||||
int columnCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return TorrentModelItem::NB_COLUMNS; }
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
int torrentRow(const QString &hash) const;
|
||||
int torrentRow(const BitTorrent::InfoHash &hash) const;
|
||||
QString torrentHash(int row) const;
|
||||
void setRefreshInterval(int refreshInterval);
|
||||
TorrentStatusReport getTorrentStatusReport() const;
|
||||
BitTorrent::TorrentHandle *torrentHandle(const QModelIndex &index) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
void populate();
|
||||
bool inhibitSystem();
|
||||
|
||||
signals:
|
||||
void torrentAdded(TorrentModelItem *torrentItem);
|
||||
void torrentAboutToBeRemoved(TorrentModelItem *torrentItem);
|
||||
void torrentChangedLabel(TorrentModelItem *torrentItem, QString previous, QString current);
|
||||
void modelRefreshed();
|
||||
|
||||
private slots:
|
||||
void addTorrent(const QTorrentHandle& h);
|
||||
void handleTorrentUpdate(const QTorrentHandle &h);
|
||||
void handleFinishedTorrent(const QTorrentHandle& h);
|
||||
void addTorrent(BitTorrent::TorrentHandle *const torrent);
|
||||
void notifyTorrentChanged(int row);
|
||||
void forceModelRefresh();
|
||||
void handleTorrentLabelChange(QString previous, QString current);
|
||||
void handleTorrentAboutToBeRemoved(const QTorrentHandle & h);
|
||||
void stateUpdated(const std::vector<libtorrent::torrent_status> &statuses);
|
||||
void handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
|
||||
void handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent);
|
||||
|
||||
private:
|
||||
void beginInsertTorrent(int row);
|
||||
@@ -126,9 +102,7 @@ private:
|
||||
void endRemoveTorrent();
|
||||
|
||||
private:
|
||||
QList<TorrentModelItem*> m_torrents;
|
||||
int m_refreshInterval;
|
||||
QTimer m_refreshTimer;
|
||||
QList<TorrentModelItem*> m_items;
|
||||
};
|
||||
|
||||
#endif // TORRENTMODEL_H
|
||||
|
||||
@@ -28,17 +28,18 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "trackerlogin.h"
|
||||
|
||||
trackerLogin::trackerLogin(QWidget *parent, QTorrentHandle h)
|
||||
trackerLogin::trackerLogin(QWidget *parent, BitTorrent::TorrentHandle *const torrent)
|
||||
: QDialog(parent)
|
||||
, h(h)
|
||||
, m_torrent(torrent)
|
||||
{
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
login_logo->setPixmap(QPixmap(QString::fromUtf8(":/icons/oxygen/encrypted.png")));
|
||||
tracker_url->setText(h.current_tracker());
|
||||
connect(this, SIGNAL(trackerLoginCancelled(QPair<QTorrentHandle,QString>)), parent, SLOT(addUnauthenticatedTracker(QPair<QTorrentHandle,QString>)));
|
||||
tracker_url->setText(torrent->currentTracker());
|
||||
connect(this, SIGNAL(trackerLoginCancelled(QPair<BitTorrent::TorrentHandle *const, QString>)), parent, SLOT(addUnauthenticatedTracker(QPair<BitTorrent::TorrentHandle *const, QString>)));
|
||||
show();
|
||||
}
|
||||
|
||||
@@ -46,12 +47,12 @@ trackerLogin::~trackerLogin() {}
|
||||
|
||||
void trackerLogin::on_loginButton_clicked() {
|
||||
// login
|
||||
h.set_tracker_login(lineUsername->text(), linePasswd->text());
|
||||
m_torrent->setTrackerLogin(lineUsername->text(), linePasswd->text());
|
||||
close();
|
||||
}
|
||||
|
||||
void trackerLogin::on_cancelButton_clicked() {
|
||||
// Emit a signal to GUI to stop asking for authentication
|
||||
emit trackerLoginCancelled(QPair<QTorrentHandle,QString>(h, h.current_tracker()));
|
||||
emit trackerLoginCancelled(QPair<BitTorrent::TorrentHandle *const, QString>(m_torrent, m_torrent->currentTracker()));
|
||||
close();
|
||||
}
|
||||
|
||||
@@ -34,20 +34,24 @@
|
||||
#include <QDialog>
|
||||
|
||||
#include "ui_login.h"
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentHandle;
|
||||
}
|
||||
|
||||
class trackerLogin : public QDialog, private Ui::authentication{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QTorrentHandle h;
|
||||
BitTorrent::TorrentHandle *const m_torrent;
|
||||
|
||||
public:
|
||||
trackerLogin(QWidget *parent, QTorrentHandle h);
|
||||
trackerLogin(QWidget *parent, BitTorrent::TorrentHandle *const torrent);
|
||||
~trackerLogin();
|
||||
|
||||
signals:
|
||||
void trackerLoginCancelled(QPair<QTorrentHandle,QString> tracker);
|
||||
void trackerLoginCancelled(QPair<BitTorrent::TorrentHandle *const, QString> tracker);
|
||||
|
||||
public slots:
|
||||
void on_loginButton_clicked();
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
#include <QPainter>
|
||||
#include "core/misc.h"
|
||||
#include "torrentmodel.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
@@ -90,49 +91,43 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
||||
const int state = index.data().toInt();
|
||||
QString display;
|
||||
switch(state) {
|
||||
case TorrentModelItem::STATE_DOWNLOADING:
|
||||
case BitTorrent::TorrentState::Downloading:
|
||||
display = tr("Downloading");
|
||||
break;
|
||||
case TorrentModelItem::STATE_DOWNLOADING_META:
|
||||
display = tr("Downloading metadata", "used when loading a magnet link");
|
||||
break;
|
||||
case TorrentModelItem::STATE_FORCED_DL:
|
||||
display = tr("[F] Downloading", "used when the torrent is forced started. You probably shouldn't translate the F.");
|
||||
break;
|
||||
case TorrentModelItem::STATE_ALLOCATING:
|
||||
display = tr("Allocating", "qBittorrent is allocating the files on disk");
|
||||
break;
|
||||
case TorrentModelItem::STATE_STALLED_DL:
|
||||
case BitTorrent::TorrentState::StalledDownloading:
|
||||
display = tr("Stalled", "Torrent is waiting for download to begin");
|
||||
break;
|
||||
case TorrentModelItem::STATE_SEEDING:
|
||||
case TorrentModelItem::STATE_STALLED_UP:
|
||||
case BitTorrent::TorrentState::DownloadingMetadata:
|
||||
display = tr("Downloading metadata", "used when loading a magnet link");
|
||||
break;
|
||||
case BitTorrent::TorrentState::ForcedDownloading:
|
||||
display = tr("[F] Downloading", "used when the torrent is forced started. You probably shouldn't translate the F.");
|
||||
break;
|
||||
case BitTorrent::TorrentState::Allocating:
|
||||
display = tr("Allocating", "qBittorrent is allocating the files on disk");
|
||||
break;
|
||||
case BitTorrent::TorrentState::Uploading:
|
||||
case BitTorrent::TorrentState::StalledUploading:
|
||||
display = tr("Seeding", "Torrent is complete and in upload-only mode");
|
||||
break;
|
||||
case TorrentModelItem::STATE_FORCED_UP:
|
||||
case BitTorrent::TorrentState::ForcedUploading:
|
||||
display = tr("[F] Seeding", "used when the torrent is forced started. You probably shouldn't translate the F.");
|
||||
break;
|
||||
case TorrentModelItem::STATE_QUEUED_DL:
|
||||
case TorrentModelItem::STATE_QUEUED_UP:
|
||||
case BitTorrent::TorrentState::QueuedDownloading:
|
||||
case BitTorrent::TorrentState::QueuedUploading:
|
||||
display = tr("Queued", "i.e. torrent is queued");
|
||||
break;
|
||||
case TorrentModelItem::STATE_CHECKING_DL:
|
||||
case TorrentModelItem::STATE_CHECKING_UP:
|
||||
case BitTorrent::TorrentState::CheckingDownloading:
|
||||
case BitTorrent::TorrentState::CheckingUploading:
|
||||
display = tr("Checking", "Torrent local data is being checked");
|
||||
break;
|
||||
case TorrentModelItem::STATE_QUEUED_CHECK:
|
||||
display = tr("Queued for checking", "i.e. torrent is queued for hash checking");
|
||||
break;
|
||||
case TorrentModelItem::STATE_QUEUED_FASTCHECK:
|
||||
display = tr("Checking resume data", "used when loading the torrents from disk after qbt is launched. It checks the correctness of the .fastresume file. Normally it is completed in a fraction of a second, unless loading many many torrents.");
|
||||
break;
|
||||
case TorrentModelItem::STATE_PAUSED_DL:
|
||||
case BitTorrent::TorrentState::PausedDownloading:
|
||||
display = tr("Paused");
|
||||
break;
|
||||
case TorrentModelItem::STATE_PAUSED_UP:
|
||||
case BitTorrent::TorrentState::PausedUploading:
|
||||
display = tr("Completed");
|
||||
break;
|
||||
case TorrentModelItem::STATE_PAUSED_MISSING:
|
||||
case BitTorrent::TorrentState::Error:
|
||||
display = tr("Missing Files");
|
||||
break;
|
||||
default:
|
||||
@@ -178,13 +173,13 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||
const qreal ratio = index.data().toDouble();
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect,
|
||||
(ratio == -1 || ratio > QBtSession::MAX_RATIO) ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 2));
|
||||
((ratio == -1) || (ratio > BitTorrent::TorrentHandle::MAX_RATIO)) ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 2));
|
||||
break;
|
||||
}
|
||||
case TorrentModelItem::TR_PRIORITY: {
|
||||
const int priority = index.data().toInt();
|
||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||
if (priority >= 0)
|
||||
if (priority > 0)
|
||||
QItemDelegate::paint(painter, opt, index);
|
||||
else {
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
|
||||
@@ -43,12 +43,15 @@
|
||||
#include "transferlistwidget.h"
|
||||
#include "core/preferences.h"
|
||||
#include "torrentmodel.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "torrentfilterenum.h"
|
||||
#include "core/torrentfilter.h"
|
||||
#include "core/bittorrent/trackerentry.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "core/net/downloadhandler.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/downloadthread.h"
|
||||
#include "core/logger.h"
|
||||
|
||||
FiltersBase::FiltersBase(QWidget *parent, TransferListWidget *transferList)
|
||||
@@ -104,7 +107,7 @@ StatusFiltersWidget::StatusFiltersWidget(QWidget *parent, TransferListWidget *tr
|
||||
// Height is fixed (sizeHint().height() is used)
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
setSpacing(0);
|
||||
connect(transferList->getSourceModel(), SIGNAL(modelRefreshed()), SLOT(updateTorrentNumbers()));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentsUpdated(const BitTorrent::TorrentStatusReport &)), SLOT(updateTorrentNumbers(const BitTorrent::TorrentStatusReport &)));
|
||||
|
||||
// Add status filters
|
||||
QListWidgetItem *all = new QListWidgetItem(this);
|
||||
@@ -142,17 +145,16 @@ StatusFiltersWidget::~StatusFiltersWidget()
|
||||
Preferences::instance()->setTransSelFilter(currentRow());
|
||||
}
|
||||
|
||||
void StatusFiltersWidget::updateTorrentNumbers()
|
||||
void StatusFiltersWidget::updateTorrentNumbers(const BitTorrent::TorrentStatusReport &report)
|
||||
{
|
||||
const TorrentStatusReport report = transferList->getSourceModel()->getTorrentStatusReport();
|
||||
item(TorrentFilter::ALL)->setData(Qt::DisplayRole, QVariant(tr("All (%1)").arg(report.nb_active + report.nb_inactive)));
|
||||
item(TorrentFilter::DOWNLOADING)->setData(Qt::DisplayRole, QVariant(tr("Downloading (%1)").arg(report.nb_downloading)));
|
||||
item(TorrentFilter::SEEDING)->setData(Qt::DisplayRole, QVariant(tr("Seeding (%1)").arg(report.nb_seeding)));
|
||||
item(TorrentFilter::COMPLETED)->setData(Qt::DisplayRole, QVariant(tr("Completed (%1)").arg(report.nb_completed)));
|
||||
item(TorrentFilter::PAUSED)->setData(Qt::DisplayRole, QVariant(tr("Paused (%1)").arg(report.nb_paused)));
|
||||
item(TorrentFilter::RESUMED)->setData(Qt::DisplayRole, QVariant(tr("Resumed (%1)").arg(report.nb_downloading + report.nb_seeding - report.nb_paused)));
|
||||
item(TorrentFilter::ACTIVE)->setData(Qt::DisplayRole, QVariant(tr("Active (%1)").arg(report.nb_active)));
|
||||
item(TorrentFilter::INACTIVE)->setData(Qt::DisplayRole, QVariant(tr("Inactive (%1)").arg(report.nb_inactive)));
|
||||
item(TorrentFilter::All)->setData(Qt::DisplayRole, QVariant(tr("All (%1)").arg(report.nbActive + report.nbInactive)));
|
||||
item(TorrentFilter::Downloading)->setData(Qt::DisplayRole, QVariant(tr("Downloading (%1)").arg(report.nbDownloading)));
|
||||
item(TorrentFilter::Seeding)->setData(Qt::DisplayRole, QVariant(tr("Seeding (%1)").arg(report.nbSeeding)));
|
||||
item(TorrentFilter::Completed)->setData(Qt::DisplayRole, QVariant(tr("Completed (%1)").arg(report.nbCompleted)));
|
||||
item(TorrentFilter::Paused)->setData(Qt::DisplayRole, QVariant(tr("Paused (%1)").arg(report.nbPaused)));
|
||||
item(TorrentFilter::Resumed)->setData(Qt::DisplayRole, QVariant(tr("Resumed (%1)").arg(report.nbResumed)));
|
||||
item(TorrentFilter::Active)->setData(Qt::DisplayRole, QVariant(tr("Active (%1)").arg(report.nbActive)));
|
||||
item(TorrentFilter::Inactive)->setData(Qt::DisplayRole, QVariant(tr("Inactive (%1)").arg(report.nbInactive)));
|
||||
}
|
||||
|
||||
void StatusFiltersWidget::showMenu(QPoint) {}
|
||||
@@ -177,10 +179,10 @@ LabelFiltersList::LabelFiltersList(QWidget *parent, TransferListWidget *transfer
|
||||
// Add Label filters
|
||||
QListWidgetItem *allLabels = new QListWidgetItem(this);
|
||||
allLabels->setData(Qt::DisplayRole, QVariant(tr("All (0)", "this is for the label filter")));
|
||||
allLabels->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory"));
|
||||
allLabels->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("inode-directory"));
|
||||
QListWidgetItem *noLabel = new QListWidgetItem(this);
|
||||
noLabel->setData(Qt::DisplayRole, QVariant(tr("Unlabeled (0)")));
|
||||
noLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory"));
|
||||
noLabel->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("inode-directory"));
|
||||
|
||||
const Preferences* const pref = Preferences::instance();
|
||||
QStringList labelList = pref->getTorrentLabels();
|
||||
@@ -215,7 +217,7 @@ void LabelFiltersList::addItem(QString &label, bool hasTorrent)
|
||||
}
|
||||
else {
|
||||
labelItem = new QListWidgetItem();
|
||||
labelItem->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory"));
|
||||
labelItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("inode-directory"));
|
||||
}
|
||||
|
||||
if (hasTorrent) {
|
||||
@@ -269,9 +271,12 @@ void LabelFiltersList::removeItem(const QString &label)
|
||||
|
||||
void LabelFiltersList::removeSelectedLabel()
|
||||
{
|
||||
const int labelRow = row(selectedItems().first());
|
||||
if (labelRow < 2)
|
||||
return;
|
||||
QList<QListWidgetItem*> items = selectedItems();
|
||||
if (items.size() == 0) return;
|
||||
|
||||
const int labelRow = row(items.first());
|
||||
if (labelRow < 2) return;
|
||||
|
||||
const QString &label = labelFromRow(labelRow);
|
||||
Q_ASSERT(m_labels.contains(label));
|
||||
m_labels.remove(label);
|
||||
@@ -314,16 +319,16 @@ void LabelFiltersList::torrentChangedLabel(TorrentModelItem *torrentItem, QStrin
|
||||
void LabelFiltersList::showMenu(QPoint)
|
||||
{
|
||||
QMenu menu(this);
|
||||
QAction *addAct = menu.addAction(IconProvider::instance()->getIcon("list-add"), tr("Add label..."));
|
||||
QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add label..."));
|
||||
QAction *removeAct = 0;
|
||||
QAction *removeUnusedAct = 0;
|
||||
if (!selectedItems().empty() && row(selectedItems().first()) > 1)
|
||||
removeAct = menu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove label"));
|
||||
removeUnusedAct = menu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove unused labels"));
|
||||
removeAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove label"));
|
||||
removeUnusedAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove unused labels"));
|
||||
menu.addSeparator();
|
||||
QAction *startAct = menu.addAction(IconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents"));
|
||||
QAction *pauseAct = menu.addAction(IconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
|
||||
QAction *deleteTorrentsAct = menu.addAction(IconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
|
||||
QAction *startAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents"));
|
||||
QAction *pauseAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
|
||||
QAction *deleteTorrentsAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
|
||||
QAction *act = 0;
|
||||
act = menu.exec(QCursor::pos());
|
||||
if (!act)
|
||||
@@ -415,17 +420,16 @@ int LabelFiltersList::rowFromLabel(const QString &label) const
|
||||
|
||||
TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *transferList)
|
||||
: FiltersBase(parent, transferList)
|
||||
, m_downloader(new DownloadThread(this))
|
||||
, m_totalTorrents(0)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
|
||||
QListWidgetItem *allTrackers = new QListWidgetItem(this);
|
||||
allTrackers->setData(Qt::DisplayRole, QVariant(tr("All (0)", "this is for the label filter")));
|
||||
allTrackers->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("network-server"));
|
||||
allTrackers->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server"));
|
||||
QListWidgetItem *noTracker = new QListWidgetItem(this);
|
||||
noTracker->setData(Qt::DisplayRole, QVariant(tr("Trackerless (0)")));
|
||||
noTracker->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("network-server"));
|
||||
noTracker->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server"));
|
||||
QListWidgetItem *errorTracker = new QListWidgetItem(this);
|
||||
errorTracker->setData(Qt::DisplayRole, QVariant(tr("Error (0)")));
|
||||
errorTracker->setData(Qt::DecorationRole, style()->standardIcon(QStyle::SP_MessageBoxCritical));
|
||||
@@ -435,14 +439,11 @@ TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *tran
|
||||
m_trackers.insert("", QStringList());
|
||||
|
||||
setCurrentRow(0, QItemSelectionModel::SelectCurrent);
|
||||
connect(m_downloader, SIGNAL(downloadFinished(QString, QString)), SLOT(handleFavicoDownload(QString, QString)));
|
||||
connect(m_downloader, SIGNAL(downloadFailure(QString, QString)), SLOT(handleFavicoFailure(QString, QString)));
|
||||
toggleFilter(Preferences::instance()->getTrackerFilterState());
|
||||
}
|
||||
|
||||
TrackerFiltersList::~TrackerFiltersList()
|
||||
{
|
||||
delete m_downloader;
|
||||
foreach (const QString &iconPath, m_iconPaths)
|
||||
fsutils::forceRemove(iconPath);
|
||||
}
|
||||
@@ -466,8 +467,11 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
|
||||
}
|
||||
else {
|
||||
trackerItem = new QListWidgetItem();
|
||||
trackerItem->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("network-server"));
|
||||
m_downloader->downloadUrl(QString("http://") + host + QString("/favicon.ico"));
|
||||
trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server"));
|
||||
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host));
|
||||
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
|
||||
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
|
||||
}
|
||||
|
||||
tmp.append(hash);
|
||||
@@ -611,18 +615,20 @@ void TrackerFiltersList::trackerWarning(const QString &hash, const QString &trac
|
||||
void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString& filePath)
|
||||
{
|
||||
QString host = getHost(url);
|
||||
if (!m_trackers.contains(host))
|
||||
return;
|
||||
if (!m_trackers.contains(host)) return;
|
||||
|
||||
QListWidgetItem *trackerItem = item(rowFromTracker(host));
|
||||
QIcon icon(filePath);
|
||||
//Detect a non-decodable icon
|
||||
bool invalid = icon.pixmap(icon.availableSizes().first()).isNull();
|
||||
QList<QSize> sizes = icon.availableSizes();
|
||||
bool invalid = (sizes.size() > 0 ? icon.pixmap(sizes.first()).isNull() : true);
|
||||
if (invalid) {
|
||||
if (url.endsWith(".ico", Qt::CaseInsensitive)) {
|
||||
Logger::instance()->addMessage(tr("Couldn't decode favico for url `%1`. Trying to download favico in PNG format.").arg(url),
|
||||
Log::WARNING);
|
||||
m_downloader->downloadUrl(url.left(url.size() - 4) + ".png");
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png");
|
||||
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
|
||||
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
|
||||
}
|
||||
else {
|
||||
Logger::instance()->addMessage(tr("Couldn't decode favico for url `%1`.").arg(url), Log::WARNING);
|
||||
@@ -646,9 +652,9 @@ void TrackerFiltersList::handleFavicoFailure(const QString& url, const QString&
|
||||
void TrackerFiltersList::showMenu(QPoint)
|
||||
{
|
||||
QMenu menu(this);
|
||||
QAction *startAct = menu.addAction(IconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents"));
|
||||
QAction *pauseAct = menu.addAction(IconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
|
||||
QAction *deleteTorrentsAct = menu.addAction(IconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
|
||||
QAction *startAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents"));
|
||||
QAction *pauseAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
|
||||
QAction *deleteTorrentsAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
|
||||
QAction *act = 0;
|
||||
act = menu.exec(QCursor::pos());
|
||||
|
||||
@@ -673,11 +679,11 @@ void TrackerFiltersList::applyFilter(int row)
|
||||
|
||||
void TrackerFiltersList::handleNewTorrent(TorrentModelItem* torrentItem)
|
||||
{
|
||||
QTorrentHandle handle = torrentItem->torrentHandle();
|
||||
QString hash = handle.hash();
|
||||
std::vector<libtorrent::announce_entry> trackers = handle.trackers();
|
||||
for (std::vector<libtorrent::announce_entry>::iterator i = trackers.begin(), e = trackers.end(); i != e; ++i)
|
||||
addItem(misc::toQStringU(i->url), hash);
|
||||
BitTorrent::TorrentHandle *const handle = torrentItem->torrentHandle();
|
||||
QString hash = handle->hash();
|
||||
QList<BitTorrent::TrackerEntry> trackers = handle->trackers();
|
||||
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
||||
addItem(tracker.url(), hash);
|
||||
|
||||
//Check for trackerless torrent
|
||||
if (trackers.size() == 0)
|
||||
@@ -688,11 +694,11 @@ void TrackerFiltersList::handleNewTorrent(TorrentModelItem* torrentItem)
|
||||
|
||||
void TrackerFiltersList::torrentAboutToBeDeleted(TorrentModelItem* torrentItem)
|
||||
{
|
||||
QTorrentHandle handle = torrentItem->torrentHandle();
|
||||
QString hash = handle.hash();
|
||||
std::vector<libtorrent::announce_entry> trackers = handle.trackers();
|
||||
for (std::vector<libtorrent::announce_entry>::iterator i = trackers.begin(), e = trackers.end(); i != e; ++i)
|
||||
removeItem(misc::toQStringU(i->url), hash);
|
||||
BitTorrent::TorrentHandle *const handle = torrentItem->torrentHandle();
|
||||
QString hash = handle->hash();
|
||||
QList<BitTorrent::TrackerEntry> trackers = handle->trackers();
|
||||
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
||||
removeItem(tracker.url(), hash);
|
||||
|
||||
//Check for trackerless torrent
|
||||
if (trackers.size() == 0)
|
||||
@@ -817,19 +823,34 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
|
||||
connect(this, SIGNAL(trackerWarning(const QString &, const QString &)), trackerFilters, SLOT(trackerWarning(const QString &, const QString &)));
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::addTrackers(const QStringList &trackers, const QString &hash)
|
||||
void TransferListFiltersWidget::addTrackers(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers)
|
||||
{
|
||||
foreach (const QString &tracker, trackers)
|
||||
trackerFilters->addItem(tracker, hash);
|
||||
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
||||
trackerFilters->addItem(tracker.url(), torrent->hash());
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::removeTrackers(const QStringList &trackers, const QString &hash)
|
||||
void TransferListFiltersWidget::removeTrackers(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers)
|
||||
{
|
||||
foreach (const QString &tracker, trackers)
|
||||
trackerFilters->removeItem(tracker, hash);
|
||||
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
||||
trackerFilters->removeItem(tracker.url(), torrent->hash());
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::changeTrackerless(bool trackerless, const QString &hash)
|
||||
void TransferListFiltersWidget::changeTrackerless(BitTorrent::TorrentHandle *const torrent, bool trackerless)
|
||||
{
|
||||
trackerFilters->changeTrackerless(trackerless, hash);
|
||||
trackerFilters->changeTrackerless(trackerless, torrent->hash());
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker)
|
||||
{
|
||||
emit trackerSuccess(torrent->hash(), tracker);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker)
|
||||
{
|
||||
emit trackerWarning(torrent->hash(), tracker);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker)
|
||||
{
|
||||
emit trackerError(torrent->hash(), tracker);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,13 @@ QT_END_NAMESPACE
|
||||
|
||||
class TransferListWidget;
|
||||
class TorrentModelItem;
|
||||
class QTorrentHandle;
|
||||
class DownloadThread;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentHandle;
|
||||
class TrackerEntry;
|
||||
struct TorrentStatusReport;
|
||||
}
|
||||
|
||||
class FiltersBase: public QListWidget
|
||||
{
|
||||
@@ -76,7 +81,7 @@ public:
|
||||
~StatusFiltersWidget();
|
||||
|
||||
private slots:
|
||||
void updateTorrentNumbers();
|
||||
void updateTorrentNumbers(const BitTorrent::TorrentStatusReport &report);
|
||||
|
||||
private:
|
||||
// These 4 methods are virtual slots in the base class.
|
||||
@@ -158,7 +163,6 @@ private:
|
||||
QHash<QString, QStringList> m_trackers;
|
||||
QHash<QString, QStringList> m_errors;
|
||||
QHash<QString, QStringList> m_warnings;
|
||||
DownloadThread *m_downloader;
|
||||
QStringList m_iconPaths;
|
||||
int m_totalTorrents;
|
||||
};
|
||||
@@ -171,9 +175,12 @@ public:
|
||||
TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList);
|
||||
|
||||
public slots:
|
||||
void addTrackers(const QStringList &trackers, const QString &hash);
|
||||
void removeTrackers(const QStringList &trackers, const QString &hash);
|
||||
void changeTrackerless(bool trackerless, const QString &hash);
|
||||
void addTrackers(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
||||
void removeTrackers(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
||||
void changeTrackerless(BitTorrent::TorrentHandle *const torrent, bool trackerless);
|
||||
void trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker);
|
||||
void trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker);
|
||||
void trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker);
|
||||
|
||||
signals:
|
||||
void trackerSuccess(const QString &hash, const QString &tracker);
|
||||
|
||||
@@ -28,61 +28,46 @@
|
||||
* Contact : daymansmail@gmail.com
|
||||
*/
|
||||
|
||||
#include "transferlistsortmodel.h"
|
||||
#include <QStringList>
|
||||
|
||||
#include "torrentmodel.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "torrentmodel.h"
|
||||
#include "transferlistsortmodel.h"
|
||||
|
||||
TransferListSortModel::TransferListSortModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, filter0(TorrentFilter::ALL)
|
||||
, labelFilterEnabled(false)
|
||||
, trackerFilterEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
void TransferListSortModel::setStatusFilter(const TorrentFilter::TorrentFilter &filter)
|
||||
void TransferListSortModel::setStatusFilter(TorrentFilter::Type filter)
|
||||
{
|
||||
if (filter != filter0) {
|
||||
filter0 = filter;
|
||||
if (m_filter.setType(filter))
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::setLabelFilter(const QString &label)
|
||||
{
|
||||
if (!labelFilterEnabled || labelFilter != label) {
|
||||
labelFilterEnabled = true;
|
||||
labelFilter = label;
|
||||
if (m_filter.setLabel(label))
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::disableLabelFilter()
|
||||
{
|
||||
if (labelFilterEnabled) {
|
||||
labelFilterEnabled = false;
|
||||
labelFilter = QString();
|
||||
if (m_filter.setLabel(TorrentFilter::AnyLabel))
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::setTrackerFilter(const QStringList &hashes)
|
||||
{
|
||||
if (!trackerFilterEnabled || trackerFilter != hashes) {
|
||||
trackerFilterEnabled = true;
|
||||
trackerFilter = hashes;
|
||||
if (m_filter.setHashSet(hashes.toSet()))
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::disableTrackerFilter()
|
||||
{
|
||||
if (trackerFilterEnabled) {
|
||||
trackerFilterEnabled = false;
|
||||
trackerFilter = QStringList();
|
||||
if (m_filter.setHashSet(TorrentFilter::AnyHash))
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
@@ -92,12 +77,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
if (column == TorrentModelItem::TR_NAME) {
|
||||
QVariant vL = left.data();
|
||||
QVariant vR = right.data();
|
||||
if (!(vL.isValid() && vR.isValid()))
|
||||
return lowerPositionThan(left, right);
|
||||
Q_ASSERT(vL.isValid());
|
||||
Q_ASSERT(vR.isValid());
|
||||
|
||||
if (vL == vR)
|
||||
if (!vL.isValid() || !vR.isValid() || (vL == vR))
|
||||
return lowerPositionThan(left, right);
|
||||
|
||||
bool res = false;
|
||||
@@ -136,7 +116,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
}
|
||||
}
|
||||
else if (column == TorrentModelItem::TR_ETA) {
|
||||
const QAbstractItemModel *model = sourceModel();
|
||||
TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel());
|
||||
const int prioL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
|
||||
const int prioR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
|
||||
const qlonglong etaL = left.data().toLongLong();
|
||||
@@ -146,36 +126,9 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
const bool invalidR = (etaR < 0 || etaR >= MAX_ETA);
|
||||
const bool seedingL = (prioL < 0);
|
||||
const bool seedingR = (prioR < 0);
|
||||
bool activeL;
|
||||
bool activeR;
|
||||
|
||||
switch (model->data(model->index(left.row(), TorrentModelItem::TR_STATUS)).toInt()) {
|
||||
case TorrentModelItem::STATE_DOWNLOADING:
|
||||
case TorrentModelItem::STATE_DOWNLOADING_META:
|
||||
case TorrentModelItem::STATE_FORCED_DL:
|
||||
case TorrentModelItem::STATE_STALLED_DL:
|
||||
case TorrentModelItem::STATE_SEEDING:
|
||||
case TorrentModelItem::STATE_FORCED_UP:
|
||||
case TorrentModelItem::STATE_STALLED_UP:
|
||||
activeL = true;
|
||||
break;
|
||||
default:
|
||||
activeL = false;
|
||||
}
|
||||
|
||||
switch (model->data(model->index(right.row(), TorrentModelItem::TR_STATUS)).toInt()) {
|
||||
case TorrentModelItem::STATE_DOWNLOADING:
|
||||
case TorrentModelItem::STATE_DOWNLOADING_META:
|
||||
case TorrentModelItem::STATE_FORCED_DL:
|
||||
case TorrentModelItem::STATE_STALLED_DL:
|
||||
case TorrentModelItem::STATE_SEEDING:
|
||||
case TorrentModelItem::STATE_FORCED_UP:
|
||||
case TorrentModelItem::STATE_STALLED_UP:
|
||||
activeR = true;
|
||||
break;
|
||||
default:
|
||||
activeR = false;
|
||||
}
|
||||
bool activeR = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(right.row())));
|
||||
bool activeL = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(right.row())));
|
||||
|
||||
// Sorting rules prioritized.
|
||||
// 1. Active torrents at the top
|
||||
@@ -189,7 +142,6 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
}
|
||||
|
||||
if (invalidL && invalidR) {
|
||||
|
||||
if (seedingL) { //Both seeding
|
||||
QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
|
||||
QDateTime dateR = model->data(model->index(right.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
|
||||
@@ -204,7 +156,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
return prioL < prioR;
|
||||
}
|
||||
}
|
||||
else if ((invalidL == false) && (invalidR == false)) {
|
||||
else if (!invalidL && !invalidR) {
|
||||
return lowerPositionThan(left, right);
|
||||
}
|
||||
else {
|
||||
@@ -243,14 +195,8 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
|
||||
// Sort according to TR_PRIORITY
|
||||
const int queueL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
|
||||
const int queueR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
|
||||
if (!(queueL < 0 && queueR < 0)) {
|
||||
if (queueL > 0 && queueR > 0)
|
||||
return queueL < queueR;
|
||||
else if (queueL < 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
if ((queueL > 0) || (queueR > 0))
|
||||
return queueL < queueR;
|
||||
|
||||
// Sort according to TR_SEED_DATE
|
||||
const QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
|
||||
@@ -272,88 +218,17 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
|
||||
|
||||
bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
return matchStatusFilter(sourceRow, sourceParent)
|
||||
&& matchLabelFilter(sourceRow, sourceParent)
|
||||
&& matchTrackerFilter(sourceRow, sourceParent)
|
||||
&& QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
return matchFilter(sourceRow, sourceParent)
|
||||
&& QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
}
|
||||
|
||||
bool TransferListSortModel::matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const
|
||||
bool TransferListSortModel::matchFilter(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (filter0 == TorrentFilter::ALL)
|
||||
return true;
|
||||
QAbstractItemModel *model = sourceModel();
|
||||
if (!model) return false;
|
||||
QModelIndex index = model->index(sourceRow, TorrentModelItem::TR_STATUS, sourceParent);
|
||||
TorrentModelItem::State state = (TorrentModelItem::State)index.data().toInt();
|
||||
|
||||
switch (filter0) {
|
||||
case TorrentFilter::DOWNLOADING:
|
||||
return (state == TorrentModelItem::STATE_DOWNLOADING || state == TorrentModelItem::STATE_STALLED_DL
|
||||
|| state == TorrentModelItem::STATE_PAUSED_DL || state == TorrentModelItem::STATE_CHECKING_DL
|
||||
|| state == TorrentModelItem::STATE_QUEUED_DL || state == TorrentModelItem::STATE_DOWNLOADING_META
|
||||
|| state == TorrentModelItem::STATE_PAUSED_MISSING || state == TorrentModelItem::STATE_FORCED_DL);
|
||||
|
||||
case TorrentFilter::SEEDING:
|
||||
return (state == TorrentModelItem::STATE_SEEDING || state == TorrentModelItem::STATE_STALLED_UP
|
||||
|| state == TorrentModelItem::STATE_CHECKING_UP || state == TorrentModelItem::STATE_QUEUED_UP
|
||||
|| state == TorrentModelItem::STATE_FORCED_UP);
|
||||
|
||||
case TorrentFilter::COMPLETED:
|
||||
return (state == TorrentModelItem::STATE_SEEDING || state == TorrentModelItem::STATE_STALLED_UP
|
||||
|| state == TorrentModelItem::STATE_PAUSED_UP || state == TorrentModelItem::STATE_CHECKING_UP
|
||||
|| state == TorrentModelItem::STATE_QUEUED_UP || state == TorrentModelItem::STATE_FORCED_UP);
|
||||
|
||||
case TorrentFilter::PAUSED:
|
||||
return (state == TorrentModelItem::STATE_PAUSED_DL || state == TorrentModelItem::STATE_PAUSED_MISSING);
|
||||
|
||||
case TorrentFilter::RESUMED:
|
||||
return (state != TorrentModelItem::STATE_PAUSED_UP && state != TorrentModelItem::STATE_PAUSED_DL
|
||||
&& state != TorrentModelItem::STATE_PAUSED_MISSING);
|
||||
|
||||
case TorrentFilter::ACTIVE:
|
||||
if (state == TorrentModelItem::STATE_STALLED_DL) {
|
||||
const qulonglong up_speed = model->index(sourceRow, TorrentModelItem::TR_UPSPEED, sourceParent).data().toULongLong();
|
||||
return (up_speed > 0);
|
||||
}
|
||||
|
||||
return (state == TorrentModelItem::STATE_DOWNLOADING || state == TorrentModelItem::STATE_SEEDING
|
||||
|| state == TorrentModelItem::STATE_FORCED_DL || state == TorrentModelItem::STATE_FORCED_UP);
|
||||
|
||||
case TorrentFilter::INACTIVE:
|
||||
if (state == TorrentModelItem::STATE_STALLED_DL) {
|
||||
const qulonglong up_speed = model->index(sourceRow, TorrentModelItem::TR_UPSPEED, sourceParent).data().toULongLong();
|
||||
return !(up_speed > 0);
|
||||
}
|
||||
|
||||
return (state != TorrentModelItem::STATE_DOWNLOADING && state != TorrentModelItem::STATE_SEEDING
|
||||
&& state != TorrentModelItem::STATE_FORCED_DL && state != TorrentModelItem::STATE_FORCED_UP);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TransferListSortModel::matchLabelFilter(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (!labelFilterEnabled)
|
||||
return true;
|
||||
|
||||
QAbstractItemModel *model = sourceModel();
|
||||
if (!model)
|
||||
return false;
|
||||
|
||||
return model->index(sourceRow, TorrentModelItem::TR_LABEL, sourceParent).data().toString() == labelFilter;
|
||||
}
|
||||
|
||||
bool TransferListSortModel::matchTrackerFilter(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (!trackerFilterEnabled)
|
||||
return true;
|
||||
|
||||
TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel());
|
||||
if (!model)
|
||||
return false;
|
||||
if (!model) return false;
|
||||
|
||||
return trackerFilter.contains(model->torrentHash(sourceRow));
|
||||
BitTorrent::TorrentHandle *const torrent = model->torrentHandle(model->index(sourceRow, 0, sourceParent));
|
||||
if (!torrent) return false;
|
||||
|
||||
return m_filter.match(torrent);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
#define TRANSFERLISTSORTMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStringList>
|
||||
#include "torrentfilterenum.h"
|
||||
#include "core/torrentfilter.h"
|
||||
|
||||
class QStringList;
|
||||
|
||||
class TransferListSortModel: public QSortFilterProxyModel
|
||||
{
|
||||
@@ -42,7 +43,7 @@ class TransferListSortModel: public QSortFilterProxyModel
|
||||
public:
|
||||
TransferListSortModel(QObject *parent = 0);
|
||||
|
||||
void setStatusFilter(const TorrentFilter::TorrentFilter &filter);
|
||||
void setStatusFilter(TorrentFilter::Type filter);
|
||||
void setLabelFilter(const QString &label);
|
||||
void disableLabelFilter();
|
||||
void setTrackerFilter(const QStringList &hashes);
|
||||
@@ -52,18 +53,10 @@ private:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
bool lowerPositionThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
|
||||
bool matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool matchLabelFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool matchTrackerFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool matchFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
|
||||
private:
|
||||
TorrentFilter::TorrentFilter filter0;
|
||||
|
||||
bool labelFilterEnabled;
|
||||
QString labelFilter;
|
||||
bool trackerFilterEnabled;
|
||||
QStringList trackerFilter;
|
||||
TorrentFilter m_filter;
|
||||
};
|
||||
|
||||
#endif // TRANSFERLISTSORTMODEL_H
|
||||
|
||||
@@ -42,14 +42,10 @@
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "transferlistwidget.h"
|
||||
#include "qbtsession.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "core/torrentfilter.h"
|
||||
#include "transferlistdelegate.h"
|
||||
#include "previewselect.h"
|
||||
#include "speedlimitdlg.h"
|
||||
@@ -60,15 +56,14 @@
|
||||
#include "torrentmodel.h"
|
||||
#include "deletionconfirmationdlg.h"
|
||||
#include "propertieswidget.h"
|
||||
#include "iconprovider.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "transferlistsortmodel.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window, QBtSession *_BTSession):
|
||||
QTreeView(parent), BTSession(_BTSession), main_window(main_window)
|
||||
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
|
||||
: QTreeView(parent)
|
||||
, main_window(main_window)
|
||||
{
|
||||
|
||||
setUniformRowHeights(true);
|
||||
@@ -181,12 +176,6 @@ void TransferListWidget::previewFile(QString filePath)
|
||||
openUrl(filePath);
|
||||
}
|
||||
|
||||
void TransferListWidget::setRefreshInterval(int t)
|
||||
{
|
||||
qDebug("Settings transfer list refresh interval to %dms", t);
|
||||
listModel->setRefreshInterval(t);
|
||||
}
|
||||
|
||||
int TransferListWidget::getRowFromHash(QString hash) const
|
||||
{
|
||||
return listModel->torrentRow(hash);
|
||||
@@ -216,24 +205,24 @@ void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
|
||||
{
|
||||
const int row = mapToSource(index).row();
|
||||
const QString hash = getHashFromRow(row);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_valid()) return;
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (!torrent) return;
|
||||
|
||||
int action;
|
||||
if (h.is_seed())
|
||||
if (torrent->isSeed())
|
||||
action = Preferences::instance()->getActionOnDblClOnTorrentFn();
|
||||
else
|
||||
action = Preferences::instance()->getActionOnDblClOnTorrentDl();
|
||||
|
||||
switch(action) {
|
||||
case TOGGLE_PAUSE:
|
||||
if (h.is_paused())
|
||||
h.resume();
|
||||
if (torrent->isPaused())
|
||||
torrent->resume();
|
||||
else
|
||||
h.pause();
|
||||
torrent->pause();
|
||||
break;
|
||||
case OPEN_DEST:
|
||||
const QString path = h.root_path();
|
||||
openUrl(path);
|
||||
openUrl(torrent->rootPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,72 +239,85 @@ void TransferListWidget::setSelectedTorrentsLocation()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
if (hashes.isEmpty()) return;
|
||||
|
||||
BitTorrent::TorrentHandle *const firstTorrent = BitTorrent::Session::instance()->findTorrent(hashes.first());
|
||||
if (!firstTorrent) return;
|
||||
|
||||
QString dir;
|
||||
const QDir saveDir(TorrentPersistentData::instance()->getSavePath(hashes.first()));
|
||||
const QDir saveDir(firstTorrent->savePath());
|
||||
qDebug("Old save path is %s", qPrintable(saveDir.absolutePath()));
|
||||
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), saveDir.absolutePath(),
|
||||
QFileDialog::DontConfirmOverwrite | QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails);
|
||||
if (!dir.isNull()) {
|
||||
qDebug("New path is %s", qPrintable(dir));
|
||||
// Check if savePath exists
|
||||
QDir savePath(fsutils::expandPathAbs(dir));
|
||||
qDebug("New path after clean up is %s", qPrintable(savePath.absolutePath()));
|
||||
foreach (const QString & hash, hashes) {
|
||||
foreach (const QString &hash, hashes) {
|
||||
// Actually move storage
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!BTSession->useTemporaryFolder() || h.is_seed()) {
|
||||
if (!savePath.exists()) savePath.mkpath(savePath.absolutePath());
|
||||
h.move_storage(savePath.absolutePath());
|
||||
}
|
||||
else {
|
||||
TorrentPersistentData::instance()->saveSavePath(h.hash(), savePath.absolutePath());
|
||||
main_window->getProperties()->updateSavePath(h);
|
||||
}
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (!torrent) continue;
|
||||
|
||||
torrent->move(fsutils::expandPathAbs(dir));
|
||||
main_window->getProperties()->updateSavePath(torrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::pauseAllTorrents()
|
||||
{
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||
torrent->pause();
|
||||
}
|
||||
|
||||
void TransferListWidget::resumeAllTorrents()
|
||||
{
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||
torrent->resume();
|
||||
}
|
||||
|
||||
void TransferListWidget::startSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->resumeTorrent(hash);
|
||||
foreach (const QString &hash, getSelectedTorrentsHashes()) {
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent->resume();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::forceStartSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->resumeTorrent(hash, true);
|
||||
foreach (const QString &hash, getSelectedTorrentsHashes()) {
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent->resume(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::startVisibleTorrents()
|
||||
{
|
||||
QStringList hashes;
|
||||
for (int i = 0; i<nameFilterModel->rowCount(); ++i) {
|
||||
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
|
||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
||||
hashes << getHashFromRow(row);
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
|
||||
if (torrent)
|
||||
torrent->resume();
|
||||
}
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->resumeTorrent(hash);
|
||||
}
|
||||
|
||||
void TransferListWidget::pauseSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->pauseTorrent(hash);
|
||||
foreach (const QString &hash, getSelectedTorrentsHashes()) {
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::pauseVisibleTorrents()
|
||||
{
|
||||
QStringList hashes;
|
||||
for (int i = 0; i<nameFilterModel->rowCount(); ++i) {
|
||||
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
|
||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
||||
hashes << getHashFromRow(row);
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
|
||||
if (torrent)
|
||||
torrent->pause();
|
||||
}
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->pauseTorrent(hash);
|
||||
}
|
||||
|
||||
void TransferListWidget::deleteSelectedTorrents()
|
||||
@@ -323,13 +325,14 @@ void TransferListWidget::deleteSelectedTorrents()
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList& hashes = getSelectedTorrentsHashes();
|
||||
if (hashes.empty()) return;
|
||||
QTorrentHandle torrent = BTSession->getTorrentHandle(hashes[0]);
|
||||
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes[0]);
|
||||
bool delete_local_files = false;
|
||||
if (Preferences::instance()->confirmTorrentDeletion() &&
|
||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent.name()))
|
||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent->name()))
|
||||
return;
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->deleteTorrent(hash, delete_local_files);
|
||||
BitTorrent::Session::instance()->deleteTorrent(hash, delete_local_files);
|
||||
}
|
||||
|
||||
void TransferListWidget::deleteVisibleTorrents()
|
||||
@@ -340,83 +343,40 @@ void TransferListWidget::deleteVisibleTorrents()
|
||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
||||
hashes << getHashFromRow(row);
|
||||
}
|
||||
QTorrentHandle torrent = BTSession->getTorrentHandle(hashes[0]);
|
||||
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes[0]);
|
||||
bool delete_local_files = false;
|
||||
if (Preferences::instance()->confirmTorrentDeletion() &&
|
||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent.name()))
|
||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent->name()))
|
||||
return;
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->deleteTorrent(hash, delete_local_files);
|
||||
BitTorrent::Session::instance()->deleteTorrent(hash, delete_local_files);
|
||||
}
|
||||
|
||||
void TransferListWidget::increasePrioSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
std::priority_queue<QPair<int, QTorrentHandle>, std::vector<QPair<int, QTorrentHandle> >, std::greater<QPair<int, QTorrentHandle> > > torrent_queue;
|
||||
// Sort torrents by priority
|
||||
foreach (const QString &hash, hashes) {
|
||||
try {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_seed())
|
||||
torrent_queue.push(qMakePair(h.queue_position(), h));
|
||||
}catch(invalid_handle&) {}
|
||||
}
|
||||
// Increase torrents priority (starting with the ones with highest priority)
|
||||
while(!torrent_queue.empty()) {
|
||||
QTorrentHandle h = torrent_queue.top().second;
|
||||
try {
|
||||
h.queue_position_up();
|
||||
} catch(invalid_handle& h) {}
|
||||
torrent_queue.pop();
|
||||
}
|
||||
if (main_window->getCurrentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->increaseTorrentsPriority(getSelectedTorrentsHashes());
|
||||
}
|
||||
|
||||
void TransferListWidget::decreasePrioSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
std::priority_queue<QPair<int, QTorrentHandle>, std::vector<QPair<int, QTorrentHandle> >, std::less<QPair<int, QTorrentHandle> > > torrent_queue;
|
||||
// Sort torrents by priority
|
||||
foreach (const QString &hash, hashes) {
|
||||
try {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_seed())
|
||||
torrent_queue.push(qMakePair(h.queue_position(), h));
|
||||
}catch(invalid_handle&) {}
|
||||
}
|
||||
// Decrease torrents priority (starting with the ones with lowest priority)
|
||||
while(!torrent_queue.empty()) {
|
||||
QTorrentHandle h = torrent_queue.top().second;
|
||||
try {
|
||||
h.queue_position_down();
|
||||
} catch(invalid_handle& h) {}
|
||||
torrent_queue.pop();
|
||||
}
|
||||
if (main_window->getCurrentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->decreaseTorrentsPriority(getSelectedTorrentsHashes());
|
||||
}
|
||||
|
||||
void TransferListWidget::topPrioSelectedTorrents()
|
||||
{
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && !h.is_seed())
|
||||
h.queue_position_top();
|
||||
}
|
||||
if (main_window->getCurrentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->topTorrentsPriority(getSelectedTorrentsHashes());
|
||||
}
|
||||
|
||||
void TransferListWidget::bottomPrioSelectedTorrents()
|
||||
{
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && !h.is_seed())
|
||||
h.queue_position_bottom();
|
||||
}
|
||||
if (main_window->getCurrentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->bottomTorrentsPriority(getSelectedTorrentsHashes());
|
||||
}
|
||||
|
||||
void TransferListWidget::copySelectedMagnetURIs() const
|
||||
@@ -424,9 +384,9 @@ void TransferListWidget::copySelectedMagnetURIs() const
|
||||
QStringList magnet_uris;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid())
|
||||
magnet_uris << misc::toQString(make_magnet_uri(h));
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
magnet_uris << torrent->toMagnetUri();
|
||||
}
|
||||
qApp->clipboard()->setText(magnet_uris.join("\n"));
|
||||
}
|
||||
@@ -436,9 +396,9 @@ void TransferListWidget::copySelectedNames() const
|
||||
QStringList torrent_names;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid())
|
||||
torrent_names << h.name();
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent_names << torrent->name();
|
||||
}
|
||||
qApp->clipboard()->setText(torrent_names.join("\n"));
|
||||
}
|
||||
@@ -456,9 +416,9 @@ void TransferListWidget::openSelectedTorrentsFolder() const
|
||||
QSet<QString> pathsList;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid()) {
|
||||
QString rootFolder = h.root_path();
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent) {
|
||||
QString rootFolder = torrent->rootPath();
|
||||
qDebug("Opening path at %s", qPrintable(rootFolder));
|
||||
if (!pathsList.contains(rootFolder)) {
|
||||
pathsList.insert(rootFolder);
|
||||
@@ -472,27 +432,27 @@ void TransferListWidget::previewSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && h.has_metadata())
|
||||
new PreviewSelect(this, h);
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent && torrent->hasMetadata())
|
||||
new PreviewSelect(this, torrent);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setDlLimitSelectedTorrents()
|
||||
{
|
||||
QList<QTorrentHandle> selected_torrents;
|
||||
QList<BitTorrent::TorrentHandle *> selected_torrents;
|
||||
bool first = true;
|
||||
bool all_same_limit = true;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && !h.is_seed()) {
|
||||
selected_torrents << h;
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent && !torrent->isSeed()) {
|
||||
selected_torrents << torrent;
|
||||
// Determine current limit for selected torrents
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
if (all_same_limit && h.download_limit() != selected_torrents.first().download_limit())
|
||||
if (all_same_limit && (torrent->downloadLimit() != selected_torrents.first()->downloadLimit()))
|
||||
all_same_limit = false;
|
||||
}
|
||||
}
|
||||
@@ -501,31 +461,31 @@ void TransferListWidget::setDlLimitSelectedTorrents()
|
||||
bool ok = false;
|
||||
int default_limit = -1;
|
||||
if (all_same_limit)
|
||||
default_limit = selected_torrents.first().download_limit();
|
||||
default_limit = selected_torrents.first()->downloadLimit();
|
||||
const long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Torrent Download Speed Limiting"), default_limit, Preferences::instance()->getGlobalDownloadLimit() * 1024.);
|
||||
if (ok) {
|
||||
foreach (const QTorrentHandle &h, selected_torrents) {
|
||||
qDebug("Applying download speed limit of %ld Kb/s to torrent %s", (long)(new_limit / 1024.), qPrintable(h.hash()));
|
||||
BTSession->setDownloadLimit(h.hash(), new_limit);
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, selected_torrents) {
|
||||
qDebug("Applying download speed limit of %ld Kb/s to torrent %s", (long)(new_limit / 1024.), qPrintable(torrent->hash()));
|
||||
torrent->setDownloadLimit(new_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setUpLimitSelectedTorrents()
|
||||
{
|
||||
QList<QTorrentHandle> selected_torrents;
|
||||
QList<BitTorrent::TorrentHandle *> selected_torrents;
|
||||
bool first = true;
|
||||
bool all_same_limit = true;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid()) {
|
||||
selected_torrents << h;
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent) {
|
||||
selected_torrents << torrent;
|
||||
// Determine current limit for selected torrents
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
if (all_same_limit && h.upload_limit() != selected_torrents.first().upload_limit())
|
||||
if (all_same_limit && (torrent->uploadLimit() != selected_torrents.first()->uploadLimit()))
|
||||
all_same_limit = false;
|
||||
}
|
||||
}
|
||||
@@ -534,12 +494,12 @@ void TransferListWidget::setUpLimitSelectedTorrents()
|
||||
bool ok = false;
|
||||
int default_limit = -1;
|
||||
if (all_same_limit)
|
||||
default_limit = selected_torrents.first().upload_limit();
|
||||
default_limit = selected_torrents.first()->uploadLimit();
|
||||
const long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Torrent Upload Speed Limiting"), default_limit, Preferences::instance()->getGlobalUploadLimit() * 1024.);
|
||||
if (ok) {
|
||||
foreach (const QTorrentHandle &h, selected_torrents) {
|
||||
qDebug("Applying upload speed limit of %ld Kb/s to torrent %s", (long)(new_limit / 1024.), qPrintable(h.hash()));
|
||||
BTSession->setUploadLimit(h.hash(), new_limit);
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, selected_torrents) {
|
||||
qDebug("Applying upload speed limit of %ld Kb/s to torrent %s", (long)(new_limit / 1024.), qPrintable(torrent->hash()));
|
||||
torrent->setUploadLimit(new_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,34 +509,37 @@ void TransferListWidget::setMaxRatioSelectedTorrents()
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
if (hashes.isEmpty())
|
||||
return;
|
||||
bool useGlobalValue;
|
||||
qreal currentMaxRatio;
|
||||
bool useGlobalValue = true;
|
||||
qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio();;
|
||||
if (hashes.count() == 1) {
|
||||
currentMaxRatio = BTSession->getMaxRatioPerTorrent(hashes.first(), &useGlobalValue);
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes.first());
|
||||
if (torrent)
|
||||
currentMaxRatio = torrent->maxRatio(&useGlobalValue);
|
||||
}
|
||||
else {
|
||||
useGlobalValue = true;
|
||||
currentMaxRatio = BTSession->getGlobalMaxRatio();
|
||||
}
|
||||
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, QBtSession::MAX_RATIO, this);
|
||||
if (dlg.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO, this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
|
||||
foreach (const QString &hash, hashes) {
|
||||
if (dlg.useDefault())
|
||||
BTSession->removeRatioPerTorrent(hash);
|
||||
else
|
||||
BTSession->setMaxRatioPerTorrent(hash, dlg.ratio());
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent) {
|
||||
qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio());
|
||||
torrent->setRatioLimit(ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::recheckSelectedTorrents()
|
||||
{
|
||||
QMessageBox::StandardButton ret = QMessageBox::question(this, tr("Recheck confirmation"), tr("Are you sure you want to recheck the selected torrent(s)?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
if (ret != QMessageBox::Yes)
|
||||
return;
|
||||
if (ret != QMessageBox::Yes) return;
|
||||
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->recheckTorrent(hash);
|
||||
foreach (const QString &hash, hashes) {
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent->forceRecheck();
|
||||
}
|
||||
}
|
||||
|
||||
// hide/show columns menu
|
||||
@@ -586,7 +549,7 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
|
||||
hideshowColumn.setTitle(tr("Column visibility"));
|
||||
QList<QAction*> actions;
|
||||
for (int i = 0; i < listModel->columnCount(); ++i) {
|
||||
if (!BTSession->isQueueingEnabled() && i == TorrentModelItem::TR_PRIORITY) {
|
||||
if (!BitTorrent::Session::instance()->isQueueingEnabled() && i == TorrentModelItem::TR_PRIORITY) {
|
||||
actions.append(0);
|
||||
continue;
|
||||
}
|
||||
@@ -624,9 +587,9 @@ void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && h.has_metadata())
|
||||
h.super_seeding(!h.status(0).super_seeding);
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent && torrent->hasMetadata())
|
||||
torrent->setSuperSeeding(!torrent->superSeeding());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,8 +597,9 @@ void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
h.toggleSequentialDownload();
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent->toggleSequentialDownload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,8 +607,9 @@ void TransferListWidget::toggleSelectedFirstLastPiecePrio() const
|
||||
{
|
||||
QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
h.toggleFirstLastPiecePrio();
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
torrent->setFirstLastPiecePriority(!torrent->hasFirstLastPiecePriority());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,11 +650,12 @@ void TransferListWidget::renameSelectedTorrent()
|
||||
if (!selectedIndexes.first().isValid()) return;
|
||||
QModelIndex mi = mapToSource(selectedIndexes.first());
|
||||
const QString hash = getHashFromRow(mi.row());
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_valid()) return;
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (!torrent) return;
|
||||
|
||||
// Ask for a new Name
|
||||
bool ok;
|
||||
QString name = AutoExpandableDialog::getText(this, tr("Rename"), tr("New name:"), QLineEdit::Normal, h.name(), &ok);
|
||||
QString name = AutoExpandableDialog::getText(this, tr("Rename"), tr("New name:"), QLineEdit::Normal, torrent->name(), &ok);
|
||||
if (ok && !name.isEmpty()) {
|
||||
name.replace(QRegExp("\r?\n|\r"), " ");
|
||||
// Rename the torrent
|
||||
@@ -703,23 +669,15 @@ void TransferListWidget::setSelectionLabel(QString label)
|
||||
foreach (const QString &hash, hashes) {
|
||||
Q_ASSERT(!hash.isEmpty());
|
||||
const int row = getRowFromHash(hash);
|
||||
const QString old_label = listModel->data(listModel->index(row, TorrentModelItem::TR_LABEL)).toString();
|
||||
listModel->setData(listModel->index(row, TorrentModelItem::TR_LABEL), QVariant(label), Qt::DisplayRole);
|
||||
// Update save path if necessary
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
BTSession->changeLabelInTorrentSavePath(h, old_label, label);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::removeLabelFromRows(QString label)
|
||||
{
|
||||
for (int i = 0; i<listModel->rowCount(); ++i) {
|
||||
for (int i = 0; i < listModel->rowCount(); ++i) {
|
||||
if (listModel->data(listModel->index(i, TorrentModelItem::TR_LABEL)) == label) {
|
||||
const QString hash = getHashFromRow(i);
|
||||
listModel->setData(listModel->index(i, TorrentModelItem::TR_LABEL), "", Qt::DisplayRole);
|
||||
// Update save path if necessary
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
BTSession->changeLabelInTorrentSavePath(h, label, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -730,15 +688,15 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
if (selectedIndexes.size() == 0)
|
||||
return;
|
||||
// Create actions
|
||||
QAction actionStart(IconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), 0);
|
||||
QAction actionStart(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), 0);
|
||||
connect(&actionStart, SIGNAL(triggered()), this, SLOT(startSelectedTorrents()));
|
||||
QAction actionForceStart(tr("Force Resume", "Force Resume/start the torrent"), 0);
|
||||
connect(&actionForceStart, SIGNAL(triggered()), this, SLOT(forceStartSelectedTorrents()));
|
||||
QAction actionPause(IconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), 0);
|
||||
QAction actionPause(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), 0);
|
||||
connect(&actionPause, SIGNAL(triggered()), this, SLOT(pauseSelectedTorrents()));
|
||||
QAction actionDelete(IconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), 0);
|
||||
QAction actionDelete(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), 0);
|
||||
connect(&actionDelete, SIGNAL(triggered()), this, SLOT(deleteSelectedTorrents()));
|
||||
QAction actionPreview_file(IconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), 0);
|
||||
QAction actionPreview_file(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), 0);
|
||||
connect(&actionPreview_file, SIGNAL(triggered()), this, SLOT(previewSelectedTorrents()));
|
||||
QAction actionSet_max_ratio(QIcon(QString::fromUtf8(":/icons/skin/ratio.png")), tr("Limit share ratio..."), 0);
|
||||
connect(&actionSet_max_ratio, SIGNAL(triggered()), this, SLOT(setMaxRatioSelectedTorrents()));
|
||||
@@ -746,28 +704,28 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
connect(&actionSet_upload_limit, SIGNAL(triggered()), this, SLOT(setUpLimitSelectedTorrents()));
|
||||
QAction actionSet_download_limit(QIcon(QString::fromUtf8(":/icons/skin/download.png")), tr("Limit download rate..."), 0);
|
||||
connect(&actionSet_download_limit, SIGNAL(triggered()), this, SLOT(setDlLimitSelectedTorrents()));
|
||||
QAction actionOpen_destination_folder(IconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), 0);
|
||||
QAction actionOpen_destination_folder(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), 0);
|
||||
connect(&actionOpen_destination_folder, SIGNAL(triggered()), this, SLOT(openSelectedTorrentsFolder()));
|
||||
QAction actionIncreasePriority(IconProvider::instance()->getIcon("go-up"), tr("Move up", "i.e. move up in the queue"), 0);
|
||||
QAction actionIncreasePriority(GuiIconProvider::instance()->getIcon("go-up"), tr("Move up", "i.e. move up in the queue"), 0);
|
||||
connect(&actionIncreasePriority, SIGNAL(triggered()), this, SLOT(increasePrioSelectedTorrents()));
|
||||
QAction actionDecreasePriority(IconProvider::instance()->getIcon("go-down"), tr("Move down", "i.e. Move down in the queue"), 0);
|
||||
QAction actionDecreasePriority(GuiIconProvider::instance()->getIcon("go-down"), tr("Move down", "i.e. Move down in the queue"), 0);
|
||||
connect(&actionDecreasePriority, SIGNAL(triggered()), this, SLOT(decreasePrioSelectedTorrents()));
|
||||
QAction actionTopPriority(IconProvider::instance()->getIcon("go-top"), tr("Move to top", "i.e. Move to top of the queue"), 0);
|
||||
QAction actionTopPriority(GuiIconProvider::instance()->getIcon("go-top"), tr("Move to top", "i.e. Move to top of the queue"), 0);
|
||||
connect(&actionTopPriority, SIGNAL(triggered()), this, SLOT(topPrioSelectedTorrents()));
|
||||
QAction actionBottomPriority(IconProvider::instance()->getIcon("go-bottom"), tr("Move to bottom", "i.e. Move to bottom of the queue"), 0);
|
||||
QAction actionBottomPriority(GuiIconProvider::instance()->getIcon("go-bottom"), tr("Move to bottom", "i.e. Move to bottom of the queue"), 0);
|
||||
connect(&actionBottomPriority, SIGNAL(triggered()), this, SLOT(bottomPrioSelectedTorrents()));
|
||||
QAction actionSetTorrentPath(IconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), 0);
|
||||
QAction actionSetTorrentPath(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), 0);
|
||||
connect(&actionSetTorrentPath, SIGNAL(triggered()), this, SLOT(setSelectedTorrentsLocation()));
|
||||
QAction actionForce_recheck(IconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), 0);
|
||||
QAction actionForce_recheck(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), 0);
|
||||
connect(&actionForce_recheck, SIGNAL(triggered()), this, SLOT(recheckSelectedTorrents()));
|
||||
QAction actionCopy_magnet_link(QIcon(":/icons/magnet.png"), tr("Copy magnet link"), 0);
|
||||
connect(&actionCopy_magnet_link, SIGNAL(triggered()), this, SLOT(copySelectedMagnetURIs()));
|
||||
QAction actionCopy_name(IconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), 0);
|
||||
QAction actionCopy_name(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), 0);
|
||||
connect(&actionCopy_name, SIGNAL(triggered()), this, SLOT(copySelectedNames()));
|
||||
QAction actionSuper_seeding_mode(tr("Super seeding mode"), 0);
|
||||
actionSuper_seeding_mode.setCheckable(true);
|
||||
connect(&actionSuper_seeding_mode, SIGNAL(triggered()), this, SLOT(toggleSelectedTorrentsSuperSeeding()));
|
||||
QAction actionRename(IconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), 0);
|
||||
QAction actionRename(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), 0);
|
||||
connect(&actionRename, SIGNAL(triggered()), this, SLOT(renameSelectedTorrent()));
|
||||
QAction actionSequential_download(tr("Download in sequential order"), 0);
|
||||
actionSequential_download.setCheckable(true);
|
||||
@@ -786,43 +744,45 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
bool one_has_metadata = false, one_not_seed = false;
|
||||
bool first = true;
|
||||
bool forced = false;
|
||||
QTorrentHandle h;
|
||||
|
||||
BitTorrent::TorrentHandle *torrent;
|
||||
qDebug("Displaying menu");
|
||||
foreach (const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file name
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
// Get handle and pause the torrent
|
||||
h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_valid()) continue;
|
||||
if (h.has_metadata())
|
||||
torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (!torrent) continue;
|
||||
|
||||
if (torrent->hasMetadata())
|
||||
one_has_metadata = true;
|
||||
forced = h.is_forced();
|
||||
if (!h.is_seed()) {
|
||||
forced = torrent->isForced();
|
||||
if (!torrent->isSeed()) {
|
||||
one_not_seed = true;
|
||||
if (h.has_metadata()) {
|
||||
if (torrent->hasMetadata()) {
|
||||
if (first) {
|
||||
sequential_download_mode = h.is_sequential_download();
|
||||
prioritize_first_last = h.first_last_piece_first();
|
||||
sequential_download_mode = torrent->isSequentialDownload();
|
||||
prioritize_first_last = torrent->hasFirstLastPiecePriority();
|
||||
}
|
||||
else {
|
||||
if (sequential_download_mode != h.is_sequential_download())
|
||||
if (sequential_download_mode != torrent->isSequentialDownload())
|
||||
all_same_sequential_download_mode = false;
|
||||
if (prioritize_first_last != h.first_last_piece_first())
|
||||
if (prioritize_first_last != torrent->hasFirstLastPiecePriority())
|
||||
all_same_prio_firstlast = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!one_not_seed && all_same_super_seeding && h.has_metadata()) {
|
||||
if (!one_not_seed && all_same_super_seeding && torrent->hasMetadata()) {
|
||||
if (first) {
|
||||
super_seeding_mode = h.status(0).super_seeding;
|
||||
super_seeding_mode = torrent->superSeeding();
|
||||
}
|
||||
else if (super_seeding_mode != h.status(0).super_seeding)
|
||||
else if (super_seeding_mode != torrent->superSeeding())
|
||||
all_same_super_seeding = false;
|
||||
|
||||
}
|
||||
}
|
||||
if (h.is_paused()) {
|
||||
if (torrent->isPaused()) {
|
||||
if (!has_start) {
|
||||
listMenu.addAction(&actionStart);
|
||||
has_start = true;
|
||||
@@ -852,7 +812,7 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
has_pause = true;
|
||||
}
|
||||
}
|
||||
if (h.has_metadata() && !has_preview)
|
||||
if (torrent->hasMetadata() && !has_preview)
|
||||
has_preview = true;
|
||||
first = false;
|
||||
if (has_pause && has_start && has_force && has_preview && one_not_seed) break;
|
||||
@@ -867,12 +827,12 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
QStringList customLabels = Preferences::instance()->getTorrentLabels();
|
||||
customLabels.sort();
|
||||
QList<QAction*> labelActions;
|
||||
QMenu *labelMenu = listMenu.addMenu(IconProvider::instance()->getIcon("view-categories"), tr("Label"));
|
||||
labelActions << labelMenu->addAction(IconProvider::instance()->getIcon("list-add"), tr("New...", "New label..."));
|
||||
labelActions << labelMenu->addAction(IconProvider::instance()->getIcon("edit-clear"), tr("Reset", "Reset label"));
|
||||
QMenu *labelMenu = listMenu.addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Label"));
|
||||
labelActions << labelMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New...", "New label..."));
|
||||
labelActions << labelMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Reset", "Reset label"));
|
||||
labelMenu->addSeparator();
|
||||
foreach (const QString &label, customLabels)
|
||||
labelActions << labelMenu->addAction(IconProvider::instance()->getIcon("inode-directory"), label);
|
||||
labelActions << labelMenu->addAction(GuiIconProvider::instance()->getIcon("inode-directory"), label);
|
||||
listMenu.addSeparator();
|
||||
if (one_not_seed)
|
||||
listMenu.addAction(&actionSet_download_limit);
|
||||
@@ -907,7 +867,7 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
listMenu.addSeparator();
|
||||
}
|
||||
listMenu.addAction(&actionOpen_destination_folder);
|
||||
if (BTSession->isQueueingEnabled() && one_not_seed) {
|
||||
if (BitTorrent::Session::instance()->isQueueingEnabled() && one_not_seed) {
|
||||
listMenu.addSeparator();
|
||||
QMenu *prioMenu = listMenu.addMenu(tr("Priority"));
|
||||
prioMenu->addAction(&actionTopPriority);
|
||||
@@ -944,14 +904,14 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
||||
void TransferListWidget::currentChanged(const QModelIndex& current, const QModelIndex&)
|
||||
{
|
||||
qDebug("CURRENT CHANGED");
|
||||
QTorrentHandle h;
|
||||
BitTorrent::TorrentHandle *torrent = 0;
|
||||
if (current.isValid()) {
|
||||
const int row = mapToSource(current).row();
|
||||
h = BTSession->getTorrentHandle(getHashFromRow(row));
|
||||
torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
|
||||
// Scroll Fix
|
||||
scrollTo(current);
|
||||
}
|
||||
emit currentTorrentChanged(h);
|
||||
emit currentTorrentChanged(torrent);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyLabelFilterAll()
|
||||
@@ -982,7 +942,7 @@ void TransferListWidget::applyNameFilter(const QString& name)
|
||||
|
||||
void TransferListWidget::applyStatusFilter(int f)
|
||||
{
|
||||
nameFilterModel->setStatusFilter((TorrentFilter::TorrentFilter)f);
|
||||
nameFilterModel->setStatusFilter(static_cast<TorrentFilter::Type>(f));
|
||||
// Select first item if nothing is selected
|
||||
if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) {
|
||||
qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModelItem::TR_NAME).data().toString()));
|
||||
|
||||
@@ -32,10 +32,12 @@
|
||||
#define TRANSFERLISTWIDGET_H
|
||||
|
||||
#include <QTreeView>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
class QBtSession;
|
||||
class QTorrentHandle;
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentHandle;
|
||||
}
|
||||
|
||||
class MainWindow;
|
||||
class TransferListDelegate;
|
||||
class TransferListSortModel;
|
||||
@@ -52,14 +54,15 @@ class TransferListWidget: public QTreeView
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TransferListWidget(QWidget *parent, MainWindow *main_window, QBtSession* BTSession);
|
||||
TransferListWidget(QWidget *parent, MainWindow *main_window);
|
||||
~TransferListWidget();
|
||||
TorrentModel* getSourceModel() const;
|
||||
|
||||
public slots:
|
||||
void setSelectionLabel(QString label);
|
||||
void setRefreshInterval(int t);
|
||||
void setSelectedTorrentsLocation();
|
||||
void pauseAllTorrents();
|
||||
void resumeAllTorrents();
|
||||
void startSelectedTorrents();
|
||||
void forceStartSelectedTorrents();
|
||||
void startVisibleTorrents();
|
||||
@@ -113,13 +116,12 @@ private:
|
||||
bool openUrl(const QString& _path) const;
|
||||
|
||||
signals:
|
||||
void currentTorrentChanged(const QTorrentHandle &h);
|
||||
void currentTorrentChanged(BitTorrent::TorrentHandle *const torrent);
|
||||
|
||||
private:
|
||||
TransferListDelegate *listDelegate;
|
||||
TorrentModel *listModel;
|
||||
TransferListSortModel *nameFilterModel;
|
||||
QBtSession* BTSession;
|
||||
MainWindow *main_window;
|
||||
QShortcut *editHotkey;
|
||||
QShortcut *deleteHotkey;
|
||||
|
||||
Reference in New Issue
Block a user