Compare commits
1 Commits
release-1.
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b0d473a53 |
5
AUTHORS
@@ -17,11 +17,6 @@ Images Authors:
|
||||
license: GPLv2
|
||||
url: http://ftp.acc.umu.se/pub/GNOME/sources/gnome-icon-theme
|
||||
|
||||
* files: src/oxygen/*.png
|
||||
copyright: Oxygen Icon Theme (KDE)
|
||||
license: LGPL
|
||||
url: http://www.oxygen-icons.org
|
||||
|
||||
* files: src/Icons/flags/*.png
|
||||
copyright: Open Clip Art Library
|
||||
license: Creative Commons Public Domain Dedication
|
||||
|
||||
14
COPYING
@@ -1,17 +1,3 @@
|
||||
qBittorrent is licensed under the GNU General Public License version 2 with the
|
||||
addition of the following special exception:
|
||||
|
||||
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.
|
||||
|
||||
----------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
||||
69
Changelog
@@ -1,72 +1,3 @@
|
||||
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.5.0
|
||||
- FEATURE: Added Magnet URI support
|
||||
- FEATURE: Make use of torrent enclosure in RSS feeds for direct download
|
||||
- FEATURE: Implemented a RSS feed downloader with filter support
|
||||
- FEATURE: Save old RSS item to hard disk to remember them on start up
|
||||
- FEATURE: Display free disk space in torrent addition dialog
|
||||
- FEATURE: In torrent addition from URL, paste clipboard content if it contains an URL
|
||||
- FEATURE: RSS Feeds URLs can now be copied to clipboard
|
||||
- FEATURE: If a torrent contains a torrent file, process downloaded torrent file too
|
||||
- BUGFIX: torrent resume code rewrited
|
||||
|
||||
* Thu Aug 13 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.0
|
||||
- FEATURE: Display swarm information in lists
|
||||
- FEATURE: Allow to define temporary download folder
|
||||
- FEATURE: Display total amount of uploaded data in finished list
|
||||
- FEATURE: Resizing a column in a search results tab affects all tabs
|
||||
- FEATURE: Search results tab columns are now remembered upon startup
|
||||
- FEATURE: Added right click menu in search engine to clear completion history
|
||||
- FEATURE: Allow to set a different port for DHT (UDP) than the one used for Bittorrent
|
||||
- FEATURE: Updated spoofing code to avoid trackers ban
|
||||
- BUGFIX: Provide more helpful explanation when an I/O error occured
|
||||
- BUGFIX: Stop enforcing UTF-8 and use system locale instead
|
||||
- COSMETIC: Redesigned program preferences
|
||||
- COSMETIC: Updated icons set
|
||||
|
||||
* Fri Jul 24 2009 - Christophe DUMEZ <chris@qbittorrent.org> - 1.3.5
|
||||
- BUGFIX: Made IP filter parser more robust
|
||||
- BUGFIX: Fixed torrent creation tool
|
||||
- BUGFIX: Fixed possible overflow in progress calculation in arborescence.h
|
||||
- BUGFIX: Save properties window size, position, columns width and restore them
|
||||
- BUGFIX: Set a minimum default width for NAME column in properties
|
||||
- BUGFIX: Remember visual indexes of columns in transfer lists
|
||||
|
||||
* Sun Jul 12 2009 - Christophe DUMEZ <chris@qbittorrent.org> - v1.3.4
|
||||
- BUGFIX: Fixed IP filter file parsing on 64bits
|
||||
- BUGFIX: Suppressed QLayout: Attempting to add QLayout "" to properties "properties" warning message when opening a properties dialog
|
||||
- BUGFIX: Fixed a little bug in search engine plugins helper file
|
||||
- BUGFIX: Fixed compilation problems with Qt 4.3
|
||||
- BUGFIX: Percentages no longer disapear with default cleanlooks style
|
||||
- BUGFIX: Cleanly fixed popup menus position in lists (no more workarounds)
|
||||
- BUGFIX: Fixed memory leak in search engine
|
||||
- BUGFIX: Torrents with an infinite ratio are no longer affected by ratio_limit set in program preferences
|
||||
- BUGFIX: Display a ratio of 0.0 if total_upload and total_download are both 0
|
||||
- BUGFIX: Remove last separator in top tool bar
|
||||
- BUGFIX: Tuned lists properties to make sure display is correct
|
||||
- COSMETIC: Display date as well as time in log window
|
||||
|
||||
* Sun Apr 5 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.3
|
||||
- BUGFIX: Fixed Web UI torrent upload form
|
||||
- BUGFIX: Fixed unicode support in search engine
|
||||
- BUGFIX: Fixed search engine bug that prevented a torrent from appearing more than once among all tabs
|
||||
- LICENSE: Added an exception to the license regarding OpenSSL.
|
||||
- I18N: Updated Finnish translation
|
||||
|
||||
* Sat Mar 7 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.2
|
||||
- BUGFIX: Fix top toolbar disabling
|
||||
- BUGFIX: Fix building with Qt 4.5
|
||||
- BUGFIX: RSS items read status is now remembered upon restart
|
||||
|
||||
* Mon Jan 26 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.1
|
||||
- BUGFIX: Torrents paused due to an I/O error were displayed as queued
|
||||
- BUGFIX: qBittorrent now prints backtrace in terminal when segfaulting
|
||||
- BUGFIX: Fixed files progress display in torrent properties
|
||||
- BUGFIX: Improved torrent ratio calculation
|
||||
- BUGFIX: Fixed possible crash when parsing filter file
|
||||
- BUGFIX: Made some code optimization
|
||||
- BUGFIX: Fixed download/upload speed decrease problems
|
||||
- I18N: Updated Finnish, Bulgarian and Greek translations
|
||||
|
||||
* Fri Jan 9 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.0
|
||||
- FEATURE: Based on libtorrent-rasterbar v0.14.2
|
||||
- FEATURE: Improved ratio calculation system
|
||||
|
||||
16
TODO
@@ -1,2 +1,18 @@
|
||||
See https://blueprints.launchpad.net/qbittorrent/
|
||||
|
||||
// translations done in v1.3.0
|
||||
- Romanian
|
||||
- Russian
|
||||
- Hungarian
|
||||
- German
|
||||
- Chinese (traditional)
|
||||
- Chinese (simplified)
|
||||
- Italian
|
||||
- Swedish
|
||||
- Turkish
|
||||
- French
|
||||
- Slovak
|
||||
- Czech
|
||||
- Korean
|
||||
- Portuguese
|
||||
- Brazilian
|
||||
|
||||
95
configure
vendored
@@ -18,6 +18,11 @@ Main options:
|
||||
--help This help text.
|
||||
|
||||
Dependency options:
|
||||
--with-libtorrent-inc=[path] Path to libtorrent-rasterbar include
|
||||
files
|
||||
--with-libtorrent-lib=[path] Path to libtorrent-rasterbar library
|
||||
files
|
||||
--with-libtorrent-static-lib=[path] Path to libtorrent-rasterbar .a file
|
||||
--with-libboost-inc=[path] Path to libboost include files
|
||||
--with-libcurl-inc=[path] Path to libcurl include files
|
||||
--with-libcurl-lib=[path] Path to libcurl library files
|
||||
@@ -140,6 +145,21 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-inc=*)
|
||||
QC_WITH_LIBTORRENT_INC=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-lib=*)
|
||||
QC_WITH_LIBTORRENT_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-static-lib=*)
|
||||
QC_WITH_LIBTORRENT_STATIC_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libboost-inc=*)
|
||||
QC_WITH_LIBBOOST_INC=$optarg
|
||||
shift
|
||||
@@ -191,6 +211,9 @@ echo PREFIX=$PREFIX
|
||||
echo BINDIR=$BINDIR
|
||||
echo DATADIR=$DATADIR
|
||||
echo EX_QTDIR=$EX_QTDIR
|
||||
echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC
|
||||
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
|
||||
echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB
|
||||
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
|
||||
echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC
|
||||
echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB
|
||||
@@ -323,29 +346,70 @@ public:
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libtorrent-rasterbar
|
||||
arg: with-libtorrent-inc=[path], Path to libtorrent-rasterbar include files
|
||||
arg: with-libtorrent-lib=[path], Path to libtorrent-rasterbar library files
|
||||
arg: with-libtorrent-static-lib=[path], Path to libtorrent-rasterbar .a file
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.0 (>= 0.14.4 advised)"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.0";
|
||||
QString adv_ver = "0.14.4";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "libtorrent/magnet_uri.hpp")) {
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(!libs.isEmpty())
|
||||
conf->addLib(libs);
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
||||
printf("\nWarning: libtorrent-rasterbar v%s was detected. Although it will compile and run, you will probably experience some bugs. Please consider updating to v%s!\n", version.toUtf8().data(), adv_ver.toUtf8().data());
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "libtorrent/magnet_uri.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
conf->addIncludePath(s+QDir::separator()+"libtorrent");
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
|
||||
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
|
||||
conf->addLib(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "torrent-rasterbar")) {
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "torrent-rasterbar")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -1503,6 +1567,9 @@ export PREFIX
|
||||
export BINDIR
|
||||
export DATADIR
|
||||
export EX_QTDIR
|
||||
export QC_WITH_LIBTORRENT_INC
|
||||
export QC_WITH_LIBTORRENT_LIB
|
||||
export QC_WITH_LIBTORRENT_STATIC_LIB
|
||||
export QC_WITH_LIBBOOST_INC
|
||||
export QC_WITH_LIBCURL_INC
|
||||
export QC_WITH_LIBCURL_LIB
|
||||
|
||||
65
qcm/libcommoncpp2.qcm
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libcommoncpp2
|
||||
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
|
||||
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_libcommoncpp2 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libcommoncpp2(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "GNU Common C++ library (libcommoncpp2)"; }
|
||||
QString shortname() const { return "libcommoncpp2"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "cc++/url.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "cc++/url.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!QFile::exists(s+QString("/libccext2.so")))
|
||||
return false;
|
||||
if(!QFile::exists(s+QString("/libccgnu2.so")))
|
||||
return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(QFile::exists(s+QString("libccext2.so"))){
|
||||
if(QFile::exists(s+QString("libccgnu2.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -64,11 +64,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
QString out = "";
|
||||
QProcess magickConfig;
|
||||
QStringList params;
|
||||
params << "--libs";
|
||||
qconf->doCommand("Magick++-config", params, &out);
|
||||
out = out.replace("\n", "");
|
||||
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
|
||||
magickConfig.waitForStarted();
|
||||
magickConfig.waitForFinished();
|
||||
QByteArray result = magickConfig.readAll();
|
||||
result = result.replace("\n", "");
|
||||
conf->addLib(result.data());
|
||||
conf->addDefine("HAVE_MAGICK");
|
||||
return true;
|
||||
|
||||
@@ -1,29 +1,70 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libtorrent-rasterbar
|
||||
arg: with-libtorrent-inc=[path], Path to libtorrent-rasterbar include files
|
||||
arg: with-libtorrent-lib=[path], Path to libtorrent-rasterbar library files
|
||||
arg: with-libtorrent-static-lib=[path], Path to libtorrent-rasterbar .a file
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.0 (>= 0.14.4 advised)"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.0";
|
||||
QString adv_ver = "0.14.4";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "libtorrent/magnet_uri.hpp")) {
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(!libs.isEmpty())
|
||||
conf->addLib(libs);
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
||||
printf("\nWarning: libtorrent-rasterbar v%s was detected. Although it will compile and run, you will probably experience some bugs. Please consider updating to v%s!\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "libtorrent/magnet_uri.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
conf->addIncludePath(s+QDir::separator()+"libtorrent");
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
|
||||
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
|
||||
conf->addLib(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "torrent-rasterbar")) {
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "torrent-rasterbar")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -81,9 +72,6 @@ class DLListDelegate: public QItemDelegate {
|
||||
case RATIO:{
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double ratio = index.data().toDouble();
|
||||
if(ratio > 100.)
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::fromUtf8("∞"));
|
||||
else
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,480 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef FEEDDOWNLOADER_H
|
||||
#define FEEDDOWNLOADER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QSettings>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QRegExp>
|
||||
#include <QMenu>
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "bittorrent.h"
|
||||
#include "ui_FeedDownloader.h"
|
||||
|
||||
class FeedFilter: public QHash<QString, QVariant> {
|
||||
private:
|
||||
bool valid;
|
||||
public:
|
||||
FeedFilter():valid(true) {}
|
||||
FeedFilter(bool valid): valid(valid) {}
|
||||
FeedFilter(QHash<QString, QVariant> filter): QHash<QString, QVariant>(filter), valid(true) {}
|
||||
|
||||
bool matches(QString s) {
|
||||
QStringList match_tokens = getMatchingTokens();
|
||||
foreach(const QString& token, match_tokens) {
|
||||
if(token.isEmpty() || token == "")
|
||||
continue;
|
||||
QRegExp reg(token, Qt::CaseInsensitive);
|
||||
if(reg.indexIn(s) < 0) return false;
|
||||
}
|
||||
// Checking not matching
|
||||
QStringList notmatch_tokens = getNotMatchingTokens();
|
||||
foreach(const QString& token, notmatch_tokens) {
|
||||
if(token.isEmpty()) continue;
|
||||
QRegExp reg(token, Qt::CaseInsensitive);
|
||||
if(reg.indexIn(s) > -1) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return valid;
|
||||
}
|
||||
|
||||
QStringList getMatchingTokens() const {
|
||||
QString matches = this->value("matches", "").toString();
|
||||
return matches.split(" ");
|
||||
}
|
||||
|
||||
QString getMatchingTokens_str() const {
|
||||
return this->value("matches", "*").toString();
|
||||
}
|
||||
|
||||
void setMatchingTokens(QString tokens) {
|
||||
tokens = tokens.trimmed();
|
||||
if(tokens.isEmpty())
|
||||
(*this)["matches"] = "";
|
||||
else
|
||||
(*this)["matches"] = tokens;
|
||||
}
|
||||
|
||||
QStringList getNotMatchingTokens() const {
|
||||
QString notmatching = this->value("not", "").toString();
|
||||
return notmatching.split(" ");
|
||||
}
|
||||
|
||||
QString getNotMatchingTokens_str() const {
|
||||
return this->value("not", "").toString();
|
||||
}
|
||||
|
||||
void setNotMatchingTokens(QString tokens) {
|
||||
(*this)["not"] = tokens.trimmed();
|
||||
}
|
||||
|
||||
QString getSavePath() const {
|
||||
return this->value("save_path", "").toString();
|
||||
}
|
||||
|
||||
void setSavePath(QString save_path) {
|
||||
(*this)["save_path"] = save_path;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FeedFilters : public QHash<QString, QVariant> {
|
||||
|
||||
private:
|
||||
QString feed_url;
|
||||
|
||||
public:
|
||||
FeedFilters() {}
|
||||
FeedFilters(QString feed_url, QHash<QString, QVariant> filters): QHash<QString, QVariant>(filters), feed_url(feed_url) {}
|
||||
|
||||
bool hasFilter(QString name) const {
|
||||
return this->contains(name);
|
||||
}
|
||||
|
||||
FeedFilter* matches(QString s) {
|
||||
if(!isDownloadingEnabled()) return 0;
|
||||
if(this->size() == 0) return new FeedFilter(false);
|
||||
foreach(QVariant var_hash_filter, this->values()) {
|
||||
QHash<QString, QVariant> hash_filter = var_hash_filter.toHash();
|
||||
FeedFilter *filter = new FeedFilter(hash_filter);
|
||||
if(filter->matches(s))
|
||||
return filter;
|
||||
else
|
||||
delete filter;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList names() const {
|
||||
return this->keys();
|
||||
}
|
||||
|
||||
FeedFilter getFilter(QString name) const {
|
||||
if(this->contains(name))
|
||||
return FeedFilter(this->value(name).toHash());
|
||||
return FeedFilter();
|
||||
}
|
||||
|
||||
void setFilter(QString name, FeedFilter f) {
|
||||
(*this)[name] = f;
|
||||
}
|
||||
|
||||
bool isDownloadingEnabled() const {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
return feeds_w_downloader.value(feed_url, false).toBool();
|
||||
}
|
||||
|
||||
void setDownloadingEnabled(bool enabled) {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
feeds_w_downloader[feed_url] = enabled;
|
||||
qBTRSS.setValue("downloader_on", feeds_w_downloader);
|
||||
}
|
||||
|
||||
static FeedFilters getFeedFilters(QString url) {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||
return FeedFilters(url, all_feeds_filters.value(url, QHash<QString, QVariant>()).toHash());
|
||||
}
|
||||
|
||||
void rename(QString old_name, QString new_name) {
|
||||
Q_ASSERT(this->contains(old_name));
|
||||
(*this)[new_name] = this->take(old_name);
|
||||
}
|
||||
|
||||
bool serialize(QString path) {
|
||||
QFile f(path);
|
||||
if(f.open(QIODevice::WriteOnly)) {
|
||||
QDataStream out(&f);
|
||||
out.setVersion(QDataStream::Qt_4_3);
|
||||
out << (QHash<QString, QVariant>)(*this);
|
||||
f.close();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool unserialize(QString path) {
|
||||
QFile f(path);
|
||||
if(f.open(QIODevice::ReadOnly)) {
|
||||
QDataStream in(&f);
|
||||
in.setVersion(QDataStream::Qt_4_3);
|
||||
QHash<QString, QVariant> tmp;
|
||||
in >> tmp;
|
||||
qDebug("Unserialized %d filters", tmp.size());
|
||||
foreach(const QString& key, tmp.keys()) {
|
||||
(*this)[key] = tmp[key];
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void save() {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||
qDebug("Saving filters for feed: %s (%d filters)", feed_url.toLocal8Bit().data(), (*this).size());
|
||||
all_feeds_filters[feed_url] = *this;
|
||||
qBTRSS.setValue("feed_filters", all_feeds_filters);
|
||||
}
|
||||
};
|
||||
|
||||
class FeedDownloaderDlg : public QDialog, private Ui_FeedDownloader{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString feed_url;
|
||||
QString feed_name;
|
||||
FeedFilters filters;
|
||||
bittorrent *BTSession;
|
||||
QString selected_filter; // name
|
||||
|
||||
public:
|
||||
FeedDownloaderDlg(QWidget *parent, QString feed_url, QString feed_name, bittorrent* BTSession): QDialog(parent), feed_url(feed_url), feed_name(feed_name), BTSession(BTSession), selected_filter(QString::null){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
Q_ASSERT(!feed_name.isEmpty());
|
||||
rssfeed_lbl->setText(feed_name);
|
||||
filters = FeedFilters::getFeedFilters(feed_url);
|
||||
// Connect Signals/Slots
|
||||
connect(filtersList, SIGNAL(currentItemChanged(QListWidgetItem* , QListWidgetItem *)), this, SLOT(showFilterSettings(QListWidgetItem *)));
|
||||
connect(filtersList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFiltersListMenu(const QPoint&)));
|
||||
connect(actionAdd_filter, SIGNAL(triggered()), this, SLOT(addFilter()));
|
||||
connect(actionRemove_filter, SIGNAL(triggered()), this, SLOT(deleteFilter()));
|
||||
connect(actionRename_filter, SIGNAL(triggered()), this, SLOT(renameFilter()));
|
||||
connect(del_button, SIGNAL(clicked(bool)), this, SLOT(deleteFilter()));
|
||||
connect(add_button, SIGNAL(clicked(bool)), this, SLOT(addFilter()));
|
||||
connect(enableDl_cb, SIGNAL(stateChanged(int)), this, SLOT(enableFilterBox(int)));
|
||||
// Restore saved info
|
||||
enableDl_cb->setChecked(filters.isDownloadingEnabled());
|
||||
fillFiltersList();
|
||||
if(filters.size() > 0) {
|
||||
// Select first filter
|
||||
filtersList->setCurrentItem(filtersList->item(0));
|
||||
//showFilterSettings(filtersList->item(0));
|
||||
}
|
||||
// Show
|
||||
show();
|
||||
}
|
||||
|
||||
~FeedDownloaderDlg() {
|
||||
// Make sure we save everything
|
||||
saveCurrentFilterSettings();
|
||||
filters.save();
|
||||
}
|
||||
|
||||
protected slots:
|
||||
void saveCurrentFilterSettings() {
|
||||
if(!selected_filter.isEmpty()) {
|
||||
FeedFilter filter = filters.getFilter(selected_filter);
|
||||
filter.setMatchingTokens(match_line->text());
|
||||
filter.setNotMatchingTokens(notmatch_line->text());
|
||||
QString save_path = savepath_line->text().trimmed();
|
||||
if(save_path.isEmpty())
|
||||
save_path = BTSession->getDefaultSavePath();
|
||||
filter.setSavePath(save_path);
|
||||
// Save updated filter
|
||||
filters.setFilter(selected_filter, filter);
|
||||
}
|
||||
}
|
||||
|
||||
void fillFiltersList() {
|
||||
// Fill filter list
|
||||
foreach(QString filter_name, filters.names()) {
|
||||
new QListWidgetItem(filter_name, filtersList);
|
||||
}
|
||||
}
|
||||
|
||||
void displayFiltersListMenu(const QPoint&) {
|
||||
QMenu myFiltersListMenu(this);
|
||||
if(filtersList->selectedItems().size() > 0) {
|
||||
myFiltersListMenu.addAction(actionRename_filter);
|
||||
myFiltersListMenu.addAction(actionRemove_filter);
|
||||
} else {
|
||||
myFiltersListMenu.addAction(actionAdd_filter);
|
||||
}
|
||||
// Call menu
|
||||
myFiltersListMenu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void showFilterSettings(QListWidgetItem *item) {
|
||||
// First, save current filter settings
|
||||
saveCurrentFilterSettings();
|
||||
// Clear all fields
|
||||
clearFields();
|
||||
if(!item) {
|
||||
qDebug("No new selected item");
|
||||
return;
|
||||
}
|
||||
// Actually show filter settings
|
||||
QString filter_name = item->text();
|
||||
FeedFilter filter = filters.getFilter(filter_name);
|
||||
filterSettingsBox->setEnabled(true);
|
||||
match_line->setText(filter.getMatchingTokens_str());
|
||||
if(match_line->text().trimmed().isEmpty()) {
|
||||
match_line->setText(filter_name);
|
||||
}
|
||||
notmatch_line->setText(filter.getNotMatchingTokens_str());
|
||||
QString save_path = filter.getSavePath();
|
||||
if(save_path.isEmpty())
|
||||
save_path = BTSession->getDefaultSavePath();
|
||||
savepath_line->setText(save_path);
|
||||
// Update selected filter
|
||||
selected_filter = filter_name;
|
||||
}
|
||||
|
||||
void deleteFilter() {
|
||||
QList<QListWidgetItem *> items = filtersList->selectedItems();
|
||||
if(items.size() == 1) {
|
||||
QListWidgetItem * item = items.first();
|
||||
filters.remove(item->text());
|
||||
selected_filter = QString::null;
|
||||
delete item;
|
||||
// Reset Filter settings view
|
||||
if(filters.size() == 0) {
|
||||
clearFields();
|
||||
filterSettingsBox->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renameFilter() {
|
||||
QList<QListWidgetItem *> items = filtersList->selectedItems();
|
||||
if(items.size() == 1) {
|
||||
QListWidgetItem *item = items.first();
|
||||
QString current_name = item->text();
|
||||
QString new_name;
|
||||
bool validated = false;
|
||||
do {
|
||||
new_name = askFilterName(current_name);
|
||||
if(new_name.isNull() || new_name == current_name) return;
|
||||
if(!filters.hasFilter(new_name)) {
|
||||
validated = true;
|
||||
} else {
|
||||
QMessageBox::critical(0, tr("Invalid filter name"), tr("This filter name is already in use."));
|
||||
}
|
||||
}while(!validated);
|
||||
// Rename the filter
|
||||
filters.rename(current_name, new_name);
|
||||
if(selected_filter == current_name)
|
||||
selected_filter = new_name;
|
||||
item->setText(new_name);
|
||||
}
|
||||
}
|
||||
|
||||
void enableFilterBox(int state) {
|
||||
if(state == Qt::Checked) {
|
||||
filtersBox->setEnabled(true);
|
||||
filters.setDownloadingEnabled(true);
|
||||
} else {
|
||||
filtersBox->setEnabled(false);
|
||||
filters.setDownloadingEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
QString askFilterName(QString name=QString::null) {
|
||||
QString name_prop;
|
||||
if(name.isEmpty())
|
||||
name_prop = tr("New filter");
|
||||
else
|
||||
name_prop = name;
|
||||
QString new_name;
|
||||
bool validated = false;
|
||||
do {
|
||||
bool ok;
|
||||
new_name = QInputDialog::getText(this, tr("Please choose a name for this filter"), tr("Filter name:"), QLineEdit::Normal, name_prop, &ok);
|
||||
if(!ok) {
|
||||
return QString::null;
|
||||
}
|
||||
// Validate filter name
|
||||
new_name = new_name.trimmed();
|
||||
if(new_name.isEmpty()) {
|
||||
// Cannot be left empty
|
||||
QMessageBox::critical(0, tr("Invalid filter name"), tr("The filter name cannot be left empty."));
|
||||
} else {
|
||||
validated = true;
|
||||
}
|
||||
} while(!validated);
|
||||
return new_name;
|
||||
}
|
||||
|
||||
void addFilter() {
|
||||
QString filter_name = QString::null;
|
||||
bool validated = false;
|
||||
do {
|
||||
filter_name = askFilterName();
|
||||
if(filter_name.isNull()) return;
|
||||
if(filters.hasFilter(filter_name)) {
|
||||
// Filter alread exists
|
||||
QMessageBox::critical(0, tr("Invalid filter name"), tr("This filter name is already in use."));
|
||||
} else {
|
||||
validated = true;
|
||||
}
|
||||
}while(!validated);
|
||||
QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList);
|
||||
filtersList->setCurrentItem(it);
|
||||
//showFilterSettings(it);
|
||||
}
|
||||
|
||||
void clearFields() {
|
||||
match_line->clear();
|
||||
notmatch_line->clear();
|
||||
savepath_line->clear();
|
||||
test_res_lbl->setText("");
|
||||
test_line->clear();
|
||||
}
|
||||
|
||||
void on_testButton_clicked(bool) {
|
||||
if(selected_filter.isEmpty()) return;
|
||||
QString s = test_line->text().trimmed();
|
||||
if(s.isEmpty()) {
|
||||
QMessageBox::critical(0, tr("Filter testing error"), tr("Please specify a test torrent name."));
|
||||
return;
|
||||
}
|
||||
// Get current filter
|
||||
saveCurrentFilterSettings();
|
||||
FeedFilter f = filters.getFilter(selected_filter);
|
||||
if(f.matches(s))
|
||||
test_res_lbl->setText("<b><font color=\"green\">"+tr("matches")+"</font></b>");
|
||||
else
|
||||
test_res_lbl->setText("<b><font color=\"red\">"+tr("does not match")+"</font></b>");
|
||||
}
|
||||
|
||||
void on_importButton_clicked(bool) {
|
||||
QString source = QFileDialog::getOpenFileName(0, tr("Select file to import"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)"));
|
||||
if(source.isEmpty()) return;
|
||||
if(filters.unserialize(source)) {
|
||||
// Clean up first
|
||||
clearFields();
|
||||
filtersList->clear();
|
||||
selected_filter = QString::null;
|
||||
fillFiltersList();
|
||||
if(filters.size() > 0)
|
||||
filtersList->setCurrentItem(filtersList->item(0));
|
||||
QMessageBox::information(0, tr("Import successful"), tr("Filters import was successful."));
|
||||
} else {
|
||||
QMessageBox::critical(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error."));
|
||||
}
|
||||
}
|
||||
|
||||
void on_exportButton_clicked(bool) {
|
||||
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination file"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)"));
|
||||
if(destination.isEmpty()) return;
|
||||
// Append file extension
|
||||
if(!destination.endsWith(".filters"))
|
||||
destination += ".filters";
|
||||
if(QFile::exists(destination)) {
|
||||
int ret = QMessageBox::question(0, tr("Overwriting confirmation"), tr("Are you sure you want to overwrite existing file?"));
|
||||
if(ret != QMessageBox::Yes) return;
|
||||
}
|
||||
if(filters.serialize(destination))
|
||||
QMessageBox::information(0, tr("Export successful"), tr("Filters export was successful."));
|
||||
else
|
||||
QMessageBox::critical(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error."));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // FEEDDOWNLOADER_H
|
||||
@@ -1,546 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FeedDownloader</class>
|
||||
<widget class="QDialog" name="FeedDownloader">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>737</width>
|
||||
<height>415</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>RSS Feed downloader</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>RSS feed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rssfeed_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Feed name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableDl_cb">
|
||||
<property name="text">
|
||||
<string>Automatically download torrents from this feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filtersBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Download filters</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filters:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="filtersList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="del_button">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="add_button">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filterSettingsBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Filter settings</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Matches:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Does not match:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Destination folder:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="match_line">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="notmatch_line"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="savepath_line">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="browse_button">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="testerBox">
|
||||
<property name="title">
|
||||
<string>Filter testing</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Torrent title:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Result:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="test_line"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="testButton">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="test_res_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>9</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QPushButton" name="importButton">
|
||||
<property name="text">
|
||||
<string>Import...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportButton">
|
||||
<property name="text">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionRename_filter">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/edit_clear.png</normaloff>:/Icons/oxygen/edit_clear.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rename filter</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Rename filter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRemove_filter">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove filter</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove filter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAdd_filter">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add filter</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>FeedDownloader</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>FeedDownloader</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -44,13 +35,9 @@
|
||||
#define F_NAME 0
|
||||
#define F_SIZE 1
|
||||
#define F_UPSPEED 2
|
||||
#define F_SWARM 3
|
||||
#define F_PEERS 4
|
||||
#define F_UPLOAD 5
|
||||
#define F_RATIO 6
|
||||
#define F_HASH 7
|
||||
|
||||
#define MAX_RATIO 100.
|
||||
#define F_LEECH 3
|
||||
#define F_RATIO 4
|
||||
#define F_HASH 5
|
||||
|
||||
class FinishedListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
@@ -64,7 +51,6 @@ class FinishedListDelegate: public QItemDelegate {
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
switch(index.column()){
|
||||
case F_SIZE:
|
||||
case F_UPLOAD:
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
@@ -77,9 +63,6 @@ class FinishedListDelegate: public QItemDelegate {
|
||||
case F_RATIO:{
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double ratio = index.data().toDouble();
|
||||
if(ratio > MAX_RATIO)
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::fromUtf8("∞"));
|
||||
else
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#include "FinishedTorrents.h"
|
||||
@@ -46,17 +37,13 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
|
||||
setupUi(this);
|
||||
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
|
||||
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
|
||||
finishedListModel = new QStandardItemModel(0,8);
|
||||
finishedListModel = new QStandardItemModel(0,6);
|
||||
finishedListModel->setHeaderData(F_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
finishedListModel->setHeaderData(F_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
finishedListModel->setHeaderData(F_UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
|
||||
finishedListModel->setHeaderData(F_SWARM, Qt::Horizontal, tr("Seeds / Leechers"));
|
||||
finishedListModel->setHeaderData(F_PEERS, Qt::Horizontal, tr("Connected peers"));
|
||||
finishedListModel->setHeaderData(F_UPLOAD, Qt::Horizontal, tr("Total uploaded", "i.e: Total amount of uploaded data"));
|
||||
finishedListModel->setHeaderData(F_LEECH, Qt::Horizontal, tr("Leechers", "i.e: full/partial sources"));
|
||||
finishedListModel->setHeaderData(F_RATIO, Qt::Horizontal, tr("Ratio"));
|
||||
finishedList->setModel(finishedListModel);
|
||||
finishedList->setRootIsDecorated(false);
|
||||
finishedList->setAllColumnsShowFocus(true);
|
||||
loadHiddenColumns();
|
||||
// Hide hash column
|
||||
finishedList->hideColumn(F_HASH);
|
||||
@@ -64,8 +51,6 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
|
||||
if(!loadColWidthFinishedList()){
|
||||
finishedList->header()->resizeSection(0, 200);
|
||||
}
|
||||
// Connect BTSession signals
|
||||
connect(BTSession, SIGNAL(metadataReceived(QTorrentHandle&)), this, SLOT(updateMetadata(QTorrentHandle&)));
|
||||
// Make download list header clickable for sorting
|
||||
finishedList->header()->setClickable(true);
|
||||
finishedList->header()->setSortIndicatorShown(true);
|
||||
@@ -81,8 +66,6 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
|
||||
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
|
||||
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
|
||||
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
|
||||
actionCopy_magnet_link->setIcon(QIcon(QString::fromUtf8(":/Icons/magnet.png")));
|
||||
|
||||
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
|
||||
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
|
||||
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
|
||||
@@ -92,14 +75,11 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
|
||||
connect(actionBuy_it, SIGNAL(triggered()), (GUI*)parent, SLOT(goBuyPage()));
|
||||
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
|
||||
connect(actionForce_recheck, SIGNAL(triggered()), this, SLOT(forceRecheck()));
|
||||
connect(actionCopy_magnet_link, SIGNAL(triggered()), (GUI*)parent, SLOT(copyMagnetURI()));
|
||||
|
||||
connect(actionHOSColName, SIGNAL(triggered()), this, SLOT(hideOrShowColumnName()));
|
||||
connect(actionHOSColSize, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSize()));
|
||||
connect(actionHOSColUpSpeed, SIGNAL(triggered()), this, SLOT(hideOrShowColumnUpSpeed()));
|
||||
connect(actionHOSColSwarm, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSwarm()));
|
||||
connect(actionHOSColPeers, SIGNAL(triggered()), this, SLOT(hideOrShowColumnPeers()));
|
||||
connect(actionHOSColUpload, SIGNAL(triggered()), this, SLOT(hideOrShowColumnUpload()));
|
||||
connect(actionHOSColLeechers, SIGNAL(triggered()), this, SLOT(hideOrShowColumnLeechers()));
|
||||
connect(actionHOSColRatio, SIGNAL(triggered()), this, SLOT(hideOrShowColumnRatio()));
|
||||
}
|
||||
|
||||
@@ -126,9 +106,7 @@ void FinishedTorrents::addTorrent(QString hash){
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SWARM), QVariant("-1/-1"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), QVariant("0"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPLOAD), QVariant((qlonglong)h.all_time_upload()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_LEECH), QVariant("0"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString::fromUtf8(misc::toString(BTSession->getRealRatio(hash)).c_str())));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash));
|
||||
if(h.is_paused()) {
|
||||
@@ -155,8 +133,9 @@ void FinishedTorrents::setRowColor(int row, QString color){
|
||||
|
||||
QStringList FinishedTorrents::getSelectedTorrents(bool only_one) const{
|
||||
QStringList res;
|
||||
QModelIndex index;
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == F_NAME) {
|
||||
// Get the file hash
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
@@ -187,23 +166,6 @@ bool FinishedTorrents::loadColWidthFinishedList(){
|
||||
finishedList->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
loadLastSortedColumn();
|
||||
QVariantList visualIndexes = settings.value(QString::fromUtf8("FinishedListVisualIndexes"), QVariantList()).toList();
|
||||
if(visualIndexes.size() != finishedListModel->columnCount()-1) {
|
||||
qDebug("Corrupted values for download list columns sizes");
|
||||
return false;
|
||||
}
|
||||
bool change = false;
|
||||
do {
|
||||
change = false;
|
||||
for(int i=0;i<visualIndexes.size(); ++i) {
|
||||
int new_visual_index = visualIndexes.at(finishedList->header()->logicalIndex(i)).toInt();
|
||||
if(i != new_visual_index) {
|
||||
qDebug("Moving column from %d to %d", finishedList->header()->logicalIndex(i), new_visual_index);
|
||||
finishedList->header()->moveSection(i, new_visual_index);
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}while(change);
|
||||
qDebug("Finished list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
@@ -238,7 +200,7 @@ void FinishedTorrents::saveColWidthFinishedList() const{
|
||||
width_list = line.split(' ');
|
||||
}
|
||||
for(short i=0; i<nbColumns; ++i){
|
||||
if(finishedList->columnWidth(i)<1 && width_list.size() == nbColumns && width_list.at(i).toInt()>=1) {
|
||||
if(finishedList->columnWidth(i)<1 && width_list.size() == finishedListModel->columnCount()-1 && width_list.at(i).toInt()>=1) {
|
||||
// load the former width
|
||||
new_width_list << width_list.at(i);
|
||||
} else if(finishedList->columnWidth(i)>=1) {
|
||||
@@ -251,18 +213,14 @@ void FinishedTorrents::saveColWidthFinishedList() const{
|
||||
}
|
||||
}
|
||||
settings.setValue("FinishedListColsWidth", new_width_list.join(" "));
|
||||
QVariantList visualIndexes;
|
||||
for(int i=0; i<nbColumns; ++i) {
|
||||
visualIndexes.append(finishedList->header()->visualIndex(i));
|
||||
}
|
||||
settings.setValue(QString::fromUtf8("FinishedListVisualIndexes"), visualIndexes);
|
||||
qDebug("Finished list columns width saved");
|
||||
}
|
||||
|
||||
void FinishedTorrents::on_actionSet_upload_limit_triggered(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
QStringList hashes;
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
// Get the file hash
|
||||
hashes << finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
@@ -271,18 +229,7 @@ void FinishedTorrents::on_actionSet_upload_limit_triggered(){
|
||||
new BandwidthAllocationDialog(this, true, BTSession, hashes);
|
||||
}
|
||||
|
||||
void FinishedTorrents::updateMetadata(QTorrentHandle &h) {
|
||||
QString hash = h.hash();
|
||||
int row = getRowFromHash(hash);
|
||||
if(row != -1) {
|
||||
qDebug("Updating torrent metadata in download list");
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::updateTorrent(QTorrentHandle h) {
|
||||
if(!h.is_valid()) return;
|
||||
QString hash = h.hash();
|
||||
int row = getRowFromHash(hash);
|
||||
if(row == -1){
|
||||
@@ -291,25 +238,22 @@ void FinishedTorrents::updateTorrent(QTorrentHandle h) {
|
||||
row = getRowFromHash(hash);
|
||||
}
|
||||
Q_ASSERT(row != -1);
|
||||
if(!finishedList->isColumnHidden(F_SWARM)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SWARM), misc::toQString(h.num_complete())+QString("/")+misc::toQString(h.num_incomplete()));
|
||||
}
|
||||
if(h.is_paused()) return;
|
||||
// Update queued torrent
|
||||
if(BTSession->isQueueingEnabled() && h.is_queued()) {
|
||||
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking){
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
} else {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
|
||||
}
|
||||
// Reset upload speed and seeds/leech
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), 0.);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), "0");
|
||||
finishedListModel->setData(finishedListModel->index(row, F_LEECH), "0");
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
return;
|
||||
}
|
||||
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking){
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
return;
|
||||
}
|
||||
@@ -318,11 +262,8 @@ void FinishedTorrents::updateTorrent(QTorrentHandle h) {
|
||||
if(!finishedList->isColumnHidden(F_UPSPEED)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate()));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_PEERS)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), misc::toQString(h.num_peers() - h.num_seeds(), true));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_UPLOAD)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPLOAD), QVariant((double)h.all_time_upload()));
|
||||
if(!finishedList->isColumnHidden(F_LEECH)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_LEECH), misc::toQString(h.num_peers() - h.num_seeds(), true));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_RATIO)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
|
||||
@@ -346,7 +287,7 @@ void FinishedTorrents::pauseTorrent(QString hash) {
|
||||
return;
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.0));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), QVariant(QString::fromUtf8("0")));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_LEECH), QVariant(QString::fromUtf8("0")));
|
||||
setRowColor(row, QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
@@ -389,7 +330,8 @@ void FinishedTorrents::updateFileSize(QString hash){
|
||||
// display properties of selected items
|
||||
void FinishedTorrents::propertiesSelection(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
showProperties(index);
|
||||
}
|
||||
@@ -398,22 +340,23 @@ void FinishedTorrents::propertiesSelection(){
|
||||
|
||||
void FinishedTorrents::forceRecheck(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
qDebug("Forcing recheck for torrent %s", hash.toLocal8Bit().data());
|
||||
h.force_recheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::displayFinishedListMenu(const QPoint&){
|
||||
void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
|
||||
QMenu myFinishedListMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
bool has_pause = false, has_start = false, has_preview = false;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == F_NAME) {
|
||||
// Get the file name
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
@@ -449,11 +392,11 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint&){
|
||||
myFinishedListMenu.addAction(actionOpen_destination_folder);
|
||||
myFinishedListMenu.addAction(actionTorrent_Properties);
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionCopy_magnet_link);
|
||||
myFinishedListMenu.addAction(actionBuy_it);
|
||||
|
||||
// Call menu
|
||||
myFinishedListMenu.exec(QCursor::pos());
|
||||
// XXX: why mapToGlobal() is not enough?
|
||||
myFinishedListMenu.exec(mapToGlobal(pos)+QPoint(10,58));
|
||||
}
|
||||
|
||||
|
||||
@@ -488,12 +431,12 @@ void FinishedTorrents::hideOrShowColumn(int index) {
|
||||
if(nbVisibleColumns <= 1) return;
|
||||
// User can hide the column, do it.
|
||||
finishedList->setColumnHidden(index, true);
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
--nbVisibleColumns;
|
||||
} else {
|
||||
// User want to display the column
|
||||
finishedList->setColumnHidden(index, false);
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
++nbVisibleColumns;
|
||||
}
|
||||
//resize all others non-hidden columns
|
||||
@@ -516,16 +459,8 @@ void FinishedTorrents::hideOrShowColumnUpSpeed() {
|
||||
hideOrShowColumn(F_UPSPEED);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnSwarm() {
|
||||
hideOrShowColumn(F_SWARM);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnPeers() {
|
||||
hideOrShowColumn(F_PEERS);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnUpload() {
|
||||
hideOrShowColumn(F_UPLOAD);
|
||||
void FinishedTorrents::hideOrShowColumnLeechers() {
|
||||
hideOrShowColumn(F_LEECH);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnRatio() {
|
||||
@@ -551,9 +486,9 @@ bool FinishedTorrents::loadHiddenColumns() {
|
||||
for(int i=0; i<finishedListModel->columnCount()-1; i++) {
|
||||
if(loaded && ishidden_list.at(i) == "0") {
|
||||
finishedList->setColumnHidden(i, true);
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
} else {
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
@@ -587,14 +522,8 @@ QAction* FinishedTorrents::getActionHoSCol(int index) {
|
||||
case F_UPSPEED :
|
||||
return actionHOSColUpSpeed;
|
||||
break;
|
||||
case F_SWARM :
|
||||
return actionHOSColSwarm;
|
||||
break;
|
||||
case F_PEERS :
|
||||
return actionHOSColPeers;
|
||||
break;
|
||||
case F_UPLOAD :
|
||||
return actionHOSColUpload;
|
||||
case F_LEECH :
|
||||
return actionHOSColLeechers;
|
||||
break;
|
||||
case F_RATIO :
|
||||
return actionHOSColRatio;
|
||||
@@ -618,7 +547,6 @@ void FinishedTorrents::toggleFinishedListSortOrder(int index) {
|
||||
case F_SIZE:
|
||||
case F_UPSPEED:
|
||||
case F_RATIO:
|
||||
case F_UPLOAD:
|
||||
sortFinishedListFloat(index, sortOrder);
|
||||
break;
|
||||
default:
|
||||
@@ -643,8 +571,6 @@ void FinishedTorrents::sortFinishedList(int index, Qt::SortOrder sortOrder){
|
||||
switch(index) {
|
||||
case F_SIZE:
|
||||
case F_UPSPEED:
|
||||
case F_UPLOAD:
|
||||
case F_RATIO:
|
||||
sortFinishedListFloat(index, sortOrder);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -79,9 +70,7 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
|
||||
void hideOrShowColumnName();
|
||||
void hideOrShowColumnSize();
|
||||
void hideOrShowColumnUpSpeed();
|
||||
void hideOrShowColumnSwarm();
|
||||
void hideOrShowColumnPeers();
|
||||
void hideOrShowColumnUpload();
|
||||
void hideOrShowColumnLeechers();
|
||||
void hideOrShowColumnRatio();
|
||||
void forceRecheck();
|
||||
|
||||
@@ -93,7 +82,6 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
|
||||
void deleteTorrent(QString hash);
|
||||
void showPropertiesFromHash(QString hash);
|
||||
void loadLastSortedColumn();
|
||||
void updateMetadata(QTorrentHandle &h);
|
||||
|
||||
signals:
|
||||
void torrentMovedFromFinishedList(QString);
|
||||
|
||||
185
src/GUI.cpp
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#include <QFileDialog>
|
||||
@@ -34,7 +25,6 @@
|
||||
#include <QDesktopServices>
|
||||
#include <QStatusBar>
|
||||
#include <QFrame>
|
||||
#include <QClipboard>
|
||||
#ifdef QT_4_4
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
@@ -68,7 +58,6 @@
|
||||
#include <stdlib.h>
|
||||
#include "console_imp.h"
|
||||
#include "httpserver.h"
|
||||
#include "torrentPersistentData.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
@@ -101,14 +90,14 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
qDebug("Info: System tray unavailable");
|
||||
}
|
||||
// Setting icons
|
||||
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png")));
|
||||
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent32.png")));
|
||||
actionOpen->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/open.png")));
|
||||
actionExit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/exit.png")));
|
||||
actionDownload_from_URL->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/url.png")));
|
||||
actionOptions->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/settings.png")));
|
||||
actionAbout->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/info.png")));
|
||||
actionWebsite->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png")));
|
||||
actionBugReport->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/bug.png")));
|
||||
actionWebsite->setIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent32.png")));
|
||||
actionBugReport->setIcon(QIcon(QString::fromUtf8(":/Icons/newmsg.png")));
|
||||
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
|
||||
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
|
||||
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
|
||||
@@ -134,7 +123,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
options = new options_imp(this);
|
||||
connect(options, SIGNAL(status_changed(bool)), this, SLOT(OptionsSaved(bool)));
|
||||
BTSession = new bittorrent();
|
||||
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&, QString)), this, SLOT(fullDiskError(QTorrentHandle&, QString)));
|
||||
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&)), this, SLOT(fullDiskError(QTorrentHandle&)));
|
||||
connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&)));
|
||||
connect(BTSession, SIGNAL(addedTorrent(QTorrentHandle&)), this, SLOT(addedTorrent(QTorrentHandle&)));
|
||||
connect(BTSession, SIGNAL(pausedTorrent(QTorrentHandle&)), this, SLOT(pausedTorrent(QTorrentHandle&)));
|
||||
@@ -144,7 +133,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString)));
|
||||
connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
|
||||
connect(BTSession, SIGNAL(deletedTorrent(QString)), this, SLOT(deleteTorrent(QString)));
|
||||
connect(BTSession, SIGNAL(torrentPaused(QTorrentHandle&)), this, SLOT(setPaused(QTorrentHandle&)));
|
||||
qDebug("create tabWidget");
|
||||
tabs = new QTabWidget();
|
||||
// Download torrents tab
|
||||
@@ -174,7 +162,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
// Configure BT session according to options
|
||||
configureSession(true);
|
||||
// Resume unfinished torrents
|
||||
BTSession->startUpTorrents();
|
||||
BTSession->resumeUnfinishedTorrents();
|
||||
downloadingTorrentTab->loadLastSortedColumn();
|
||||
finishedTorrentTab->loadLastSortedColumn();
|
||||
// Add torrent given on command line
|
||||
@@ -252,9 +240,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
if(!settings.value(QString::fromUtf8("Preferences/General/StartMinimized"), false).toBool()) {
|
||||
show();
|
||||
}
|
||||
scrapeTimer = new QTimer(this);
|
||||
connect(scrapeTimer, SIGNAL(timeout()), this, SLOT(scrapeTrackers()));
|
||||
scrapeTimer->start(20000);
|
||||
qDebug("GUI Built");
|
||||
}
|
||||
|
||||
@@ -266,8 +251,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
BTSession->saveDHTEntry();
|
||||
BTSession->saveSessionState();
|
||||
BTSession->saveFastResumeData();
|
||||
scrapeTimer->stop();
|
||||
delete scrapeTimer;
|
||||
delete dlSpeedLbl;
|
||||
delete upSpeedLbl;
|
||||
delete ratioLbl;
|
||||
@@ -315,7 +298,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
if(enable) {
|
||||
// RSS tab
|
||||
if(rssWidget == 0) {
|
||||
rssWidget = new RSSImp(BTSession);
|
||||
rssWidget = new RSSImp();
|
||||
tabs->addTab(rssWidget, tr("RSS"));
|
||||
tabs->setTabIcon(3, QIcon(QString::fromUtf8(":/Icons/rss32.png")));
|
||||
}
|
||||
@@ -327,16 +310,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::scrapeTrackers() {
|
||||
std::vector<torrent_handle> torrents = BTSession->getTorrents();
|
||||
std::vector<torrent_handle>::iterator torrentIT;
|
||||
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
||||
if(!h.is_valid()) continue;
|
||||
h.scrape_tracker();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::updateRatio() {
|
||||
// Update ratio info
|
||||
float ratio = 1.;
|
||||
@@ -381,7 +354,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
qDebug("In GUI, a torrent has finished");
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
bool show_msg = true;
|
||||
if(TorrentPersistentData::isSeed(h.hash()))
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished"))
|
||||
show_msg = false;
|
||||
QString fileName = h.name();
|
||||
bool useNotificationBalloons = settings.value(QString::fromUtf8("Preferences/General/NotificationBaloons"), true).toBool();
|
||||
@@ -427,8 +400,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
finishedTorrentTab->addTorrent(h.hash());
|
||||
} else {
|
||||
// Move torrent back to download list (if necessary)
|
||||
if(TorrentPersistentData::isSeed(h.hash())) {
|
||||
TorrentPersistentData::saveSeedStatus(h);
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished")) {
|
||||
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished");
|
||||
finishedTorrentTab->deleteTorrent(h.hash());
|
||||
downloadingTorrentTab->addTorrent(h.hash());
|
||||
}
|
||||
@@ -436,29 +409,23 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
|
||||
// Notification when disk is full
|
||||
void GUI::fullDiskError(QTorrentHandle& h, QString msg) const {
|
||||
void GUI::fullDiskError(QTorrentHandle& h) const {
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
bool useNotificationBalloons = settings.value(QString::fromUtf8("Preferences/General/NotificationBaloons"), true).toBool();
|
||||
if(systrayIntegration && useNotificationBalloons) {
|
||||
myTrayIcon->showMessage(tr("I/O Error", "i.e: Input/Output Error"), tr("An I/O error occured for torrent %1.\n Reason: %2", "e.g: An error occured for torrent xxx.avi.\n Reason: disk is full.").arg(h.name()).arg(msg), QSystemTrayIcon::Critical, TIME_TRAY_BALLOON);
|
||||
myTrayIcon->showMessage(tr("I/O Error", "i.e: Input/Output Error"), tr("An error occured when trying to read or write %1. The disk is probably full, download has been paused", "e.g: An error occured when trying to read or write xxx.avi. The disk is probably full, download has been paused").arg(h.name()), QSystemTrayIcon::Critical, TIME_TRAY_BALLOON);
|
||||
}
|
||||
// Download will be paused by libtorrent. Updating GUI information accordingly
|
||||
QString hash = h.hash();
|
||||
qDebug("Full disk error, pausing torrent %s", hash.toLocal8Bit().data());
|
||||
setPaused(h);
|
||||
BTSession->addConsoleMessage(tr("An error occured (full disk?), '%1' paused.", "e.g: An error occured (full disk?), 'xxx.avi' paused.").arg(h.name()));
|
||||
}
|
||||
|
||||
void GUI::setPaused(QTorrentHandle &h) const {
|
||||
if(!h.is_paused()) return;
|
||||
qDebug("Marking torrent %s as paused", h.hash().toLocal8Bit().data());
|
||||
qDebug("Full disk error, pausing torrent %s", hash.toUtf8().data());
|
||||
if(h.is_seed()) {
|
||||
// In finished list
|
||||
qDebug("Automatically paused torrent was in finished list");
|
||||
finishedTorrentTab->pauseTorrent(h.hash());
|
||||
finishedTorrentTab->pauseTorrent(hash);
|
||||
}else{
|
||||
downloadingTorrentTab->pauseTorrent(h.hash());
|
||||
downloadingTorrentTab->pauseTorrent(hash);
|
||||
}
|
||||
BTSession->addConsoleMessage(tr("An error occured (full disk?), '%1' paused.", "e.g: An error occured (full disk?), 'xxx.avi' paused.").arg(h.name()));
|
||||
}
|
||||
|
||||
void GUI::createKeyboardShortcuts() {
|
||||
@@ -588,8 +555,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
default:
|
||||
return;
|
||||
}
|
||||
QString hash;
|
||||
QStringList pathsList;
|
||||
foreach(const QString &hash, hashes) {
|
||||
foreach(hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
QString savePath = h.save_path();
|
||||
if(!pathsList.contains(savePath)) {
|
||||
@@ -599,28 +567,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::copyMagnetURI() const {
|
||||
QStringList hashes;
|
||||
switch(tabs->currentIndex()){
|
||||
case 0:
|
||||
hashes = downloadingTorrentTab->getSelectedTorrents();
|
||||
break;
|
||||
case 1:
|
||||
hashes = finishedTorrentTab->getSelectedTorrents();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
QStringList magnet_uris;
|
||||
foreach(QString hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid()) {
|
||||
magnet_uris << misc::toQString(make_magnet_uri(h.get_torrent_info()));
|
||||
}
|
||||
}
|
||||
qApp->clipboard()->setText(magnet_uris.join("\n"));
|
||||
}
|
||||
|
||||
void GUI::goBuyPage() const {
|
||||
QStringList hashes;
|
||||
switch(tabs->currentIndex()){
|
||||
@@ -633,8 +579,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
default:
|
||||
return;
|
||||
}
|
||||
QString hash;
|
||||
QStringList pathsList;
|
||||
foreach(const QString &hash, hashes) {
|
||||
foreach(hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
QDesktopServices::openUrl("http://match.sharemonkey.com/?info_hash="+hash+"&n="+h.name()+"&cid=33");
|
||||
}
|
||||
@@ -716,8 +663,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool();
|
||||
if(!force_exit && systrayIntegration && goToSystrayOnExit && !this->isHidden()) {
|
||||
hide();
|
||||
//e->ignore();
|
||||
e->accept();
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
if(settings.value(QString::fromUtf8("Preferences/General/ExitConfirm"), true).toBool() && downloadingTorrentTab->getNbTorrentsInList()) {
|
||||
@@ -775,8 +721,10 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
QStringList files;
|
||||
if(event->mimeData()->hasUrls()) {
|
||||
QList<QUrl> urls = event->mimeData()->urls();
|
||||
foreach(const QUrl &url, urls) {
|
||||
QString tmp = url.toString().trimmed();
|
||||
QUrl url;
|
||||
foreach(url, urls) {
|
||||
QString tmp = url.toString();
|
||||
tmp.trimmed();
|
||||
if(!tmp.isEmpty())
|
||||
files << url.toString();
|
||||
}
|
||||
@@ -784,20 +732,16 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
files = event->mimeData()->text().split(QString::fromUtf8("\n"));
|
||||
}
|
||||
// Add file to download list
|
||||
QString file;
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
foreach(QString file, files) {
|
||||
foreach(file, files) {
|
||||
file = file.trimmed().replace(QString::fromUtf8("file://"), QString::fromUtf8(""), Qt::CaseInsensitive);
|
||||
qDebug("Dropped file %s on download list", file.toLocal8Bit().data());
|
||||
qDebug("Dropped file %s on download list", file.toUtf8().data());
|
||||
if(file.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
BTSession->downloadFromUrl(file);
|
||||
continue;
|
||||
}
|
||||
if(file.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
// FIXME: Possibly skipped torrent addition dialog
|
||||
BTSession->addMagnetUri(file);
|
||||
continue;
|
||||
}
|
||||
if(useTorrentAdditionDialog) {
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
|
||||
dialog->showLoad(file);
|
||||
@@ -809,8 +753,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
|
||||
// Decode if we accept drag 'n drop or not
|
||||
void GUI::dragEnterEvent(QDragEnterEvent *event) {
|
||||
foreach(const QString &mime, event->mimeData()->formats()){
|
||||
qDebug("mimeData: %s", mime.toLocal8Bit().data());
|
||||
QString mime;
|
||||
foreach(mime, event->mimeData()->formats()){
|
||||
qDebug("mimeData: %s", mime.toUtf8().data());
|
||||
}
|
||||
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
|
||||
event->acceptProposedAction();
|
||||
@@ -883,7 +828,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
if(ret) return;
|
||||
//User clicked YES
|
||||
foreach(const QString &hash, hashes) {
|
||||
QString hash;
|
||||
foreach(hash, hashes) {
|
||||
// Get the file name
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
QString fileName = h.name();
|
||||
@@ -935,7 +881,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
if(ret) return;
|
||||
//User clicked YES
|
||||
foreach(const QString &hash, hashes) {
|
||||
QString hash;
|
||||
foreach(hash, hashes) {
|
||||
// Get the file name
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
QString fileName = h.name();
|
||||
@@ -949,16 +896,13 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
// the right addTorrent function, considering
|
||||
// the parameter type.
|
||||
void GUI::processParams(const QStringList& params) {
|
||||
QString param;
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
foreach(QString param, params) {
|
||||
foreach(param, params) {
|
||||
param = param.trimmed();
|
||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
BTSession->downloadFromUrl(param);
|
||||
}else{
|
||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
// FIXME: Possibily skipped torrent addition dialog
|
||||
BTSession->addMagnetUri(param);
|
||||
}else{
|
||||
if(useTorrentAdditionDialog) {
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
|
||||
@@ -969,7 +913,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::addTorrent(QString path) {
|
||||
BTSession->addTorrent(path);
|
||||
@@ -996,12 +939,14 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION)));
|
||||
}
|
||||
displaySpeedInTitle = new_displaySpeedInTitle;
|
||||
if(options->isToolbarDisplayed() != toolBar->isVisible()) {
|
||||
if(options->isToolbarDisplayed()) {
|
||||
toolBar->setVisible(true);
|
||||
toolBar->layout()->setSpacing(7);
|
||||
} else {
|
||||
toolBar->setVisible(false);
|
||||
}
|
||||
}
|
||||
unsigned int new_refreshInterval = options->getRefreshInterval();
|
||||
if(refreshInterval != new_refreshInterval) {
|
||||
refreshInterval = new_refreshInterval;
|
||||
@@ -1010,11 +955,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
// Downloads
|
||||
// * Save path
|
||||
BTSession->setDefaultSavePath(options->getSavePath());
|
||||
if(options->isTempPathEnabled()) {
|
||||
BTSession->setDefaultTempPath(options->getTempPath());
|
||||
} else {
|
||||
BTSession->setDefaultTempPath(QString::null);
|
||||
}
|
||||
BTSession->preAllocateAllFiles(options->preAllocateAllFiles());
|
||||
BTSession->startTorrentsInPause(options->addTorrentsInPause());
|
||||
// * Scan dir
|
||||
@@ -1030,7 +970,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
BTSession->setListeningPortsRange(options->getPorts());
|
||||
unsigned short new_listenPort = BTSession->getListenPort();
|
||||
if(new_listenPort != old_listenPort) {
|
||||
BTSession->addConsoleMessage(tr("qBittorrent is bound to port: TCP/%1", "e.g: qBittorrent is bound to port: 6881").arg( misc::toQString(new_listenPort)));
|
||||
BTSession->addConsoleMessage(tr("qBittorrent is bind to port: %1", "e.g: qBittorrent is bind to port: 1666").arg( misc::toQString(new_listenPort)));
|
||||
}
|
||||
// * Global download limit
|
||||
QPair<int, int> limits = options->getGlobalBandwidthLimits();
|
||||
@@ -1074,8 +1014,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
sessionSettings.upnp_ignore_nonrouters = true;
|
||||
sessionSettings.use_dht_as_fallback = false;
|
||||
// To keep same behavior as in qbittorrent v1.2.0
|
||||
sessionSettings.rate_limit_ip_overhead = false;
|
||||
// Queueing System
|
||||
if(options->isQueueingSystemEnabled()) {
|
||||
if(!BTSession->isQueueingEnabled()) {
|
||||
@@ -1119,12 +1057,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
// * DHT
|
||||
if(options->isDHTEnabled()) {
|
||||
// Set DHT Port
|
||||
BTSession->setDHTPort(options->getDHTPort());
|
||||
BTSession->setDHTPort(new_listenPort);
|
||||
if(BTSession->enableDHT(true)) {
|
||||
int dht_port = new_listenPort;
|
||||
if(options->getDHTPort())
|
||||
dht_port = options->getDHTPort();
|
||||
BTSession->addConsoleMessage(tr("DHT support [ON], port: UDP/%1").arg(dht_port), QString::fromUtf8("blue"));
|
||||
BTSession->addConsoleMessage(tr("DHT support [ON], port: %1").arg(new_listenPort), QString::fromUtf8("blue"));
|
||||
} else {
|
||||
BTSession->addConsoleMessage(tr("DHT support [OFF]"), QString::fromUtf8("red"));
|
||||
}
|
||||
@@ -1234,11 +1169,11 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
// We need this for urllib in search engine plugins
|
||||
#ifdef Q_WS_WIN
|
||||
char proxystr[512];
|
||||
snprintf(proxystr, 512, "http_proxy=%s", proxy_str.toLocal8Bit().data());
|
||||
snprintf(proxystr, 512, "http_proxy=%s", proxy_str.toUtf8().data());
|
||||
putenv(proxystr);
|
||||
#else
|
||||
qDebug("HTTP: proxy string: %s", proxy_str.toLocal8Bit().data());
|
||||
setenv("http_proxy", proxy_str.toLocal8Bit().data(), 1);
|
||||
qDebug("HTTP: proxy string: %s", proxy_str.toUtf8().data());
|
||||
setenv("http_proxy", proxy_str.toUtf8().data(), 1);
|
||||
#endif
|
||||
} else {
|
||||
qDebug("Disabling search proxy");
|
||||
@@ -1347,7 +1282,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
if(tabs->currentIndex() != 0)
|
||||
return;
|
||||
QStringList hashes = downloadingTorrentTab->getSelectedTorrents();
|
||||
foreach(const QString &hash, hashes) {
|
||||
foreach(QString hash, hashes) {
|
||||
BTSession->increaseDlTorrentPriority(hash);
|
||||
}
|
||||
updateLists();
|
||||
@@ -1356,7 +1291,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
void GUI::on_actionDecreasePriority_triggered() {
|
||||
Q_ASSERT(tabs->currentIndex() == 0);
|
||||
QStringList hashes = downloadingTorrentTab->getSelectedTorrents();
|
||||
foreach(const QString &hash, hashes) {
|
||||
foreach(QString hash, hashes) {
|
||||
BTSession->decreaseDlTorrentPriority(hash);
|
||||
}
|
||||
updateLists();
|
||||
@@ -1374,8 +1309,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
} else {
|
||||
hashes = finishedTorrentTab->getSelectedTorrents();
|
||||
}
|
||||
qDebug("nb hashes: %d", hashes.size());
|
||||
foreach(const QString &hash, hashes) {
|
||||
QString hash;
|
||||
foreach(hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_paused()){
|
||||
h.pause();
|
||||
@@ -1419,7 +1354,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
} else {
|
||||
hashes = finishedTorrentTab->getSelectedTorrents();
|
||||
}
|
||||
foreach(const QString &hash, hashes) {
|
||||
QString hash;
|
||||
foreach(hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_paused()){
|
||||
h.resume();
|
||||
@@ -1462,7 +1398,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
||||
if(!h.is_valid()) continue;
|
||||
try {
|
||||
if(h.is_seed()) {
|
||||
// Update in finished list
|
||||
finishedTorrentTab->updateTorrent(h);
|
||||
@@ -1471,12 +1406,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
if(downloadingTorrentTab->updateTorrent(h)) {
|
||||
// Torrent was added, we may need to remove it from finished tab
|
||||
finishedTorrentTab->deleteTorrent(h.hash());
|
||||
TorrentPersistentData::saveSeedStatus(h);
|
||||
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished");
|
||||
}
|
||||
}
|
||||
} catch(invalid_handle e) {
|
||||
qDebug("Caught Invalid handle exception, lucky us.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(displaySpeedInTitle) {
|
||||
@@ -1536,14 +1468,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
* *
|
||||
*****************************************************/
|
||||
|
||||
void GUI::downloadFromURLList(const QStringList& url_list) {
|
||||
foreach(const QString url, url_list) {
|
||||
if(url.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
BTSession->addMagnetUri(url);
|
||||
} else {
|
||||
BTSession->downloadFromUrl(url);
|
||||
}
|
||||
}
|
||||
void GUI::downloadFromURLList(const QStringList& urls) {
|
||||
BTSession->downloadFromURLList(urls);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
@@ -1576,10 +1502,10 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
void GUI::createTrayIcon() {
|
||||
// Tray icon
|
||||
#ifdef Q_WS_WIN
|
||||
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent16.png")), this);
|
||||
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent16.png")), this);
|
||||
#endif
|
||||
#ifndef Q_WS_WIN
|
||||
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")), this);
|
||||
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent22.png")), this);
|
||||
#endif
|
||||
// Tray icon Menu
|
||||
myTrayIconMenu = new QMenu(this);
|
||||
@@ -1661,4 +1587,3 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
downloadFromURL *downloadFromURLDialog = new downloadFromURL(this);
|
||||
connect(downloadFromURLDialog, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), BTSession, SLOT(downloadFromURLList(const QStringList&)));
|
||||
}
|
||||
|
||||
|
||||
15
src/GUI.h
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -70,7 +61,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
// Bittorrent
|
||||
bittorrent *BTSession;
|
||||
QTimer *checkConnect;
|
||||
QTimer *scrapeTimer;
|
||||
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
|
||||
// GUI related
|
||||
QTabWidget *tabs;
|
||||
@@ -140,10 +130,9 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
void createTrayIcon();
|
||||
void updateUnfinishedTorrentNumber(unsigned int nb);
|
||||
void updateFinishedTorrentNumber(unsigned int nb);
|
||||
void fullDiskError(QTorrentHandle& h, QString msg) const;
|
||||
void fullDiskError(QTorrentHandle& h) const;
|
||||
void handleDownloadFromUrlFailure(QString, QString) const;
|
||||
void createSystrayDelayed();
|
||||
void setPaused(QTorrentHandle &h) const;
|
||||
// Keyboard shortcuts
|
||||
void createKeyboardShortcuts();
|
||||
void displayDownTab() const;
|
||||
@@ -179,7 +168,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
bool initWebUi(QString username, QString password, int port);
|
||||
void on_actionIncreasePriority_triggered();
|
||||
void on_actionDecreasePriority_triggered();
|
||||
void scrapeTrackers();
|
||||
// Options slots
|
||||
void on_actionOptions_triggered();
|
||||
void OptionsSaved(bool deleteOptions);
|
||||
@@ -192,7 +180,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
void setTabText(int index, QString text) const;
|
||||
void openDestinationFolder() const;
|
||||
void goBuyPage() const;
|
||||
void copyMagnetURI() const;
|
||||
void updateRatio();
|
||||
|
||||
protected:
|
||||
|
||||
BIN
src/Icons/bt_settings.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Icons/button_cancel.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/Icons/button_ok.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/Icons/configure.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/Icons/connection.png
Normal file
|
After Width: | Height: | Size: 820 B |
BIN
src/Icons/description.png
Normal file
|
After Width: | Height: | Size: 821 B |
BIN
src/Icons/download.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 575 B After Width: | Height: | Size: 575 B |
|
Before Width: | Height: | Size: 750 B After Width: | Height: | Size: 750 B |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 704 B |
BIN
src/Icons/filter.png
Normal file
|
After Width: | Height: | Size: 998 B |
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
BIN
src/Icons/gear.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Icons/home.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/log.png
Normal file
|
After Width: | Height: | Size: 846 B |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
BIN
src/Icons/newmsg.png
Normal file
|
After Width: | Height: | Size: 532 B |
|
Before Width: | Height: | Size: 796 B |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 733 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 860 B |
|
Before Width: | Height: | Size: 892 B |
|
Before Width: | Height: | Size: 937 B |
|
Before Width: | Height: | Size: 885 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 907 B |
|
Before Width: | Height: | Size: 498 B |
|
Before Width: | Height: | Size: 541 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 752 B |
|
Before Width: | Height: | Size: 813 B |
|
Before Width: | Height: | Size: 1.5 KiB |
BIN
src/Icons/password.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
src/Icons/proxy.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Network;P2P
|
||||
Comment=V1.5.0
|
||||
Comment=V1.3.0
|
||||
Exec=qbittorrent %f
|
||||
GenericName=Bittorrent client
|
||||
GenericName[bg]=Торент клиент
|
||||
|
||||
|
Before Width: | Height: | Size: 965 B After Width: | Height: | Size: 965 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
src/Icons/skin/add.png
Normal file
|
After Width: | Height: | Size: 842 B |
BIN
src/Icons/skin/remove.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
BIN
src/Icons/star.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/Icons/style.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/Icons/subscribe.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Icons/subscribe16.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
src/Icons/systemtray.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 856 B After Width: | Height: | Size: 856 B |
BIN
src/Icons/unavailable.png
Normal file
|
After Width: | Height: | Size: 888 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 765 B After Width: | Height: | Size: 765 B |
|
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 629 B |
BIN
src/Icons/wizard.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0" >
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow" >
|
||||
@@ -25,7 +24,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>914</width>
|
||||
<height>23</height>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_Edit" >
|
||||
@@ -122,6 +121,7 @@
|
||||
<addaction name="actionIncreasePriority" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionExit" />
|
||||
<addaction name="separator" />
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar" />
|
||||
<action name="actionOpen" >
|
||||
@@ -236,8 +236,7 @@
|
||||
</action>
|
||||
<action name="actionDecreasePriority" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/skin/decrease.png</normaloff>:/Icons/skin/decrease.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/decrease.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Decrease priority</string>
|
||||
@@ -248,8 +247,7 @@
|
||||
</action>
|
||||
<action name="actionIncreasePriority" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/skin/increase.png</normaloff>:/Icons/skin/increase.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/increase.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Increase priority</string>
|
||||
@@ -260,8 +258,7 @@
|
||||
</action>
|
||||
<action name="actionShow_console" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/log.png</normaloff>:/Icons/oxygen/log.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Console</string>
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -56,14 +47,13 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget()
|
||||
|
||||
setLayout(box);
|
||||
// Set Search results list model
|
||||
SearchListModel = new QStandardItemModel(0,6);
|
||||
SearchListModel = new QStandardItemModel(0,5);
|
||||
SearchListModel->setHeaderData(SEARCH_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
SearchListModel->setHeaderData(SEARCH_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
SearchListModel->setHeaderData(SEARCH_SEEDERS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_LEECHERS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_ENGINE, Qt::Horizontal, tr("Search engine"));
|
||||
resultsBrowser->setModel(SearchListModel);
|
||||
resultsBrowser->hideColumn(URL_COLUMN); // Hide url column
|
||||
SearchDelegate = new SearchListDelegate();
|
||||
resultsBrowser->setItemDelegate(SearchDelegate);
|
||||
// Make search list header clickable for sorting
|
||||
@@ -75,36 +65,19 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget()
|
||||
connect(resultsBrowser->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortSearchList(int)));
|
||||
|
||||
// Load last columns width for search results list
|
||||
if(!loadColWidthResultsList()){
|
||||
if(!loadColWidthSearchList()){
|
||||
resultsBrowser->header()->resizeSection(0, 275);
|
||||
}
|
||||
}
|
||||
|
||||
SearchTab::~SearchTab() {
|
||||
SearchTab::~SearchTab()
|
||||
{
|
||||
saveColWidthSearchList();
|
||||
delete resultsBrowser;
|
||||
delete SearchListModel;
|
||||
delete SearchDelegate;
|
||||
}
|
||||
|
||||
QHeaderView* SearchTab::header() const {
|
||||
return resultsBrowser->header();
|
||||
}
|
||||
|
||||
bool SearchTab::loadColWidthResultsList() {
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QString line = settings.value("SearchResultsColsWidth", QString()).toString();
|
||||
if(line.isEmpty())
|
||||
return false;
|
||||
QStringList width_list = line.split(' ');
|
||||
if(width_list.size() < SearchListModel->columnCount())
|
||||
return false;
|
||||
unsigned int listSize = width_list.size();
|
||||
for(unsigned int i=0; i<listSize; ++i){
|
||||
resultsBrowser->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QLabel* SearchTab::getCurrentLabel()
|
||||
{
|
||||
return results_lbl;
|
||||
@@ -155,7 +128,7 @@ void SearchTab::sortSearchListInt(int index, Qt::SortOrder sortOrder){
|
||||
for(int row=0; row<lines.size(); ++row){
|
||||
SearchListModel->insertRow(SearchListModel->rowCount());
|
||||
int sourceRow = lines[row].first;
|
||||
for(int col=0; col<6; ++col){
|
||||
for(int col=0; col<5; ++col){
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col)));
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
@@ -175,7 +148,7 @@ void SearchTab::sortSearchListString(int index, Qt::SortOrder sortOrder){
|
||||
for(int row=0; row<nbRows_old; ++row){
|
||||
SearchListModel->insertRow(SearchListModel->rowCount());
|
||||
int sourceRow = lines[row].first;
|
||||
for(int col=0; col<6; ++col){
|
||||
for(int col=0; col<5; ++col){
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col)));
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
@@ -184,3 +157,33 @@ void SearchTab::sortSearchListString(int index, Qt::SortOrder sortOrder){
|
||||
SearchListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
|
||||
// Save columns width in a file to remember them
|
||||
// (download list)
|
||||
void SearchTab::saveColWidthSearchList() const{
|
||||
qDebug("Saving columns width in search list");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QStringList width_list;
|
||||
for(int i=0; i<SearchListModel->columnCount(); ++i){
|
||||
width_list << misc::toQString(resultsBrowser->columnWidth(i));
|
||||
}
|
||||
settings.setValue("SearchListColsWidth", width_list.join(" "));
|
||||
qDebug("Search list columns width saved");
|
||||
}
|
||||
|
||||
// Load columns width in a file that were saved previously
|
||||
// (search list)
|
||||
bool SearchTab::loadColWidthSearchList(){
|
||||
qDebug("Loading columns width for search list");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QString line = settings.value("SearchListColsWidth", QString()).toString();
|
||||
if(line.isEmpty())
|
||||
return false;
|
||||
QStringList width_list = line.split(' ');
|
||||
if(width_list.size() != SearchListModel->columnCount())
|
||||
return false;
|
||||
for(int i=0; i<width_list.size(); ++i){
|
||||
resultsBrowser->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
qDebug("Search list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -33,13 +24,9 @@
|
||||
|
||||
#include "ui_search.h"
|
||||
|
||||
#define ENGINE_URL_COLUMN 4
|
||||
#define URL_COLUMN 5
|
||||
|
||||
class SearchListDelegate;
|
||||
class SearchEngine;
|
||||
class QTreeView;
|
||||
class QHeaderView;
|
||||
class QStandardItemModel;
|
||||
|
||||
class SearchTab : public QWidget, public Ui::search_engine
|
||||
@@ -55,17 +42,16 @@ class SearchTab : public QWidget, public Ui::search_engine
|
||||
public:
|
||||
SearchTab(SearchEngine *parent);
|
||||
~SearchTab();
|
||||
bool loadColWidthResultsList();
|
||||
bool loadColWidthSearchList();
|
||||
QLabel * getCurrentLabel();
|
||||
QStandardItemModel * getCurrentSearchListModel();
|
||||
QTreeView * getCurrentTreeView();
|
||||
void setRowColor(int row, QString color);
|
||||
QHeaderView* header() const;
|
||||
|
||||
protected slots:
|
||||
void sortSearchList(int index);
|
||||
void sortSearchListInt(int index, Qt::SortOrder sortOrder);
|
||||
void sortSearchListString(int index, Qt::SortOrder sortOrder);
|
||||
void saveColWidthSearchList() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
38
src/about.ui
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0" >
|
||||
<author>Christophe Dumez</author>
|
||||
<class>AboutDlg</class>
|
||||
@@ -51,13 +50,13 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="lb_name" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><h3><b>qBittorrent</b></h3></string>
|
||||
<string><h3><b>qBittorrent</b></h3></string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::RichText</enum>
|
||||
@@ -69,7 +68,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
@@ -92,7 +91,7 @@
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>380</x>
|
||||
<y>70</y>
|
||||
<y>50</y>
|
||||
<width>94</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
@@ -105,40 +104,29 @@
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<y>40</y>
|
||||
<width>481</width>
|
||||
<height>102</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans'; font-size:8pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Bittorrent client programmed in C++, based on Qt4 toolkit </p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and libtorrent-rasterbar. <br /><br />Copyright ©2006-2009 Christophe Dumez<br /><br /><span style=" text-decoration: underline;">Home Page:</span> <a href="http://www.qbittorrent.org"><span style=" text-decoration: underline; color:#0057ae;">http://www.qbittorrent.org</span></a><br /></p></body></html></string>
|
||||
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.<br>
|
||||
<br>
|
||||
Copyright © 2006 by Christophe Dumez<br>
|
||||
<br> <u>Home Page:</u> <i>http://www.qbittorrent.org</i><br></string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab3" >
|
||||
@@ -163,7 +151,7 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
@@ -294,7 +282,7 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
@@ -356,7 +344,7 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -46,8 +37,8 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
// Set icons
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
|
||||
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/mascot.png")));
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/qbittorrent22.png")));
|
||||
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/mascot.png")));
|
||||
//Title
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
// Thanks
|
||||
@@ -70,7 +61,7 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
- <u>Czech:</u> Jirka Vilim (web@tets.cz)<br>\
|
||||
- <u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)<br>\
|
||||
- <u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net) and Peter Koeleman (peter@peerweb.nl)<br>\
|
||||
- <u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)<br>\
|
||||
- <u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net)<br>\
|
||||
- <u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)<br>\
|
||||
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||
- <u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)<br>\
|
||||
@@ -91,19 +82,7 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
te_translation->scrollToAnchor(QString::fromUtf8("top"));
|
||||
// License
|
||||
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
te_license->append(QString::fromUtf8("qBittorrent is licensed under the GNU General Public License version 2 with the\
|
||||
addition of the following special exception:\
|
||||
<br><br>\
|
||||
<i>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.</i>\
|
||||
<br><br>\
|
||||
<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
|
||||
te_license->append(QString::fromUtf8("<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
|
||||
<center>Version 2, June 1991</center><br>\
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>\
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0" >
|
||||
<class>addTorrentDialog</class>
|
||||
<widget class="QDialog" name="addTorrentDialog" >
|
||||
@@ -7,13 +6,13 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>511</width>
|
||||
<height>461</height>
|
||||
<height>441</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Torrent addition dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="fileNameLbl" >
|
||||
<property name="text" >
|
||||
@@ -46,7 +45,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -61,75 +69,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Torrent size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_torrent_size">
|
||||
<property name="text">
|
||||
<string>Unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Free disk space:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_disk_space">
|
||||
<property name="text">
|
||||
<string>Unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_space_msg">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="torrentContentLbl" >
|
||||
<property name="font" >
|
||||
@@ -163,7 +102,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
@@ -190,7 +129,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
@@ -203,7 +142,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkIncrementalDL" >
|
||||
<property name="text" >
|
||||
<string>Download in sequential order (slower but good for previewing)</string>
|
||||
<string>Download in correct order (slower but good for previewing)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -219,7 +158,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -227,7 +175,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
@@ -254,7 +202,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -41,7 +32,7 @@ private:
|
||||
torrent_file *parent;
|
||||
bool is_dir;
|
||||
QString rel_path;
|
||||
QList<const torrent_file*> children;
|
||||
QList<torrent_file*> children;
|
||||
size_type size;
|
||||
float progress;
|
||||
int priority;
|
||||
@@ -51,8 +42,6 @@ public:
|
||||
torrent_file(torrent_file *parent, QString path, bool dir, size_type size=0, int index=-1, float progress=0., int priority=1): parent(parent), is_dir(dir), size(size), progress(progress), priority(priority), index(index){
|
||||
qDebug("created a file with index %d", index);
|
||||
rel_path = QDir::cleanPath(path);
|
||||
Q_ASSERT(progress >= 0.);
|
||||
Q_ASSERT(progress <= 1.);
|
||||
if(parent) {
|
||||
parent->updateProgress();
|
||||
parent->updatePriority(priority);
|
||||
@@ -77,9 +66,10 @@ public:
|
||||
progress = 0.;
|
||||
return;
|
||||
}
|
||||
double wanted = 0.;
|
||||
double done = 0.;
|
||||
foreach(const torrent_file *child, children) {
|
||||
float wanted = 0.;
|
||||
float done = 0.;
|
||||
torrent_file *child;
|
||||
foreach(child, children) {
|
||||
wanted += child->getSize();
|
||||
done += child->getSize()*child->getProgress();
|
||||
}
|
||||
@@ -90,7 +80,8 @@ public:
|
||||
|
||||
void updatePriority(int prio) {
|
||||
Q_ASSERT(is_dir);
|
||||
foreach(const torrent_file *child, children) {
|
||||
torrent_file *child;
|
||||
foreach(child, children) {
|
||||
if(child->getPriority() != prio) return;
|
||||
}
|
||||
priority = prio;
|
||||
@@ -120,13 +111,14 @@ public:
|
||||
return (!children.isEmpty());
|
||||
}
|
||||
|
||||
QList<const torrent_file*> getChildren() const {
|
||||
QList<torrent_file*> getChildren() const {
|
||||
return children;
|
||||
}
|
||||
|
||||
const torrent_file* getChild(QString fileName) const {
|
||||
torrent_file* getChild(QString fileName) const {
|
||||
Q_ASSERT(is_dir);
|
||||
foreach(const torrent_file *f, children) {
|
||||
torrent_file* f;
|
||||
foreach(f, children) {
|
||||
if(f->name() == fileName) return f;
|
||||
}
|
||||
return 0;
|
||||
@@ -149,24 +141,25 @@ public:
|
||||
return f;
|
||||
}
|
||||
|
||||
bool removeFromFS(QString saveDir) const {
|
||||
bool removeFromFS(QString saveDir) {
|
||||
QString full_path = saveDir + QDir::separator() + rel_path;
|
||||
if(!QFile::exists(full_path)) {
|
||||
qDebug("%s does not exist, no need to remove it", full_path.toLocal8Bit().data());
|
||||
qDebug("%s does not exist, no need to remove it", full_path.toUtf8().data());
|
||||
return true;
|
||||
}
|
||||
bool success = true;
|
||||
torrent_file *f;
|
||||
qDebug("We have %d children", children.size());
|
||||
foreach(const torrent_file *f, children) {
|
||||
foreach(f, children) {
|
||||
bool s = f->removeFromFS(saveDir);
|
||||
success = s && success;
|
||||
}
|
||||
if(is_dir) {
|
||||
qDebug("trying to remove directory: %s", full_path.toLocal8Bit().data());
|
||||
qDebug("trying to remove directory: %s", full_path.toUtf8().data());
|
||||
QDir dir(full_path);
|
||||
dir.rmdir(full_path);
|
||||
} else {
|
||||
qDebug("trying to remove file: %s", full_path.toLocal8Bit().data());
|
||||
qDebug("trying to remove file: %s", full_path.toUtf8().data());
|
||||
bool s = QFile::remove(full_path);
|
||||
success = s && success;
|
||||
}
|
||||
@@ -199,7 +192,7 @@ public:
|
||||
Q_ASSERT(root->getSize() == t->total_size());
|
||||
}
|
||||
|
||||
arborescence(torrent_info const& t, std::vector<size_type> fp, std::vector<int> files_priority) {
|
||||
arborescence(torrent_info const& t, std::vector<size_type> fp, int *prioritiesTab) {
|
||||
torrent_info::file_iterator fi = t.begin_files();
|
||||
if(t.num_files() > 1) {
|
||||
qDebug("More than one file in the torrent, setting a folder as root");
|
||||
@@ -207,13 +200,13 @@ public:
|
||||
} else {
|
||||
// XXX: Will crash if there is no file in torrent
|
||||
qDebug("one file in the torrent, setting it as root with index 0");
|
||||
root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, ((double)fp[0])/t.file_at(0).size, files_priority.at(0));
|
||||
root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0]/t.file_at(0).size, prioritiesTab[0]);
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while(fi != t.end_files()) {
|
||||
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
|
||||
addFile(path, fi->size, i, ((double)fp[i])/t.file_at(i).size, files_priority.at(i));
|
||||
addFile(path, fi->size, i, fp[i]/t.file_at(i).size, prioritiesTab[i]);
|
||||
fi++;
|
||||
++i;
|
||||
}
|
||||
@@ -246,13 +239,14 @@ protected:
|
||||
if(relative_path.at(0) ==QDir::separator())
|
||||
relative_path.remove(0, 1);
|
||||
QStringList fileNames = relative_path.split(QDir::separator());
|
||||
QString fileName;
|
||||
torrent_file *dad = root;
|
||||
unsigned int nb_i = 0;
|
||||
unsigned int size = fileNames.size();
|
||||
foreach(const QString &fileName, fileNames) {
|
||||
foreach(fileName, fileNames) {
|
||||
++nb_i;
|
||||
if(fileName == ".") continue;
|
||||
const torrent_file* child = dad->getChild(fileName);
|
||||
torrent_file* child = dad->getChild(fileName);
|
||||
if(!child) {
|
||||
if(nb_i != size) {
|
||||
// Folder
|
||||
@@ -262,7 +256,7 @@ protected:
|
||||
child = dad->addChild(fileName, false, file_size, index, progress, priority);
|
||||
}
|
||||
}
|
||||
dad = (torrent_file*)child;
|
||||
dad = child;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,20 +16,11 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QDir>
|
||||
#include <QDateTime>
|
||||
#include <QTime>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QFileSystemWatcher>
|
||||
@@ -40,7 +31,6 @@
|
||||
#include "misc.h"
|
||||
#include "downloadThread.h"
|
||||
#include "filterParserThread.h"
|
||||
#include "torrentPersistentData.h"
|
||||
#include <libtorrent/extensions/ut_metadata.hpp>
|
||||
#include <libtorrent/extensions/ut_pex.hpp>
|
||||
#include <libtorrent/extensions/smart_ban.hpp>
|
||||
@@ -53,17 +43,16 @@
|
||||
#include <boost/filesystem/exception.hpp>
|
||||
|
||||
#define MAX_TRACKER_ERRORS 2
|
||||
#define MAX_RATIO 100.
|
||||
|
||||
// Main constructor
|
||||
bittorrent::bittorrent() : DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), ratio_limit(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), queueingEnabled(false) {
|
||||
bittorrent::bittorrent() : DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), queueingEnabled(false) {
|
||||
// To avoid some exceptions
|
||||
fs::path::default_name_check(fs::no_check);
|
||||
// Creating bittorrent session
|
||||
// Check if we should spoof azureus
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
if(settings.value(QString::fromUtf8("AzureusSpoof"), false).toBool()) {
|
||||
s = new session(fingerprint("UT", 1, 8, 3, 0), 0);
|
||||
s = new session(fingerprint("AZ", 3, 0, 5, 2), 0);
|
||||
} else {
|
||||
s = new session(fingerprint("qB", VERSION_MAJOR, VERSION_MINOR, VERSION_BUGFIX, 0), 0);
|
||||
}
|
||||
@@ -126,7 +115,7 @@ void bittorrent::preAllocateAllFiles(bool b) {
|
||||
}
|
||||
|
||||
void bittorrent::deleteBigRatios() {
|
||||
if(ratio_limit == -1) return;
|
||||
if(max_ratio == -1) return;
|
||||
std::vector<torrent_handle> torrents = getTorrents();
|
||||
std::vector<torrent_handle>::iterator torrentIT;
|
||||
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
||||
@@ -134,8 +123,7 @@ void bittorrent::deleteBigRatios() {
|
||||
if(!h.is_valid()) continue;
|
||||
if(h.is_seed()) {
|
||||
QString hash = h.hash();
|
||||
float ratio = getRealRatio(hash);
|
||||
if(ratio <= MAX_RATIO && ratio > ratio_limit) {
|
||||
if(getRealRatio(hash) > max_ratio) {
|
||||
QString fileName = h.name();
|
||||
addConsoleMessage(tr("%1 reached the maximum ratio you set.").arg(fileName));
|
||||
deleteTorrent(hash);
|
||||
@@ -179,12 +167,6 @@ void bittorrent::setUploadLimit(QString hash, long val) {
|
||||
|
||||
void bittorrent::handleDownloadFailure(QString url, QString reason) {
|
||||
emit downloadFromUrlFailure(url, reason);
|
||||
// Clean up
|
||||
int index = url_skippingDlg.indexOf(url);
|
||||
if(index >= 0)
|
||||
url_skippingDlg.removeAt(index);
|
||||
if(savepath_fromurl.contains(url))
|
||||
savepath_fromurl.remove(url);
|
||||
}
|
||||
|
||||
void bittorrent::startTorrentsInPause(bool b) {
|
||||
@@ -267,7 +249,7 @@ unsigned int bittorrent::getUnfinishedPausedTorrentsNb() const {
|
||||
// Delete a torrent from the session, given its hash
|
||||
// permanent = true means that the torrent will be removed from the hard-drive too
|
||||
void bittorrent::deleteTorrent(QString hash, bool permanent) {
|
||||
qDebug("Deleting torrent with hash: %s", hash.toLocal8Bit().data());
|
||||
qDebug("Deleting torrent with hash: %s", hash.toUtf8().data());
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
if(!h.is_valid()) {
|
||||
qDebug("/!\\ Error: Invalid handle");
|
||||
@@ -285,10 +267,10 @@ void bittorrent::deleteTorrent(QString hash, bool permanent) {
|
||||
QStringList filters;
|
||||
filters << hash+".*";
|
||||
QStringList files = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
foreach(const QString &file, files) {
|
||||
QString file;
|
||||
foreach(file, files) {
|
||||
torrentBackup.remove(file);
|
||||
}
|
||||
TorrentPersistentData::deletePersistentData(hash);
|
||||
// Remove tracker errors
|
||||
trackersErrors.remove(hash);
|
||||
if(permanent)
|
||||
@@ -341,23 +323,28 @@ void bittorrent::resumeTorrent(QString hash) {
|
||||
}
|
||||
|
||||
void bittorrent::loadWebSeeds(QString hash) {
|
||||
QVariantList url_seeds = TorrentPersistentData::getUrlSeeds(hash);
|
||||
QFile urlseeds_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".urlseeds");
|
||||
if(!urlseeds_file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
|
||||
QByteArray urlseeds_lines = urlseeds_file.readAll();
|
||||
urlseeds_file.close();
|
||||
QList<QByteArray> url_seeds = urlseeds_lines.split('\n');
|
||||
QByteArray url_seed;
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
// First remove from the torrent the url seeds that were deleted
|
||||
// in a previous session
|
||||
QStringList seeds_to_delete;
|
||||
QStringList existing_seeds = h.url_seeds();
|
||||
foreach(const QString &existing_seed, existing_seeds) {
|
||||
if(!url_seeds.contains(existing_seed.toLocal8Bit())) {
|
||||
QString existing_seed;
|
||||
foreach(existing_seed, existing_seeds) {
|
||||
if(!url_seeds.contains(existing_seed.toUtf8())) {
|
||||
seeds_to_delete << existing_seed;
|
||||
}
|
||||
}
|
||||
foreach(const QString &existing_seed, seeds_to_delete) {
|
||||
foreach(existing_seed, seeds_to_delete) {
|
||||
h.remove_url_seed(existing_seed);
|
||||
}
|
||||
// Add the ones that were added in a previous session
|
||||
foreach(const QVariant &var_url_seed, url_seeds) {
|
||||
QString url_seed = var_url_seed.toString();
|
||||
foreach(url_seed, url_seeds) {
|
||||
if(!url_seed.isEmpty()) {
|
||||
// XXX: Should we check if it is already in the list before adding it
|
||||
// or is libtorrent clever enough to know
|
||||
@@ -366,136 +353,18 @@ void bittorrent::loadWebSeeds(QString hash) {
|
||||
}
|
||||
}
|
||||
|
||||
QTorrentHandle bittorrent::addMagnetUri(QString magnet_uri, bool resumed) {
|
||||
QTorrentHandle h;
|
||||
QString hash = misc::magnetUriToHash(magnet_uri);
|
||||
if(hash.isEmpty()) {
|
||||
addConsoleMessage(tr("'%1' is not a valid magnet URI.").arg(magnet_uri));
|
||||
return h;
|
||||
}
|
||||
if(resumed) {
|
||||
qDebug("Resuming magnet URI: %s", hash.toLocal8Bit().data());
|
||||
} else {
|
||||
qDebug("Adding new magnet URI");
|
||||
}
|
||||
|
||||
bool fastResume=false;
|
||||
Q_ASSERT(magnet_uri.startsWith("magnet:"));
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
// Checking if BT_backup Dir exists
|
||||
// create it if it is not
|
||||
if(! torrentBackup.exists()) {
|
||||
if(! torrentBackup.mkpath(torrentBackup.path())) {
|
||||
std::cerr << "Couldn't create the directory: '" << torrentBackup.path().toLocal8Bit().data() << "'\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if torrent is already in download list
|
||||
if(s->find_torrent(sha1_hash(hash.toLocal8Bit().data())).is_valid()) {
|
||||
qDebug("/!\\ Torrent is already in download list");
|
||||
// Update info Bar
|
||||
addConsoleMessage(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(magnet_uri));
|
||||
return h;
|
||||
}
|
||||
|
||||
add_torrent_params p;
|
||||
//Getting fast resume data if existing
|
||||
std::vector<char> buf;
|
||||
if(resumed) {
|
||||
qDebug("Trying to load fastresume data: %s", (torrentBackup.path()+QDir::separator()+hash+QString(".fastresume")).toLocal8Bit().data());
|
||||
if (load_file((torrentBackup.path()+QDir::separator()+hash+QString(".fastresume")).toLocal8Bit().data(), buf) == 0) {
|
||||
fastResume = true;
|
||||
p.resume_data = &buf;
|
||||
qDebug("Successfuly loaded");
|
||||
}
|
||||
}
|
||||
QString savePath = getSavePath(hash);
|
||||
qDebug("addMagnetURI: using save_path: %s", savePath.toLocal8Bit().data());
|
||||
if(defaultTempPath.isEmpty() || (resumed && TorrentPersistentData::isSeed(hash))) {
|
||||
p.save_path = savePath.toLocal8Bit().data();
|
||||
} else {
|
||||
p.save_path = defaultTempPath.toLocal8Bit().data();
|
||||
}
|
||||
// Preallocate all?
|
||||
if(preAllocateAll)
|
||||
p.storage_mode = storage_mode_allocate;
|
||||
else
|
||||
p.storage_mode = storage_mode_sparse;
|
||||
// Start in pause
|
||||
p.paused = false;
|
||||
p.duplicate_is_error = false; // Already checked
|
||||
p.auto_managed = false; // Because it is added in paused state
|
||||
// Adding torrent to bittorrent session
|
||||
try {
|
||||
h = QTorrentHandle(add_magnet_uri(*s, magnet_uri.toStdString(), p));
|
||||
}catch(std::exception e){
|
||||
qDebug("Error: %s", e.what());
|
||||
}
|
||||
// Check if it worked
|
||||
if(!h.is_valid()) {
|
||||
// No need to keep on, it failed.
|
||||
qDebug("/!\\ Error: Invalid handle");
|
||||
return h;
|
||||
}
|
||||
Q_ASSERT(h.hash() == hash);
|
||||
// Connections limit per torrent
|
||||
h.set_max_connections(maxConnecsPerTorrent);
|
||||
// Uploads limit per torrent
|
||||
h.set_max_uploads(maxUploadsPerTorrent);
|
||||
// Load filtered files
|
||||
if(resumed) {
|
||||
// Load custom url seeds
|
||||
loadWebSeeds(hash);
|
||||
// Load speed limit from hard drive
|
||||
loadTorrentSpeedLimits(hash);
|
||||
// Load trackers
|
||||
loadTrackerFile(hash);
|
||||
// XXX: only when resuming because torrentAddition dialog is not supported yet
|
||||
loadFilesPriorities(h);
|
||||
} else {
|
||||
// Sequential download
|
||||
if(TorrentTempData::hasTempData(hash)) {
|
||||
qDebug("addMagnetUri: Setting download as sequential (from tmp data)");
|
||||
h.set_sequential_download(TorrentTempData::isSequential(hash));
|
||||
}
|
||||
// Save persistent data for new torrent
|
||||
Q_ASSERT(h.is_valid());
|
||||
qDebug("addMagnetUri: hash: %s", h.hash().toLocal8Bit().data());
|
||||
TorrentPersistentData::saveTorrentPersistentData(h, true);
|
||||
qDebug("Persistent data saved");
|
||||
// Save save_path
|
||||
if(!defaultTempPath.isEmpty()) {
|
||||
qDebug("addMagnetUri: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
|
||||
TorrentPersistentData::saveSavePath(hash, savePath);
|
||||
}
|
||||
}
|
||||
if(!addInPause && !fastResume) {
|
||||
// Start torrent because it was added in paused state
|
||||
h.resume();
|
||||
}
|
||||
// Send torrent addition signal
|
||||
if(fastResume)
|
||||
addConsoleMessage(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(magnet_uri));
|
||||
else
|
||||
addConsoleMessage(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(magnet_uri));
|
||||
emit addedTorrent(h);
|
||||
return h;
|
||||
}
|
||||
|
||||
// Add a torrent to the bittorrent session
|
||||
QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bool resumed) {
|
||||
QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bool) {
|
||||
QTorrentHandle h;
|
||||
bool fastResume=false;
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QString file, dest_file, hash;
|
||||
boost::intrusive_ptr<torrent_info> t;
|
||||
QString file, dest_file;
|
||||
|
||||
// Checking if BT_backup Dir exists
|
||||
// create it if it is not
|
||||
if(! torrentBackup.exists()) {
|
||||
if(! torrentBackup.mkpath(torrentBackup.path())) {
|
||||
std::cerr << "Couldn't create the directory: '" << torrentBackup.path().toLocal8Bit().data() << "'\n";
|
||||
std::cerr << "Couldn't create the directory: '" << torrentBackup.path().toUtf8().data() << "'\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -505,11 +374,11 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||
return h;
|
||||
}
|
||||
Q_ASSERT(!file.startsWith("http://", Qt::CaseInsensitive) && !file.startsWith("https://", Qt::CaseInsensitive) && !file.startsWith("ftp://", Qt::CaseInsensitive));
|
||||
|
||||
qDebug("Adding %s to download list", file.toLocal8Bit().data());
|
||||
qDebug("Adding %s to download list", file.toUtf8().data());
|
||||
boost::intrusive_ptr<torrent_info> t;
|
||||
try {
|
||||
// Getting torrent file informations
|
||||
t = new torrent_info(file.toLocal8Bit().data());
|
||||
t = new torrent_info(file.toUtf8().data());
|
||||
} catch(std::exception&) {
|
||||
if(!from_url.isNull()) {
|
||||
addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(from_url), QString::fromUtf8("red"));
|
||||
@@ -528,8 +397,14 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||
}
|
||||
qDebug(" -> Hash: %s", misc::toString(t->info_hash()).c_str());
|
||||
qDebug(" -> Name: %s", t->name().c_str());
|
||||
hash = misc::toQString(t->info_hash());
|
||||
|
||||
QString hash = misc::toQString(t->info_hash());
|
||||
if(file.startsWith(torrentBackup.path())) {
|
||||
QFileInfo fi(file);
|
||||
QString old_hash = fi.baseName();
|
||||
if(old_hash != hash){
|
||||
qDebug("* ERROR: Strange, hash changed from %s to %s", old_hash.toUtf8().data(), hash.toUtf8().data());
|
||||
}
|
||||
}
|
||||
// Check if torrent is already in download list
|
||||
if(s->find_torrent(t->info_hash()).is_valid()) {
|
||||
qDebug("/!\\ Torrent is already in download list");
|
||||
@@ -553,27 +428,21 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||
add_torrent_params p;
|
||||
//Getting fast resume data if existing
|
||||
std::vector<char> buf;
|
||||
if(resumed) {
|
||||
qDebug("Trying to load fastresume data: %s", (torrentBackup.path()+QDir::separator()+hash+QString(".fastresume")).toLocal8Bit().data());
|
||||
if (load_file((torrentBackup.path()+QDir::separator()+hash+QString(".fastresume")).toLocal8Bit().data(), buf) == 0) {
|
||||
qDebug("Trying to load fastresume data: %s", (torrentBackup.path()+QDir::separator()+hash+QString(".fastresume")).toUtf8().data());
|
||||
if (load_file((torrentBackup.path()+QDir::separator()+hash+QString(".fastresume")).toUtf8().data(), buf) == 0) {
|
||||
fastResume = true;
|
||||
p.resume_data = &buf;
|
||||
qDebug("Successfuly loaded");
|
||||
}
|
||||
QString savePath = getSavePath(hash);
|
||||
// Save save_path to hard drive
|
||||
QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".savepath"));
|
||||
if(!savepath_file.exists()) {
|
||||
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
savepath_file.write(savePath.toUtf8());
|
||||
savepath_file.close();
|
||||
}
|
||||
QString savePath;
|
||||
if(!from_url.isEmpty() && savepath_fromurl.contains(from_url)) {
|
||||
// Enforcing the save path defined before URL download (from RSS for example)
|
||||
savePath = savepath_fromurl.take(from_url);
|
||||
} else {
|
||||
savePath = getSavePath(hash);
|
||||
}
|
||||
qDebug("addTorrent: using save_path: %s", savePath.toLocal8Bit().data());
|
||||
if(defaultTempPath.isEmpty() || (resumed && TorrentPersistentData::isSeed(hash))) {
|
||||
p.save_path = savePath.toLocal8Bit().data();
|
||||
} else {
|
||||
p.save_path = defaultTempPath.toLocal8Bit().data();
|
||||
}
|
||||
p.save_path = savePath.toUtf8().data();
|
||||
p.ti = t;
|
||||
// Preallocate all?
|
||||
if(preAllocateAll)
|
||||
@@ -604,26 +473,16 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||
h.set_max_uploads(maxUploadsPerTorrent);
|
||||
// Load filtered files
|
||||
loadFilesPriorities(h);
|
||||
if(resumed) {
|
||||
// Load custom url seeds
|
||||
loadWebSeeds(hash);
|
||||
// Load speed limit from hard drive
|
||||
loadTorrentSpeedLimits(hash);
|
||||
// Load trackers
|
||||
bool loaded_trackers = loadTrackerFile(hash);
|
||||
// Doing this to order trackers well
|
||||
if(!loaded_trackers) {
|
||||
saveTrackerFile(hash);
|
||||
loadTrackerFile(hash);
|
||||
} else {
|
||||
// Sequential download
|
||||
if(TorrentTempData::hasTempData(hash)) {
|
||||
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
||||
h.set_sequential_download(TorrentTempData::isSequential(hash));
|
||||
}
|
||||
// Save persistent data for new torrent
|
||||
TorrentPersistentData::saveTorrentPersistentData(h);
|
||||
// Save save_path
|
||||
if(!defaultTempPath.isEmpty()) {
|
||||
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
|
||||
TorrentPersistentData::saveSavePath(hash, savePath);
|
||||
}
|
||||
}
|
||||
QString newFile = torrentBackup.path() + QDir::separator() + hash + ".torrent";
|
||||
if(file != newFile) {
|
||||
@@ -633,6 +492,11 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||
// Copy it to torrentBackup directory
|
||||
QFile::copy(file, newFile);
|
||||
}
|
||||
// Incremental download
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".incremental")) {
|
||||
qDebug("Incremental download enabled for %s", t->name().c_str());
|
||||
h.set_sequential_download(true);
|
||||
}
|
||||
if(!addInPause && !fastResume) {
|
||||
// Start torrent because it was added in paused state
|
||||
h.resume();
|
||||
@@ -659,17 +523,27 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||
return h;
|
||||
}
|
||||
|
||||
// Check if the user filtered files in this torrent.
|
||||
// Check in .priorities file if the user filtered files
|
||||
// in this torrent.
|
||||
bool bittorrent::has_filtered_files(QString hash) const{
|
||||
QVariantList files_priority = TorrentPersistentData::getFilesPriority(hash);
|
||||
foreach(QVariant var_prio, files_priority) {
|
||||
int priority = var_prio.toInt();
|
||||
QFile pieces_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".priorities");
|
||||
// Read saved file
|
||||
if(!pieces_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
return false;
|
||||
}
|
||||
QByteArray pieces_text = pieces_file.readAll();
|
||||
pieces_file.close();
|
||||
QList<QByteArray> pieces_priorities_list = pieces_text.split('\n');
|
||||
unsigned int listSize = pieces_priorities_list.size();
|
||||
for(unsigned int i=0; i<listSize-1; ++i) {
|
||||
int priority = pieces_priorities_list.at(i).toInt();
|
||||
if( priority < 0 || priority > 7) {
|
||||
priority = 1;
|
||||
}
|
||||
if(!priority)
|
||||
if(!priority) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -762,7 +636,7 @@ void bittorrent::enableLSD(bool b) {
|
||||
}
|
||||
|
||||
void bittorrent::loadSessionState() {
|
||||
boost::filesystem::ifstream ses_state_file((misc::qBittorrentPath()+QString::fromUtf8("ses_state")).toLocal8Bit().data()
|
||||
boost::filesystem::ifstream ses_state_file((misc::qBittorrentPath()+QString::fromUtf8("ses_state")).toUtf8().data()
|
||||
, std::ios_base::binary);
|
||||
ses_state_file.unsetf(std::ios_base::skipws);
|
||||
s->load_state(bdecode(
|
||||
@@ -773,7 +647,7 @@ void bittorrent::loadSessionState() {
|
||||
void bittorrent::saveSessionState() {
|
||||
qDebug("Saving session state to disk...");
|
||||
entry session_state = s->state();
|
||||
boost::filesystem::ofstream out((misc::qBittorrentPath()+QString::fromUtf8("ses_state")).toLocal8Bit().data()
|
||||
boost::filesystem::ofstream out((misc::qBittorrentPath()+QString::fromUtf8("ses_state")).toUtf8().data()
|
||||
, std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), session_state);
|
||||
@@ -786,7 +660,7 @@ bool bittorrent::enableDHT(bool b) {
|
||||
entry dht_state;
|
||||
QString dht_state_path = misc::qBittorrentPath()+QString::fromUtf8("dht_state");
|
||||
if(QFile::exists(dht_state_path)) {
|
||||
boost::filesystem::ifstream dht_state_file(dht_state_path.toLocal8Bit().data(), std::ios_base::binary);
|
||||
boost::filesystem::ifstream dht_state_file(dht_state_path.toUtf8().data(), std::ios_base::binary);
|
||||
dht_state_file.unsetf(std::ios_base::skipws);
|
||||
try{
|
||||
dht_state = bdecode(std::istream_iterator<char>(dht_state_file), std::istream_iterator<char>());
|
||||
@@ -815,13 +689,13 @@ bool bittorrent::enableDHT(bool b) {
|
||||
}
|
||||
|
||||
void bittorrent::saveTorrentSpeedLimits(QString hash) {
|
||||
qDebug("Saving speedLimits file for %s", hash.toLocal8Bit().data());
|
||||
qDebug("Saving speedLimits file for %s", hash.toUtf8().data());
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
int download_limit = h.download_limit();
|
||||
int upload_limit = h.upload_limit();
|
||||
QFile speeds_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".speedLimits");
|
||||
if(!speeds_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qDebug("* Error: Couldn't open speed limits file for torrent: %s", hash.toLocal8Bit().data());
|
||||
qDebug("* Error: Couldn't open speed limits file for torrent: %s", hash.toUtf8().data());
|
||||
return;
|
||||
}
|
||||
speeds_file.write(misc::toQByteArray(download_limit)+QByteArray(" ")+misc::toQByteArray(upload_limit));
|
||||
@@ -829,7 +703,7 @@ void bittorrent::saveTorrentSpeedLimits(QString hash) {
|
||||
}
|
||||
|
||||
void bittorrent::loadTorrentSpeedLimits(QString hash) {
|
||||
// qDebug("Loading speedLimits file for %s", hash.toLocal8Bit().data());
|
||||
// qDebug("Loading speedLimits file for %s", hash.toUtf8().data());
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
QFile speeds_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".speedLimits");
|
||||
if(!speeds_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
@@ -846,27 +720,39 @@ void bittorrent::loadTorrentSpeedLimits(QString hash) {
|
||||
h.set_upload_limit(speeds.at(1).toInt());
|
||||
}
|
||||
|
||||
// Read pieces priorities from hard disk
|
||||
// Read pieces priorities from .priorities file
|
||||
// and ask QTorrentHandle to consider them
|
||||
void bittorrent::loadFilesPriorities(QTorrentHandle &h) {
|
||||
qDebug("Applying files priority");
|
||||
qDebug("Applying pieces priorities");
|
||||
if(!h.is_valid()) {
|
||||
qDebug("/!\\ Error: Invalid handle");
|
||||
return;
|
||||
}
|
||||
std::vector<int> v;
|
||||
QVariantList files_priority;
|
||||
if(TorrentTempData::hasTempData(h.hash())) {
|
||||
files_priority = TorrentTempData::getFilesPriority(h.hash());
|
||||
} else {
|
||||
files_priority = TorrentPersistentData::getFilesPriority(h.hash());
|
||||
unsigned int nbFiles = h.num_files();
|
||||
QString hash = h.hash();
|
||||
QFile pieces_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".priorities");
|
||||
if(!pieces_file.exists()){
|
||||
return;
|
||||
}
|
||||
foreach(const QVariant &var_prio, files_priority) {
|
||||
int priority = var_prio.toInt();
|
||||
// Read saved file
|
||||
if(!pieces_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qDebug("* Error: Couldn't open priorities file: %s", hash.toUtf8().data());
|
||||
return;
|
||||
}
|
||||
QByteArray pieces_priorities = pieces_file.readAll();
|
||||
pieces_file.close();
|
||||
QList<QByteArray> pieces_priorities_list = pieces_priorities.split('\n');
|
||||
if((unsigned int)pieces_priorities_list.size() != nbFiles+1) {
|
||||
std::cerr << "* Error: Corrupted priorities file\n";
|
||||
return;
|
||||
}
|
||||
std::vector<int> v;
|
||||
for(unsigned int i=0; i<nbFiles; ++i) {
|
||||
int priority = pieces_priorities_list.at(i).toInt();
|
||||
if( priority < 0 || priority > 7) {
|
||||
priority = 1;
|
||||
}
|
||||
qDebug("Setting file piority to %d", priority);
|
||||
qDebug("Setting piece piority to %d", priority);
|
||||
v.push_back(priority);
|
||||
}
|
||||
h.prioritize_files(v);
|
||||
@@ -878,13 +764,13 @@ float bittorrent::getRealRatio(QString hash) const{
|
||||
Q_ASSERT(h.all_time_upload() >= 0);
|
||||
if(h.all_time_download() == 0) {
|
||||
if(h.all_time_upload() == 0)
|
||||
return 0;
|
||||
return 101;
|
||||
return 1.;
|
||||
return 10.;
|
||||
}
|
||||
float ratio = (float)h.all_time_upload()/(float)h.all_time_download();
|
||||
Q_ASSERT(ratio >= 0.);
|
||||
if(ratio > 100.)
|
||||
ratio = 100.;
|
||||
if(ratio > 10.)
|
||||
ratio = 10.;
|
||||
return ratio;
|
||||
}
|
||||
|
||||
@@ -902,7 +788,7 @@ void bittorrent::saveFastResumeData() {
|
||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
||||
if(!h.is_valid() || !h.has_metadata()) continue;
|
||||
if(isQueueingEnabled())
|
||||
TorrentPersistentData::savePriority(h);
|
||||
saveTorrentPriority(h.hash(), h.queue_position());
|
||||
if(h.is_paused()) continue;
|
||||
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking) continue;
|
||||
h.save_resume_data();
|
||||
@@ -937,7 +823,7 @@ void bittorrent::saveFastResumeData() {
|
||||
// Remove old fastresume file if it exists
|
||||
QFile::remove(torrentBackup.path()+QDir::separator()+ h.hash() + ".fastresume");
|
||||
QString file = h.hash()+".fastresume";
|
||||
boost::filesystem::ofstream out(fs::path(torrentBackup.path().toLocal8Bit().data()) / file.toLocal8Bit().data(), std::ios_base::binary);
|
||||
boost::filesystem::ofstream out(fs::path(torrentBackup.path().toUtf8().data()) / file.toUtf8().data(), std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), *rd->resume_data);
|
||||
// Remove torrent from session
|
||||
@@ -958,7 +844,7 @@ void bittorrent::addConsoleMessage(QString msg, QColor color) {
|
||||
if(consoleMessages.size() > 100) {
|
||||
consoleMessages.removeFirst();
|
||||
}
|
||||
consoleMessages.append(QString::fromUtf8("<font color='grey'>")+ QDateTime::currentDateTime().toString(QString::fromUtf8("dd/MM/yyyy hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + msg + QString::fromUtf8("</i></font>"));
|
||||
consoleMessages.append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + msg + QString::fromUtf8("</i></font>"));
|
||||
}
|
||||
|
||||
void bittorrent::addPeerBanMessage(QString ip, bool from_ipfilter) {
|
||||
@@ -966,9 +852,9 @@ void bittorrent::addPeerBanMessage(QString ip, bool from_ipfilter) {
|
||||
peerBanMessages.removeFirst();
|
||||
}
|
||||
if(from_ipfilter)
|
||||
peerBanMessages.append(QString::fromUtf8("<font color='grey'>")+ QDateTime::currentDateTime().toString(QString::fromUtf8("dd/MM/yyyy hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was blocked due to your IP filter</i>", "x.y.z.w was blocked").arg(ip));
|
||||
peerBanMessages.append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was blocked due to your IP filter</i>", "x.y.z.w was blocked").arg(ip));
|
||||
else
|
||||
peerBanMessages.append(QString::fromUtf8("<font color='grey'>")+ QDateTime::currentDateTime().toString(QString::fromUtf8("dd/MM/yyyy hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was banned due to corrupt pieces</i>", "x.y.z.w was banned").arg(ip));
|
||||
peerBanMessages.append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was banned due to corrupt pieces</i>", "x.y.z.w was banned").arg(ip));
|
||||
}
|
||||
|
||||
bool bittorrent::isFilePreviewPossible(QString hash) const{
|
||||
@@ -992,19 +878,20 @@ bool bittorrent::isFilePreviewPossible(QString hash) const{
|
||||
// and add them to download list
|
||||
void bittorrent::scanDirectory(QString scan_dir) {
|
||||
FSMutex->lock();
|
||||
qDebug("Scanning directory: %s", scan_dir.toLocal8Bit().data());
|
||||
qDebug("Scanning directory: %s", scan_dir.toUtf8().data());
|
||||
QString file;
|
||||
QDir dir(scan_dir);
|
||||
QStringList filters;
|
||||
filters << "*.torrent";
|
||||
QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
foreach(const QString &file, files) {
|
||||
foreach(file, files) {
|
||||
QString fullPath = dir.path()+QDir::separator()+file;
|
||||
QFile torrent(fullPath);
|
||||
if(torrent.size() != 0) {
|
||||
qDebug("Adding for scan_dir: %s", fullPath.toLocal8Bit().data());
|
||||
qDebug("Adding for scan_dir: %s", fullPath.toUtf8().data());
|
||||
addTorrent(fullPath, true);
|
||||
} else {
|
||||
qDebug("Ignoring empty file: %s", fullPath.toLocal8Bit().data());
|
||||
qDebug("Ignoring empty file: %s", fullPath.toUtf8().data());
|
||||
}
|
||||
}
|
||||
FSMutex->unlock();
|
||||
@@ -1014,45 +901,6 @@ void bittorrent::setDefaultSavePath(QString savepath) {
|
||||
defaultSavePath = savepath;
|
||||
}
|
||||
|
||||
QString bittorrent::getDefaultSavePath() const {
|
||||
return defaultSavePath;
|
||||
}
|
||||
|
||||
bool bittorrent::useTemporaryFolder() const {
|
||||
return !defaultTempPath.isEmpty();
|
||||
}
|
||||
|
||||
void bittorrent::setDefaultTempPath(QString temppath) {
|
||||
if(defaultTempPath == temppath)
|
||||
return;
|
||||
if(temppath.isEmpty()) {
|
||||
// Disabling temp dir
|
||||
// Moving all torrents to their destination folder
|
||||
std::vector<torrent_handle> torrents = getTorrents();
|
||||
std::vector<torrent_handle>::iterator torrentIT;
|
||||
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
||||
if(!h.is_valid()) continue;
|
||||
h.move_storage(getSavePath(h.hash()));
|
||||
}
|
||||
} else {
|
||||
std::vector<torrent_handle> torrents = getTorrents();
|
||||
std::vector<torrent_handle>::iterator torrentIT;
|
||||
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
|
||||
QTorrentHandle h = QTorrentHandle(*torrentIT);
|
||||
if(!h.is_valid()) continue;
|
||||
if(!h.is_seed())
|
||||
h.move_storage(temppath);
|
||||
}
|
||||
}
|
||||
defaultTempPath = temppath;
|
||||
}
|
||||
|
||||
void bittorrent::saveTrackerFile(QString hash) {
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
TorrentPersistentData::saveTrackers(h);
|
||||
}
|
||||
|
||||
// Enable directory scanning
|
||||
void bittorrent::enableDirectoryScanning(QString scan_dir) {
|
||||
if(!scan_dir.isEmpty()) {
|
||||
@@ -1130,41 +978,67 @@ void bittorrent::setGlobalRatio(float ratio) {
|
||||
// be automatically deleted
|
||||
void bittorrent::setDeleteRatio(float ratio) {
|
||||
if(ratio != -1 && ratio < 1.) ratio = 1.;
|
||||
if(ratio_limit == -1 && ratio != -1) {
|
||||
if(max_ratio == -1 && ratio != -1) {
|
||||
Q_ASSERT(!BigRatioTimer);
|
||||
BigRatioTimer = new QTimer(this);
|
||||
connect(BigRatioTimer, SIGNAL(timeout()), this, SLOT(deleteBigRatios()));
|
||||
BigRatioTimer->start(5000);
|
||||
} else {
|
||||
if(ratio_limit != -1 && ratio == -1) {
|
||||
if(max_ratio != -1 && ratio == -1) {
|
||||
delete BigRatioTimer;
|
||||
}
|
||||
}
|
||||
if(ratio_limit != ratio) {
|
||||
ratio_limit = ratio;
|
||||
qDebug("* Set deleteRatio to %.1f", ratio_limit);
|
||||
if(max_ratio != ratio) {
|
||||
max_ratio = ratio;
|
||||
qDebug("* Set deleteRatio to %.1f", max_ratio);
|
||||
deleteBigRatios();
|
||||
}
|
||||
}
|
||||
|
||||
void bittorrent::loadTrackerFile(QString hash) {
|
||||
QHash<QString, QVariant> tiers = TorrentPersistentData::getTrackers(hash);
|
||||
bool bittorrent::loadTrackerFile(QString hash) {
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QFile tracker_file(torrentBackup.path()+QDir::separator()+ hash + ".trackers");
|
||||
if(!tracker_file.exists()) return false;
|
||||
tracker_file.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QStringList lines = QString::fromUtf8(tracker_file.readAll().data()).split("\n");
|
||||
std::vector<announce_entry> trackers;
|
||||
foreach(const QString tracker_url, tiers.keys()) {
|
||||
announce_entry t(tracker_url.toStdString());
|
||||
t.tier = tiers[tracker_url].toInt();
|
||||
QString line;
|
||||
foreach(line, lines) {
|
||||
QStringList parts = line.split("|");
|
||||
if(parts.size() != 2) continue;
|
||||
announce_entry t(parts[0].toStdString());
|
||||
t.tier = parts[1].toInt();
|
||||
trackers.push_back(t);
|
||||
}
|
||||
if(!trackers.empty()) {
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set DHT port (>= 1000 or 0 if same as BT)
|
||||
void bittorrent::saveTrackerFile(QString hash) {
|
||||
qDebug("Saving tracker file for %s", hash.toUtf8().data());
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QFile tracker_file(torrentBackup.path()+QDir::separator()+ hash + ".trackers");
|
||||
if(tracker_file.exists()) {
|
||||
tracker_file.remove();
|
||||
}
|
||||
tracker_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTorrentHandle h = getTorrentHandle(hash);
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
for(unsigned int i=0; i<trackers.size(); ++i) {
|
||||
tracker_file.write(QByteArray(trackers[i].url.c_str())+QByteArray("|")+QByteArray(misc::toString(i).c_str())+QByteArray("\n"));
|
||||
}
|
||||
tracker_file.close();
|
||||
}
|
||||
|
||||
// Set DHT port (>= 1000)
|
||||
void bittorrent::setDHTPort(int dht_port) {
|
||||
if(dht_port == 0 or dht_port >= 1000) {
|
||||
if(dht_port >= 1000) {
|
||||
struct dht_settings DHTSettings;
|
||||
DHTSettings.service_port = dht_port;
|
||||
s->set_dht_settings(DHTSettings);
|
||||
@@ -1239,36 +1113,12 @@ void bittorrent::readAlerts() {
|
||||
if(h.is_valid()){
|
||||
emit finishedTorrent(h);
|
||||
QString hash = h.hash();
|
||||
// Remember finished state
|
||||
TorrentPersistentData::saveSeedStatus(h);
|
||||
// Move to download directory if necessary
|
||||
if(!defaultTempPath.isEmpty()) {
|
||||
// Check if directory is different
|
||||
QDir current_dir(h.save_path());
|
||||
QDir save_dir(getSavePath(h.hash()));
|
||||
if(current_dir != save_dir) {
|
||||
h.move_storage(save_dir.path());
|
||||
}
|
||||
}
|
||||
// Create .finished file if necessary
|
||||
QFile finished_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished");
|
||||
finished_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
finished_file.close();
|
||||
h.save_resume_data();
|
||||
// Check if there is a single torrent file inside
|
||||
QString torrent_relpath = misc::toQString(h.get_torrent_info().file_at(0).path);
|
||||
if(torrent_relpath.endsWith(".torrent")) {
|
||||
addConsoleMessage(tr("Recursive download of file %1 embedded in torrent %2", "Recursive download of test.torrent embedded in torrent test2").arg(torrent_relpath).arg(h.name()));
|
||||
QString torrent_fullpath = h.save_path()+QDir::separator()+torrent_relpath;
|
||||
boost::intrusive_ptr<torrent_info> t;
|
||||
try {
|
||||
t = new torrent_info(torrent_fullpath.toLocal8Bit().data());
|
||||
QString sub_hash = misc::toQString(t->info_hash());
|
||||
// Passing the save path along to the sub torrent file
|
||||
TorrentTempData::setSavePath(sub_hash, h.save_path());
|
||||
addTorrent(torrent_fullpath);
|
||||
} catch(std::exception&) {
|
||||
qDebug("Caught error loading torrent");
|
||||
addConsoleMessage(tr("Unable to decode %1 torrent file.").arg(torrent_fullpath), QString::fromUtf8("red"));
|
||||
}
|
||||
}
|
||||
qDebug("Received finished alert for %s", h.name().toLocal8Bit().data());
|
||||
qDebug("Received finished alert for %s", h.name().toUtf8().data());
|
||||
}
|
||||
}
|
||||
else if (save_resume_data_alert* p = dynamic_cast<save_resume_data_alert*>(a.get())) {
|
||||
@@ -1278,45 +1128,25 @@ void bittorrent::readAlerts() {
|
||||
// Delete old fastresume file if necessary
|
||||
if(QFile::exists(file))
|
||||
QFile::remove(file);
|
||||
qDebug("Saving fastresume data in %s", file.toLocal8Bit().data());
|
||||
qDebug("Saving fastresume data in %s", file.toUtf8().data());
|
||||
if (p->resume_data)
|
||||
{
|
||||
boost::filesystem::ofstream out(fs::path(torrentBackup.path().toLocal8Bit().data()) / file.toLocal8Bit().data(), std::ios_base::binary);
|
||||
boost::filesystem::ofstream out(fs::path(torrentBackup.path().toUtf8().data()) / file.toUtf8().data(), std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), *p->resume_data);
|
||||
}
|
||||
}
|
||||
else if (metadata_received_alert* p = dynamic_cast<metadata_received_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
if(h.is_valid()) {
|
||||
qDebug("Received metadata for %s", h.hash().toLocal8Bit().data());
|
||||
emit metadataReceived(h);
|
||||
if(h.is_paused()) {
|
||||
// XXX: Unfortunately libtorrent-rasterbar does not send a torrent_paused_alert
|
||||
// and the torrent can be paused when metadata is received
|
||||
emit torrentPaused(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (file_error_alert* p = dynamic_cast<file_error_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
h.auto_managed(false);
|
||||
std::cerr << "File Error: " << p->message().c_str() << std::endl;
|
||||
qDebug("File Error: %s", p->message().c_str());
|
||||
if(h.is_valid())
|
||||
emit fullDiskError(h, misc::toQString(p->message()));
|
||||
emit fullDiskError(h);
|
||||
}
|
||||
else if (dynamic_cast<listen_failed_alert*>(a.get())) {
|
||||
// Level: fatal
|
||||
addConsoleMessage(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
|
||||
//emit portListeningFailure();
|
||||
}
|
||||
else if (torrent_paused_alert* p = dynamic_cast<torrent_paused_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
qDebug("Received a torrent_paused_alert for %s", h.hash().toLocal8Bit().data());
|
||||
if(h.is_valid()) {
|
||||
emit torrentPaused(h);
|
||||
}
|
||||
}
|
||||
else if (tracker_error_alert* p = dynamic_cast<tracker_error_alert*>(a.get())) {
|
||||
// Level: fatal
|
||||
QTorrentHandle h(p->handle);
|
||||
@@ -1337,7 +1167,7 @@ void bittorrent::readAlerts() {
|
||||
else if (tracker_reply_alert* p = dynamic_cast<tracker_reply_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
if(h.is_valid()){
|
||||
qDebug("Received a tracker reply from %s", (const char*)h.current_tracker().toLocal8Bit());
|
||||
qDebug("Received a tracker reply from %s", (const char*)h.current_tracker().toUtf8());
|
||||
QString hash = h.hash();
|
||||
QHash<QString, QString> errors = trackersErrors.value(hash, QHash<QString, QString>());
|
||||
// p->url requires at least libtorrent v0.13.1
|
||||
@@ -1365,7 +1195,7 @@ void bittorrent::readAlerts() {
|
||||
else if (fastresume_rejected_alert* p = dynamic_cast<fastresume_rejected_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
if(h.is_valid()){
|
||||
qDebug("/!\\ Fast resume failed for %s, reason: %s", h.name().toLocal8Bit().data(), p->message().c_str());
|
||||
qDebug("/!\\ Fast resume failed for %s, reason: %s", h.name().toUtf8().data(), p->message().c_str());
|
||||
addConsoleMessage(tr("Fast resume data was rejected for torrent %1, checking again...").arg(h.name()), QString::fromUtf8("red"));
|
||||
//emit fastResumeDataRejected(h.name());
|
||||
}
|
||||
@@ -1378,18 +1208,8 @@ void bittorrent::readAlerts() {
|
||||
QTorrentHandle h(p->handle);
|
||||
if(h.is_valid()){
|
||||
QString hash = h.hash();
|
||||
qDebug("%s have just finished checking", hash.toLocal8Bit().data());
|
||||
// Move to temp directory if necessary
|
||||
if(!h.is_seed() && !defaultTempPath.isEmpty()) {
|
||||
// Check if directory is different
|
||||
QDir current_dir(h.save_path());
|
||||
QDir save_dir(getSavePath(h.hash()));
|
||||
if(current_dir == save_dir) {
|
||||
h.move_storage(defaultTempPath);
|
||||
}
|
||||
}
|
||||
qDebug("%s have just finished checking", hash.toUtf8().data());
|
||||
emit torrentFinishedChecking(h);
|
||||
emit metadataReceived(h);
|
||||
}
|
||||
}
|
||||
a = s->pop_alert();
|
||||
@@ -1409,17 +1229,17 @@ session_status bittorrent::getSessionStatus() const{
|
||||
}
|
||||
|
||||
QString bittorrent::getSavePath(QString hash) {
|
||||
QFile savepath_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".savepath");
|
||||
QByteArray line;
|
||||
QString savePath;
|
||||
if(TorrentTempData::hasTempData(hash)) {
|
||||
savePath = TorrentTempData::getSavePath(hash);
|
||||
qDebug("getSavePath, got save_path from temp data: %s", savePath.toLocal8Bit().data());
|
||||
if(savepath_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
line = savepath_file.readAll();
|
||||
savepath_file.close();
|
||||
qDebug(" -> Save path: %s", line.data());
|
||||
savePath = QString::fromUtf8(line.data());
|
||||
}else{
|
||||
savePath = TorrentPersistentData::getSavePath(hash);
|
||||
qDebug("getSavePath, got save_path from persistent data: %s", savePath.toLocal8Bit().data());
|
||||
}
|
||||
if(savePath.isEmpty()) {
|
||||
// use default save path if no other can be found
|
||||
qDebug("Using default save path because none was set: %s", defaultSavePath.toLocal8Bit().data());
|
||||
// use default save path
|
||||
qDebug("Using default save path because none was set");
|
||||
savePath = defaultSavePath;
|
||||
}
|
||||
// Checking if savePath Dir exists
|
||||
@@ -1427,7 +1247,7 @@ QString bittorrent::getSavePath(QString hash) {
|
||||
QDir saveDir(savePath);
|
||||
if(!saveDir.exists()) {
|
||||
if(!saveDir.mkpath(saveDir.path())) {
|
||||
std::cerr << "Couldn't create the save directory: " << saveDir.path().toLocal8Bit().data() << "\n";
|
||||
std::cerr << "Couldn't create the save directory: " << saveDir.path().toUtf8().data() << "\n";
|
||||
// XXX: handle this better
|
||||
return QDir::homePath();
|
||||
}
|
||||
@@ -1445,10 +1265,8 @@ void bittorrent::downloadFromUrl(QString url) {
|
||||
downloader->downloadUrl(url);
|
||||
}
|
||||
|
||||
void bittorrent::downloadUrlAndSkipDialog(QString url, QString save_path) {
|
||||
void bittorrent::downloadUrlAndSkipDialog(QString url) {
|
||||
//emit aboutToDownloadFromUrl(url);
|
||||
if(!save_path.isEmpty())
|
||||
savepath_fromurl[url] = save_path;
|
||||
url_skippingDlg << url;
|
||||
// Launch downloader thread
|
||||
downloader->downloadUrl(url);
|
||||
@@ -1466,6 +1284,14 @@ void bittorrent::processDownloadedFile(QString url, QString file_path) {
|
||||
}
|
||||
}
|
||||
|
||||
void bittorrent::downloadFromURLList(const QStringList& url_list) {
|
||||
QString url;
|
||||
qDebug("DownloadFromUrlList");
|
||||
foreach(url, url_list) {
|
||||
downloadFromUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Return current download rate for the BT
|
||||
// session. Payload means that it only take into
|
||||
// account "useful" part of the rate
|
||||
@@ -1488,7 +1314,7 @@ void bittorrent::saveDHTEntry() {
|
||||
if(DHTEnabled) {
|
||||
try{
|
||||
entry dht_state = s->dht_state();
|
||||
boost::filesystem::ofstream out((misc::qBittorrentPath()+QString::fromUtf8("dht_state")).toLocal8Bit().data(), std::ios_base::binary);
|
||||
boost::filesystem::ofstream out((misc::qBittorrentPath()+QString::fromUtf8("dht_state")).toUtf8().data(), std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), dht_state);
|
||||
qDebug("DHT entry saved");
|
||||
@@ -1503,44 +1329,57 @@ void bittorrent::applyEncryptionSettings(pe_settings se) {
|
||||
s->set_pe_settings(se);
|
||||
}
|
||||
|
||||
void bittorrent::saveTorrentPriority(QString hash, int prio) {
|
||||
// Write .queued file
|
||||
QFile prio_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".prio");
|
||||
prio_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
prio_file.write(QByteArray::number(prio));
|
||||
prio_file.close();
|
||||
}
|
||||
|
||||
// Will fast resume torrents in
|
||||
// backup directory
|
||||
void bittorrent::startUpTorrents() {
|
||||
void bittorrent::resumeUnfinishedTorrents() {
|
||||
qDebug("Resuming unfinished torrents");
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QStringList fileNames;
|
||||
QStringList known_torrents = TorrentPersistentData::knownTorrents();
|
||||
// Scan torrentBackup directory
|
||||
QStringList filters;
|
||||
filters << "*.torrent";
|
||||
fileNames = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
if(isQueueingEnabled()) {
|
||||
QList<QPair<int, QString> > hashes;
|
||||
foreach(const QString &hash, known_torrents) {
|
||||
QString filePath;
|
||||
if(TorrentPersistentData::isMagnet(hash)) {
|
||||
filePath = TorrentPersistentData::getMagnetUri(hash);
|
||||
} else {
|
||||
filePath = torrentBackup.path()+QDir::separator()+hash+".torrent";
|
||||
QList<QPair<int, QString> > filePaths;
|
||||
foreach(QString fileName, fileNames) {
|
||||
QString filePath = torrentBackup.path()+QDir::separator()+fileName;
|
||||
int prio = 99999;
|
||||
// Get priority
|
||||
QString prioPath = filePath;
|
||||
prioPath.replace(".torrent", ".prio");
|
||||
if(QFile::exists(prioPath)) {
|
||||
QFile prio_file(prioPath);
|
||||
if(prio_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
bool ok = false;
|
||||
prio = prio_file.readAll().toInt(&ok);
|
||||
if(!ok)
|
||||
prio = 99999;
|
||||
prio_file.close();
|
||||
}
|
||||
int prio = TorrentPersistentData::getPriority(hash);
|
||||
misc::insertSort2<QString>(hashes, qMakePair(prio, hash));
|
||||
}
|
||||
misc::insertSort2<QString>(filePaths, qMakePair(prio, filePath));
|
||||
}
|
||||
// Resume downloads
|
||||
QPair<int, QString> couple;
|
||||
foreach(couple, hashes) {
|
||||
QString hash = couple.second;
|
||||
qDebug("Starting up torrent %s", hash.toLocal8Bit().data());
|
||||
if(TorrentPersistentData::isMagnet(hash)) {
|
||||
addMagnetUri(TorrentPersistentData::getMagnetUri(hash), true);
|
||||
} else {
|
||||
addTorrent(torrentBackup.path()+QDir::separator()+hash+".torrent", false, QString(), true);
|
||||
}
|
||||
QPair<int, QString> fileName;
|
||||
foreach(fileName, filePaths) {
|
||||
addTorrent(fileName.second, false, QString(), true);
|
||||
}
|
||||
} else {
|
||||
QStringList filePaths;
|
||||
foreach(QString fileName, fileNames) {
|
||||
filePaths.append(torrentBackup.path()+QDir::separator()+fileName);
|
||||
}
|
||||
// Resume downloads
|
||||
foreach(const QString &hash, known_torrents) {
|
||||
qDebug("Starting up torrent %s", hash.toLocal8Bit().data());
|
||||
if(TorrentPersistentData::isMagnet(hash))
|
||||
addMagnetUri(TorrentPersistentData::getMagnetUri(hash), true);
|
||||
else
|
||||
addTorrent(torrentBackup.path()+QDir::separator()+hash+".torrent", false, QString(), true);
|
||||
foreach(QString fileName, filePaths) {
|
||||
addTorrent(fileName, false, QString(), true);
|
||||
}
|
||||
}
|
||||
qDebug("Unfinished torrents resumed");
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#ifndef __BITTORRENT_H__
|
||||
@@ -60,7 +51,6 @@ class bittorrent : public QObject {
|
||||
bool DHTEnabled;
|
||||
QPointer<downloadThread> downloader;
|
||||
QString defaultSavePath;
|
||||
QString defaultTempPath;
|
||||
QHash<QString, QHash<QString, QString> > trackersErrors;
|
||||
QStringList consoleMessages;
|
||||
QStringList peerBanMessages;
|
||||
@@ -68,7 +58,7 @@ class bittorrent : public QObject {
|
||||
bool addInPause;
|
||||
int maxConnecsPerTorrent;
|
||||
int maxUploadsPerTorrent;
|
||||
float ratio_limit;
|
||||
float max_ratio;
|
||||
bool UPnPEnabled;
|
||||
bool NATPMPEnabled;
|
||||
bool LSDEnabled;
|
||||
@@ -76,7 +66,6 @@ class bittorrent : public QObject {
|
||||
QString filterPath;
|
||||
bool queueingEnabled;
|
||||
QStringList url_skippingDlg;
|
||||
QHash<QString, QString> savepath_fromurl;
|
||||
|
||||
protected:
|
||||
QString getSavePath(QString hash);
|
||||
@@ -108,22 +97,19 @@ class bittorrent : public QObject {
|
||||
QStringList getConsoleMessages() const;
|
||||
QStringList getPeerBanMessages() const;
|
||||
qlonglong getETA(QString hash) const;
|
||||
bool useTemporaryFolder() const;
|
||||
QString getDefaultSavePath() const;
|
||||
|
||||
public slots:
|
||||
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
|
||||
QTorrentHandle addMagnetUri(QString magnet_uri, bool resumed=false);
|
||||
void loadSessionState();
|
||||
void saveSessionState();
|
||||
void downloadFromUrl(QString url);
|
||||
void downloadFromURLList(const QStringList& url_list);
|
||||
void deleteTorrent(QString hash, bool permanent = false);
|
||||
void startUpTorrents();
|
||||
/* Needed by Web UI */
|
||||
void pauseAllTorrents();
|
||||
void resumeAllTorrents();
|
||||
void pauseTorrent(QString hash);
|
||||
void resumeTorrent(QString hash);
|
||||
void resumeAllTorrents();
|
||||
/* End Web UI */
|
||||
void saveDHTEntry();
|
||||
void preAllocateAllFiles(bool b);
|
||||
@@ -133,13 +119,15 @@ class bittorrent : public QObject {
|
||||
void enableIPFilter(QString filter);
|
||||
void disableIPFilter();
|
||||
void setQueueingEnabled(bool enable);
|
||||
void resumeUnfinishedTorrents();
|
||||
void saveTorrentPriority(QString hash, int prio);
|
||||
void saveTorrentSpeedLimits(QString hash);
|
||||
void loadTorrentSpeedLimits(QString hash);
|
||||
void handleDownloadFailure(QString url, QString reason);
|
||||
void loadWebSeeds(QString fileHash);
|
||||
void increaseDlTorrentPriority(QString hash);
|
||||
void decreaseDlTorrentPriority(QString hash);
|
||||
void downloadUrlAndSkipDialog(QString url, QString save_path=QString::null);
|
||||
void downloadUrlAndSkipDialog(QString);
|
||||
// Session configuration - Setters
|
||||
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);
|
||||
void setMaxConnections(int maxConnec);
|
||||
@@ -154,7 +142,6 @@ class bittorrent : public QObject {
|
||||
void setSessionSettings(session_settings sessionSettings);
|
||||
void startTorrentsInPause(bool b);
|
||||
void setDefaultSavePath(QString savepath);
|
||||
void setDefaultTempPath(QString temppath);
|
||||
void applyEncryptionSettings(pe_settings se);
|
||||
void loadFilesPriorities(QTorrentHandle& h);
|
||||
void setDownloadLimit(QString hash, long val);
|
||||
@@ -165,13 +152,13 @@ class bittorrent : public QObject {
|
||||
bool enableDHT(bool b);
|
||||
void addConsoleMessage(QString msg, QColor color=QApplication::palette().color(QPalette::WindowText));
|
||||
void addPeerBanMessage(QString msg, bool from_ipfilter);
|
||||
void processDownloadedFile(QString, QString);
|
||||
void saveTrackerFile(QString hash);
|
||||
|
||||
protected slots:
|
||||
void scanDirectory(QString);
|
||||
void readAlerts();
|
||||
void loadTrackerFile(QString hash);
|
||||
void processDownloadedFile(QString, QString);
|
||||
bool loadTrackerFile(QString hash);
|
||||
void saveTrackerFile(QString hash);
|
||||
void deleteBigRatios();
|
||||
|
||||
signals:
|
||||
@@ -180,15 +167,13 @@ class bittorrent : public QObject {
|
||||
void pausedTorrent(QTorrentHandle& h);
|
||||
void resumedTorrent(QTorrentHandle& h);
|
||||
void finishedTorrent(QTorrentHandle& h);
|
||||
void fullDiskError(QTorrentHandle& h, QString msg);
|
||||
void fullDiskError(QTorrentHandle& h);
|
||||
void trackerError(QString hash, QString time, QString msg);
|
||||
void trackerAuthenticationRequired(QTorrentHandle& h);
|
||||
void newDownloadedTorrent(QString path, QString url);
|
||||
void updateFileSize(QString hash);
|
||||
void downloadFromUrlFailure(QString url, QString reason);
|
||||
void torrentFinishedChecking(QTorrentHandle& h);
|
||||
void metadataReceived(QTorrentHandle &h);
|
||||
void torrentPaused(QTorrentHandle &h);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<string>qBittorrent console</string>
|
||||
</property>
|
||||
<property name="windowIcon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/oxygen/log.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
@@ -26,7 +26,7 @@
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<attribute name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/oxygen/log.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0" >
|
||||
<class>createTorrentDialog</class>
|
||||
<widget class="QDialog" name="createTorrentDialog" >
|
||||
@@ -7,7 +6,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>592</width>
|
||||
<height>658</height>
|
||||
<height>655</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
@@ -65,8 +64,7 @@
|
||||
<string>Add a file</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/add_file.png</normaloff>:/Icons/add_file.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/add_file.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -76,8 +74,7 @@
|
||||
<string>Add a folder</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/add_folder.png</normaloff>:/Icons/add_folder.png</iconset>
|
||||
<iconset resource="icons.qrc" >:/Icons/add_folder.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -153,7 +150,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -168,7 +174,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -176,7 +191,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
@@ -202,14 +217,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -231,14 +239,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -247,7 +248,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
@@ -264,7 +265,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -279,7 +289,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -287,7 +306,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
@@ -313,14 +332,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -342,14 +354,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -358,7 +363,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
@@ -448,7 +453,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
@@ -491,7 +496,16 @@
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -499,7 +513,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>131</width>
|
||||
<height>31</height>
|
||||
@@ -526,7 +540,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -184,6 +175,7 @@ void createtorrent::on_createButton_clicked(){
|
||||
|
||||
void createtorrent::handleCreationFailure(QString msg) {
|
||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(msg));
|
||||
hide();
|
||||
}
|
||||
|
||||
void createtorrent::handleCreationSuccess(QString path, const char* branch_path) {
|
||||
@@ -191,7 +183,7 @@ void createtorrent::handleCreationSuccess(QString path, const char* branch_path)
|
||||
// Create save path file
|
||||
boost::intrusive_ptr<torrent_info> t;
|
||||
try {
|
||||
t = new torrent_info(path.toLocal8Bit().data());
|
||||
t = new torrent_info(path.toUtf8().data());
|
||||
} catch(std::exception&) {
|
||||
QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
|
||||
return;
|
||||
@@ -204,7 +196,7 @@ void createtorrent::handleCreationSuccess(QString path, const char* branch_path)
|
||||
emit torrent_to_seed(path);
|
||||
}
|
||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+path);
|
||||
close();
|
||||
hide();
|
||||
}
|
||||
|
||||
void createtorrent::updateProgressBar(int progress) {
|
||||
@@ -227,12 +219,8 @@ void torrentCreatorThread::create(QString _input_path, QString _save_path, QStri
|
||||
start();
|
||||
}
|
||||
|
||||
void sendProgressUpdateSignal(int i, int num, torrentCreatorThread *parent){
|
||||
parent->sendProgressSignal((int)(i*100./(float)num));
|
||||
}
|
||||
|
||||
void torrentCreatorThread::sendProgressSignal(int progress) {
|
||||
emit updateProgress(progress);
|
||||
void sendProgressUpdateSignal(int i, int num, QDialog *parent){
|
||||
((createtorrent*)parent)->updateProgressBar((int)(i*100./(float)num));
|
||||
}
|
||||
|
||||
void torrentCreatorThread::run() {
|
||||
@@ -241,7 +229,7 @@ void torrentCreatorThread::run() {
|
||||
try {
|
||||
file_storage fs;
|
||||
file_pool fp;
|
||||
path full_path = complete(path(input_path.toLocal8Bit().data()));
|
||||
path full_path = complete(path(input_path.toUtf8().data()));
|
||||
// Adding files to the torrent
|
||||
add_files(fs, full_path, file_filter);
|
||||
if(abort) return;
|
||||
@@ -250,23 +238,25 @@ void torrentCreatorThread::run() {
|
||||
// Add url seeds
|
||||
QString seed;
|
||||
foreach(seed, url_seeds){
|
||||
t.add_url_seed(seed.toLocal8Bit().data());
|
||||
t.add_url_seed(seed.toUtf8().data());
|
||||
}
|
||||
for(int i=0; i<trackers.size(); ++i){
|
||||
t.add_tracker(trackers.at(i).toLocal8Bit().data());
|
||||
t.add_tracker(trackers.at(i).toUtf8().data());
|
||||
}
|
||||
if(abort) return;
|
||||
// calculate the hash for all pieces
|
||||
set_piece_hashes(t, full_path.branch_path(), boost::bind<void>(&sendProgressUpdateSignal, _1, t.num_pieces(), this));
|
||||
set_piece_hashes(t, full_path.branch_path(), boost::bind<void>(&sendProgressUpdateSignal, _1, t.num_pieces(), parent));
|
||||
// Set qBittorrent as creator and add user comment to
|
||||
// torrent_info structure
|
||||
t.set_creator(creator_str);
|
||||
t.set_comment((const char*)comment.toLocal8Bit());
|
||||
t.set_comment((const char*)comment.toUtf8());
|
||||
// Is private ?
|
||||
t.set_priv(is_private);
|
||||
if(is_private){
|
||||
t.set_priv(true);
|
||||
}
|
||||
if(abort) return;
|
||||
// create the torrent and print it to out
|
||||
ofstream out(complete(path((const char*)save_path.toLocal8Bit())), std::ios_base::binary);
|
||||
ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
|
||||
bencode(std::ostream_iterator<char>(out), t.generate());
|
||||
emit updateProgress(100);
|
||||
emit creationSuccess(save_path, full_path.branch_path().string().c_str());
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -57,7 +48,6 @@ class torrentCreatorThread : public QThread {
|
||||
wait();
|
||||
}
|
||||
void create(QString _input_path, QString _save_path, QStringList _trackers, QStringList _url_seeds, QString _comment, bool _is_private, int _piece_size);
|
||||
void sendProgressSignal(int progress);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
@@ -65,8 +55,6 @@ class torrentCreatorThread : public QThread {
|
||||
signals:
|
||||
void creationFailure(QString msg);
|
||||
void creationSuccess(QString path, const char* branch_path);
|
||||
|
||||
signals:
|
||||
void updateProgress(int progress);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0" >
|
||||
<class>downloading</class>
|
||||
<widget class="QWidget" name="downloading" >
|
||||
@@ -93,7 +92,7 @@
|
||||
<action name="actionOpen_destination_folder" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >
|
||||
<normaloff>:/Icons/oxygen/folder.png</normaloff>:/Icons/oxygen/folder.png</iconset>
|
||||
<normaloff>:/Icons/folder.png</normaloff>:/Icons/folder.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Open destination folder</string>
|
||||
@@ -174,17 +173,12 @@
|
||||
<action name="actionForce_recheck" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >
|
||||
<normaloff>:/Icons/oxygen/gear.png</normaloff>:/Icons/oxygen/gear.png</iconset>
|
||||
<normaloff>:/Icons/gear.png</normaloff>:/Icons/gear.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Force recheck</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCopy_magnet_link">
|
||||
<property name="text">
|
||||
<string>Copy magnet link</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc" />
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -36,7 +27,6 @@
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
#include <QStringList>
|
||||
#include <QClipboard>
|
||||
#include "ui_downloadFromURL.h"
|
||||
|
||||
class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
@@ -48,11 +38,6 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
icon_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/url.png")));
|
||||
show();
|
||||
// Paste clipboard if there is an URL in it
|
||||
QString clip_txt = qApp->clipboard()->text();
|
||||
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
textUrls->setText(clip_txt);
|
||||
}
|
||||
}
|
||||
|
||||
~downloadFromURL(){}
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -84,7 +75,7 @@ void subDownloadThread::run(){
|
||||
filePath = tmpfile->fileName();
|
||||
}
|
||||
delete tmpfile;
|
||||
FILE *f = fopen(filePath.toLocal8Bit().data(), "wb");
|
||||
FILE *f = fopen(filePath.toUtf8().data(), "wb");
|
||||
if(!f) {
|
||||
std::cerr << "couldn't open destination file" << "\n";
|
||||
return;
|
||||
@@ -93,7 +84,7 @@ void subDownloadThread::run(){
|
||||
CURLcode res = (CURLcode)-1;
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
std::string c_url = url.toLocal8Bit().data();
|
||||
std::string c_url = url.toUtf8().data();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, c_url.c_str());
|
||||
// SSL support
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
@@ -105,8 +96,8 @@ void subDownloadThread::run(){
|
||||
// Proxy enabled
|
||||
QString IP = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/IP"), "0.0.0.0").toString();
|
||||
QString port = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/Port"), 8080).toString();
|
||||
qDebug("Using proxy: %s", (IP+QString(":")+port).toLocal8Bit().data());
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYPORT, (IP+QString(":")+port).toLocal8Bit().data());
|
||||
qDebug("Using proxy: %s", (IP+QString(":")+port).toUtf8().data());
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYPORT, (IP+QString(":")+port).toUtf8().data());
|
||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||
if(intValue%2==0) {
|
||||
qDebug("Proxy is SOCKS5, not HTTP");
|
||||
@@ -117,7 +108,7 @@ void subDownloadThread::run(){
|
||||
qDebug("Proxy requires authentication, authenticating");
|
||||
QString username = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/Username"), QString()).toString();
|
||||
QString password = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/Password"), QString()).toString();
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, (username+QString(":")+password).toLocal8Bit().data());
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, (username+QString(":")+password).toUtf8().data());
|
||||
}
|
||||
}
|
||||
// We have to define CURLOPT_WRITEFUNCTION or it will crash on windows
|
||||
@@ -131,7 +122,7 @@ void subDownloadThread::run(){
|
||||
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, -1);
|
||||
qDebug("Downloading %s", url.toLocal8Bit().data());
|
||||
qDebug("Downloading %s", url.toUtf8().data());
|
||||
if(!abort)
|
||||
res = curl_easy_perform(curl);
|
||||
/* always cleanup */
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,15 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#include "downloadingTorrents.h"
|
||||
@@ -53,9 +44,8 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
|
||||
actionSet_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png")));
|
||||
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
|
||||
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
|
||||
actionCopy_magnet_link->setIcon(QIcon(QString::fromUtf8(":/Icons/magnet.png")));
|
||||
// tabBottom->setTabIcon(0, QIcon(QString::fromUtf8(":/Icons/oxygen/log.png")));
|
||||
// tabBottom->setTabIcon(1, QIcon(QString::fromUtf8(":/Icons/oxygen/filter.png")));
|
||||
// tabBottom->setTabIcon(0, QIcon(QString::fromUtf8(":/Icons/log.png")));
|
||||
// tabBottom->setTabIcon(1, QIcon(QString::fromUtf8(":/Icons/filter.png")));
|
||||
|
||||
// Set Download list model
|
||||
DLListModel = new QStandardItemModel(0,10);
|
||||
@@ -69,8 +59,6 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
|
||||
DLListModel->setHeaderData(ETA, Qt::Horizontal, tr("ETA", "i.e: Estimated Time of Arrival / Time left"));
|
||||
DLListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority"));
|
||||
downloadList->setModel(DLListModel);
|
||||
downloadList->setRootIsDecorated(false);
|
||||
downloadList->setAllColumnsShowFocus(true);
|
||||
DLDelegate = new DLListDelegate(downloadList);
|
||||
downloadList->setItemDelegate(DLDelegate);
|
||||
// Hide priority column
|
||||
@@ -80,7 +68,6 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
|
||||
loadHiddenColumns();
|
||||
|
||||
connect(BTSession, SIGNAL(torrentFinishedChecking(QTorrentHandle&)), this, SLOT(sortProgressColumn(QTorrentHandle&)));
|
||||
connect(BTSession, SIGNAL(metadataReceived(QTorrentHandle&)), this, SLOT(updateMetadata(QTorrentHandle&)));
|
||||
|
||||
// Load last columns width for download list
|
||||
if(!loadColWidthDLList()) {
|
||||
@@ -107,7 +94,6 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
|
||||
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
|
||||
connect(actionForce_recheck, SIGNAL(triggered()), this, SLOT(forceRecheck()));
|
||||
connect(actionBuy_it, SIGNAL(triggered()), (GUI*)parent, SLOT(goBuyPage()));
|
||||
connect(actionCopy_magnet_link, SIGNAL(triggered()), (GUI*)parent, SLOT(copyMagnetURI()));
|
||||
|
||||
connect(actionHOSColName, SIGNAL(triggered()), this, SLOT(hideOrShowColumnName()));
|
||||
connect(actionHOSColSize, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSize()));
|
||||
@@ -176,13 +162,11 @@ void DownloadingTorrents::showProperties(const QModelIndex &index) {
|
||||
|
||||
void DownloadingTorrents::showPropertiesFromHash(QString hash) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.has_metadata()) {
|
||||
properties *prop = new properties(this, BTSession, h);
|
||||
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSizeAndProgress(QString)));
|
||||
connect(prop, SIGNAL(trackersChanged(QString)), BTSession, SLOT(saveTrackerFile(QString)));
|
||||
prop->show();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a torrent from the download list but NOT from the BT Session
|
||||
void DownloadingTorrents::deleteTorrent(QString hash) {
|
||||
@@ -198,8 +182,9 @@ void DownloadingTorrents::deleteTorrent(QString hash) {
|
||||
|
||||
void DownloadingTorrents::on_actionSet_download_limit_triggered() {
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
QStringList hashes;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file hash
|
||||
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
@@ -211,8 +196,9 @@ void DownloadingTorrents::on_actionSet_download_limit_triggered() {
|
||||
|
||||
void DownloadingTorrents::on_actionSet_upload_limit_triggered() {
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
QStringList hashes;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file hash
|
||||
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
@@ -225,7 +211,8 @@ void DownloadingTorrents::on_actionSet_upload_limit_triggered() {
|
||||
// display properties of selected items
|
||||
void DownloadingTorrents::propertiesSelection(){
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == NAME){
|
||||
showProperties(index);
|
||||
}
|
||||
@@ -234,34 +221,29 @@ void DownloadingTorrents::propertiesSelection(){
|
||||
|
||||
void DownloadingTorrents::forceRecheck() {
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == NAME){
|
||||
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.has_metadata())
|
||||
h.force_recheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadingTorrents::displayDLListMenu(const QPoint&) {
|
||||
void DownloadingTorrents::displayDLListMenu(const QPoint& pos) {
|
||||
QMenu myDLLlistMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
bool has_pause = false, has_start = false, has_preview = false;
|
||||
bool one_has_metadata = false;
|
||||
QTorrentHandle h;
|
||||
qDebug("Displaying menu");
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file name
|
||||
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
// Get handle and pause the torrent
|
||||
h = BTSession->getTorrentHandle(hash);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()) continue;
|
||||
if(h.has_metadata()) {
|
||||
one_has_metadata = true;
|
||||
}
|
||||
if(h.is_paused()) {
|
||||
if(!has_start) {
|
||||
myDLLlistMenu.addAction(actionStart);
|
||||
@@ -273,7 +255,7 @@ void DownloadingTorrents::displayDLListMenu(const QPoint&) {
|
||||
has_pause = true;
|
||||
}
|
||||
}
|
||||
if(h.has_metadata() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
|
||||
if(BTSession->isFilePreviewPossible(hash) && !has_preview) {
|
||||
myDLLlistMenu.addAction(actionPreview_file);
|
||||
has_preview = true;
|
||||
}
|
||||
@@ -287,12 +269,9 @@ void DownloadingTorrents::displayDLListMenu(const QPoint&) {
|
||||
myDLLlistMenu.addAction(actionSet_download_limit);
|
||||
myDLLlistMenu.addAction(actionSet_upload_limit);
|
||||
myDLLlistMenu.addSeparator();
|
||||
if(one_has_metadata) {
|
||||
myDLLlistMenu.addAction(actionForce_recheck);
|
||||
myDLLlistMenu.addSeparator();
|
||||
}
|
||||
myDLLlistMenu.addAction(actionOpen_destination_folder);
|
||||
if(one_has_metadata)
|
||||
myDLLlistMenu.addAction(actionTorrent_Properties);
|
||||
if(BTSession->isQueueingEnabled()) {
|
||||
myDLLlistMenu.addSeparator();
|
||||
@@ -300,10 +279,10 @@ void DownloadingTorrents::displayDLListMenu(const QPoint&) {
|
||||
myDLLlistMenu.addAction(actionDecreasePriority);
|
||||
}
|
||||
myDLLlistMenu.addSeparator();
|
||||
myDLLlistMenu.addAction(actionCopy_magnet_link);
|
||||
myDLLlistMenu.addAction(actionBuy_it);
|
||||
// Call menu
|
||||
myDLLlistMenu.exec(QCursor::pos());
|
||||
// XXX: why mapToGlobal() is not enough?
|
||||
myDLLlistMenu.exec(mapToGlobal(pos)+QPoint(10,35));
|
||||
}
|
||||
|
||||
|
||||
@@ -343,12 +322,12 @@ void DownloadingTorrents::hideOrShowColumn(int index) {
|
||||
if(nbVisibleColumns <= 1) return;
|
||||
// User can hide the column, do it.
|
||||
downloadList->setColumnHidden(index, true);
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
--nbVisibleColumns;
|
||||
} else {
|
||||
// User want to display the column
|
||||
downloadList->setColumnHidden(index, false);
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
++nbVisibleColumns;
|
||||
}
|
||||
//resize all others non-hidden columns
|
||||
@@ -362,9 +341,9 @@ void DownloadingTorrents::hideOrShowColumn(int index) {
|
||||
void DownloadingTorrents::hidePriorityColumn(bool hide) {
|
||||
downloadList->setColumnHidden(PRIORITY, hide);
|
||||
if(hide)
|
||||
getActionHoSCol(PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
getActionHoSCol(PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
else
|
||||
getActionHoSCol(PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
getActionHoSCol(PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
}
|
||||
|
||||
// save the hidden columns in settings
|
||||
@@ -402,9 +381,9 @@ bool DownloadingTorrents::loadHiddenColumns() {
|
||||
for(int i=0; i<DLListModel->columnCount()-1; i++) {
|
||||
if(loaded && ishidden_list.at(i) == "0") {
|
||||
downloadList->setColumnHidden(i, true);
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
} else {
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
@@ -483,8 +462,9 @@ QAction* DownloadingTorrents::getActionHoSCol(int index) {
|
||||
|
||||
QStringList DownloadingTorrents::getSelectedTorrents(bool only_one) const{
|
||||
QStringList res;
|
||||
QModelIndex index;
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file hash
|
||||
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
@@ -495,20 +475,9 @@ QStringList DownloadingTorrents::getSelectedTorrents(bool only_one) const{
|
||||
return res;
|
||||
}
|
||||
|
||||
void DownloadingTorrents::updateMetadata(QTorrentHandle &h) {
|
||||
QString hash = h.hash();
|
||||
int row = getRowFromHash(hash);
|
||||
if(row != -1) {
|
||||
qDebug("Updating torrent metadata in download list");
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
|
||||
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
}
|
||||
}
|
||||
|
||||
// get information from torrent handles and
|
||||
// update download list accordingly
|
||||
bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
|
||||
if(!h.is_valid()) return false;
|
||||
bool added = false;
|
||||
try{
|
||||
QString hash = h.hash();
|
||||
@@ -525,7 +494,7 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
|
||||
DLListModel->setData(DLListModel->index(row, PRIORITY), QVariant((int)BTSession->getDlTorrentPriority(hash)));
|
||||
if(h.is_queued()) {
|
||||
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking) {
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
if(!downloadList->isColumnHidden(PROGRESS)) {
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
}
|
||||
@@ -552,7 +521,7 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
|
||||
switch(h.state()) {
|
||||
case torrent_status::checking_files:
|
||||
case torrent_status::queued_for_checking:
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
break;
|
||||
case torrent_status::downloading:
|
||||
@@ -583,13 +552,7 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
|
||||
}
|
||||
}
|
||||
if(!downloadList->isColumnHidden(SEEDSLEECH)) {
|
||||
QString tmp = misc::toQString(h.num_seeds(), true);
|
||||
if(h.num_complete() >= 0)
|
||||
tmp.append(QString("(")+misc::toQString(h.num_complete())+QString(")"));
|
||||
tmp.append(QString("/")+misc::toQString(h.num_peers() - h.num_seeds(), true));
|
||||
if(h.num_incomplete() >= 0)
|
||||
tmp.append(QString("(")+misc::toQString(h.num_incomplete())+QString(")"));
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(tmp));
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(misc::toQString(h.num_seeds(), true)+QString::fromUtf8("/")+misc::toQString(h.num_peers() - h.num_seeds(), true)));
|
||||
}
|
||||
if(!downloadList->isColumnHidden(RATIO)) {
|
||||
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
|
||||
@@ -601,7 +564,7 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
|
||||
void DownloadingTorrents::addTorrent(QString hash) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
int row = getRowFromHash(hash);
|
||||
qDebug("DL: addTorrent(): %s, row: %d", (const char*)hash.toLocal8Bit(), row);
|
||||
qDebug("DL: addTorrent(): %s, row: %d", (const char*)hash.toUtf8(), row);
|
||||
if(row != -1) return;
|
||||
row = DLListModel->rowCount();
|
||||
// Adding torrent to download list
|
||||
@@ -612,7 +575,6 @@ void DownloadingTorrents::addTorrent(QString hash) {
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
DLListModel->setData(DLListModel->index(row, RATIO), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
if(BTSession->isQueueingEnabled())
|
||||
DLListModel->setData(DLListModel->index(row, PRIORITY), QVariant((int)BTSession->getDlTorrentPriority(hash)));
|
||||
@@ -752,7 +714,7 @@ void DownloadingTorrents::saveColWidthDLList() const{
|
||||
width_list = line.split(' ');
|
||||
}
|
||||
for(short i=0; i<nbColumns; ++i){
|
||||
if(downloadList->columnWidth(i)<1 && width_list.size() == nbColumns && width_list.at(i).toInt()>=1) {
|
||||
if(downloadList->columnWidth(i)<1 && width_list.size() == DLListModel->columnCount()-1 && width_list.at(i).toInt()>=1) {
|
||||
// load the former width
|
||||
new_width_list << width_list.at(i);
|
||||
} else if(downloadList->columnWidth(i)>=1) {
|
||||
@@ -765,11 +727,6 @@ void DownloadingTorrents::saveColWidthDLList() const{
|
||||
}
|
||||
}
|
||||
settings.setValue(QString::fromUtf8("DownloadListColsWidth"), new_width_list.join(QString::fromUtf8(" ")));
|
||||
QVariantList visualIndexes;
|
||||
for(int i=0; i<nbColumns; ++i) {
|
||||
visualIndexes.append(downloadList->header()->visualIndex(i));
|
||||
}
|
||||
settings.setValue(QString::fromUtf8("DownloadListVisualIndexes"), visualIndexes);
|
||||
qDebug("Download list columns width saved");
|
||||
}
|
||||
|
||||
@@ -790,23 +747,6 @@ bool DownloadingTorrents::loadColWidthDLList() {
|
||||
for(unsigned int i=0; i<listSize; ++i) {
|
||||
downloadList->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
QVariantList visualIndexes = settings.value(QString::fromUtf8("DownloadListVisualIndexes"), QVariantList()).toList();
|
||||
if(visualIndexes.size() != DLListModel->columnCount()-1) {
|
||||
qDebug("Corrupted values for download list columns sizes");
|
||||
return false;
|
||||
}
|
||||
bool change = false;
|
||||
do {
|
||||
change = false;
|
||||
for(int i=0;i<visualIndexes.size(); ++i) {
|
||||
int new_visual_index = visualIndexes.at(downloadList->header()->logicalIndex(i)).toInt();
|
||||
if(i != new_visual_index) {
|
||||
qDebug("Moving column from %d to %d", downloadList->header()->logicalIndex(i), new_visual_index);
|
||||
downloadList->header()->moveSection(i, new_visual_index);
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}while(change);
|
||||
qDebug("Download list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||