Compare commits

..

1 Commits

Author SHA1 Message Date
Christophe Dumez
ec1521c2ca - tagged v1.2.0beta3 release 2008-08-17 04:00:52 +00:00
232 changed files with 33030 additions and 40681 deletions

23
AUTHORS
View File

@@ -6,35 +6,24 @@ Contributors:
* Ishan Arora <ishan@qbittorrent.org>
* Grigis Gaëtan <cipher16@gmail.com>
Code from other projects:
* files src/ico.cpp src/ico.h
copyright: Malte Starostik <malte@kde.org>
license: LGPL
Images Authors:
* files: src/Icons/*.png
copyright: Gnome Icon Theme
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
url: http://www.openclipart.org
* files: src/Icons/skin/*.png
files: src/menuicons/YYxYY/*.png
* files: src/Icons/skins/*.png
copyright: Mateusz Tobola <tobejodok@qbittorrent.org>
license: GPLv2
* file: src/Icons/skin/tabs.gif
copyright: Greg Houston <gregory.houston@gmail.com>
license: MIT
* files: src/menuicons/YYxYY/*.png
copyright: Mateusz Tobola <tobejodok@qbittorrent.org>
license: GPLv2
* file: src/search_engine/engines/btjunkie.png
copyright: Downloaded from btjunkie.org
@@ -57,9 +46,7 @@ Translations authors:
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
- Bulgarian: Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)
- Catalan: Gekko Dam Beer (gekko04@users.sourceforge.net)
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
- Czech: Jirka Vilim (web@tets.cz)
- Chinese (Simplified): Guo Yue (guoyue0418@hotmail.com)
- Danish: Mathias Nielsen (comoneo@gmail.com)
- Dutch: Joost Schipper (heavyjoost@users.sourceforge.net)
- English: Christophe Dumez (chris@qbittorrent.org)

14
COPYING
View File

@@ -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

135
Changelog
View File

@@ -1,143 +1,14 @@
* Sun Aug 21 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.1
- BUGFIX: Fix problems when changing save path (if using temporary download folder)
- BUGFIX: Display real save path instead of the temporary one in torrent properties
- BUGFIX: Catching invalid_handle exception to avoid rare crashes
- BUGFIX: Fixed popup menu position in RSS feeds list
- BUGFIX: Don't save RSS feed state if it could not be updated
* 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
- FEATURE: Torrent creation code cleanup
- FEATURE: Allow to set maximum number of active seeds (queueing)
- FEATURE: Now seeds priorities are handled automatically by libtorrent-rasterbar (queueing)
- FEATURE: Code cleanup and optimization (save memory and cpu)
- FEATURE: ETA calculation now relies on average speed over all sessions
- FEATURE: Allow to force rechecking torrents
- FEATURE: Added support for 2 new extensions (uTorrent metadata and smart ban plugin)
- FEATURE: Allow to change the save path of torrents after addition
- FEATURE: Got rid of libmagick++ dependency
- FEATURE: Updated Web interface to MochaUI v0.9.5
- FEATURE: Added notification in WebUI when qBittorrent is not reachable
- FEATURE: Rewrote folder scanning code (Now uses a filesystem watcher)
- FEATURE: Added torrent deletion from hard drive function in Web UI
- FEATURE: Added queueing priority actions in Web UI
- FEATURE: Display progress using progress bars in Web UI
- BUGFIX: Made usage of fastresume data more reliable
- BUGFIX: qBittorrent shutdown is now faster
- BUGFIX: Fixed several memory leaks
- BUGFIX: WebUI is now working with IE7
- BUGFIX: Fixed spacing problem in toolbar when toggling its visibility
- BUGFIX: Fixed some compilation and Qt4 warnings
- BUGFIX: Do not use an addition dialog for torrents from folder scanning
- BUGFIX: Catch SIGTERM to exit cleanly (e.g. computer shutdown)
- BUGFIX: Improved proxy support code
- BUGFIX: Fixed systray icon tooltip on Windows
- BUGFIX: Proxy settings are now saved even if disabled
* Sun Nov 9 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.1
- BUGFIX: Fixed possible crash when deleting a torrent permanently
- BUGFIX: Queued_for_checking torrents were not displayed as checking in seeding list
- BUGFIX: Speed up startup time when having a lot of torrents
* Wed Oct 29th 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.0
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.2.0
- FEATURE: Torrent queueing system (with priorities)
- FEATURE: DHT is always ON (no longer used as fallback)
- FEATURE: The number of DHT nodes is displayed
- FEATURE: RSS can now be disabled from program preferences
- FEATURE: Added collapse/expand all buttons in addition and properties dialogs
- FEATURE: Can have different proxies for Bittorrent and search engine
- FEATURE: Allow multiple item selection in Web UI transfer list
- FEATURE: Moved uploads to a separate list in Web UI
- BUGFIX: Totally rewritten Web UI list refresh system (fixed memory leak)
- BUGFIX: Disable ETA calculation when ETA column is hidden
- BUGFIX: Removed "disconnected" connection state, detection was far from perfect
- BUGFIX: Torrents are no longer starting from scratch when changing default save path (when torrent addition dialog is disabled)
- BUGFIX: Single instance code is now more reliable on Qt >= 4.4
- COSMETIC: Transfer speed, ratio, connection status and DHT nodes are displayed in status bar
- COSMETIC: RSS Tab is now hidden as a default
- COSMETIC: Allow to hide or display top toolbar
- COSMETIC: Log is now in a separate dialog
* Sun Sept 14 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.1.4
- FEATURE: DHT is no longer used as fallback only
- FEATURE: Ported WebUI to Mootools v1.2
- BUGFIX: Fixed 'start seeding after torrent creation' feature
- BUGFIX: Fixed compilation with boost v1.36
- BUGFIX: Some code optimization
- BUGFIX: Fixed memory leak in Web UI
- BUGFIX: Fixed problems with column sorting
- BUGFIX: Improved code for pausing torrents on startup
- BUGFIX: Torrent addition dialog is now disabled for downloads from WebUI
- BUGFIX: Give focus to input field in WebUI download dialog
* Tue Aug 26 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.1.3
- BUGFIX: Fixed ratio saving for seeding torrents
- I18N: Added czech and traditional chinese translations
* Sun Aug 17 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.1.2
- BUGFIX: Fixed progress calculation
- BUGFIX: Fixed finished torrent detection
* Fri Aug 01 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.1.1
- BUGFIX: Fixed bad resource file for icons
- COSMETIC: Top toolbar is now hidden as a default
* Fri Aug 01 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.1.0
- FEATURE: Web interface to control qbittorrent (Ishan Arora)

View File

@@ -17,7 +17,7 @@ Dependencies:
- Qt >= 4.3.0 (libqt-devel, libqtgui, libqtcore, libqtnetwork, libqtxml)
Qt >= 4.4.0 is advised
- libtorrent-rasterbar by Arvid Norberg (>= v0.14.0 REQUIRED)
- libtorrent-rasterbar by Arvid Norberg (>= v0.13.1 REQUIRED)
-> http://www.qbittorrent.org/download.php (advised)
-> http://www.libtorrent.net
Be careful: another library (the one used by rTorrent) uses a similar name.

2
TODO
View File

@@ -1,2 +1,4 @@
See https://blueprints.launchpad.net/qbittorrent/
// in v1.2.0
- Split download and uploads in Web UI (Ishan Ahora)

216
configure vendored
View File

@@ -18,12 +18,20 @@ Main options:
--help This help text.
Dependency options:
--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
--disable-libzzip Disable use of libzzip
--with-libzzip-inc=[path] Path to libzzip++ include files
--with-libzzip-lib=[path] Path to libzzip++ library files
--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
--disable-libmagick Disable use of libmagick
--with-libmagick-inc=[path] Path to libmagick++ include files
--with-libmagick-lib=[path] Path to libmagick++ library files
--disable-libzzip Disable use of libzzip
--with-libzzip-inc=[path] Path to libzzip++ include files
--with-libzzip-lib=[path] Path to libzzip++ library files
EOT
}
@@ -140,6 +148,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
@@ -155,6 +178,21 @@ while [ $# -gt 0 ]; do
shift
;;
--disable-libmagick)
QC_DISABLE_libmagick="Y"
shift
;;
--with-libmagick-inc=*)
QC_WITH_LIBMAGICK_INC=$optarg
shift
;;
--with-libmagick-lib=*)
QC_WITH_LIBMAGICK_LIB=$optarg
shift
;;
--disable-libzzip)
QC_DISABLE_libzzip="Y"
shift
@@ -191,9 +229,15 @@ 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
echo QC_DISABLE_libmagick=$QC_DISABLE_libmagick
echo QC_WITH_LIBMAGICK_INC=$QC_WITH_LIBMAGICK_INC
echo QC_WITH_LIBMAGICK_LIB=$QC_WITH_LIBMAGICK_LIB
echo QC_DISABLE_libzzip=$QC_DISABLE_libzzip
echo QC_WITH_LIBZZIP_INC=$QC_WITH_LIBZZIP_INC
echo QC_WITH_LIBZZIP_LIB=$QC_WITH_LIBZZIP_LIB
@@ -323,29 +367,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.13"; }
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))
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());
QString s;
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "libtorrent/lsd.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;
}
};
@@ -468,6 +553,86 @@ public:
return true;
}
};
#line 1 "libmagick.qcm"
/*
-----BEGIN QCMOD-----
name: libmagick
arg: with-libmagick-inc=[path], Path to libmagick++ include files
arg: with-libmagick-lib=[path], Path to libmagick++ library files
-----END QCMOD-----
*/
#include <QProcess>
class qc_libmagick : public ConfObj
{
public:
qc_libmagick(Conf *c) : ConfObj(c) {}
QString name() const { return "ImageMagick library (libmagick++)"; }
QString shortname() const { return "libmagick++"; }
QString checkString() const {
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
return "";
return ConfObj::checkString();
}
bool exec(){
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
return false;
QString s;
s = conf->getenv("QC_WITH_LIBMAGICK_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "Magick++.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "Magick++.h")){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "Magick++")) {
return false;
}
}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, "Magick++")) {
found = true;
break;
}
}
if(!found)
return false;
}
conf->addLib(QString("-L") + s);
QProcess magickConfig;
QStringList params;
params << "--libs";
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;
}
};
#line 1 "libzzip.qcm"
/*
-----BEGIN QCMOD-----
@@ -555,6 +720,9 @@ cat >$1/modules_new.cpp <<EOT
o = new qc_libcurl(conf);
o->required = true;
o->disabled = false;
o = new qc_libmagick(conf);
o->required = false;
o->disabled = false;
o = new qc_libzzip(conf);
o->required = false;
o->disabled = false;
@@ -1503,9 +1671,15 @@ 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
export QC_DISABLE_libmagick
export QC_WITH_LIBMAGICK_INC
export QC_WITH_LIBMAGICK_LIB
export QC_DISABLE_libzzip
export QC_WITH_LIBZZIP_INC
export QC_WITH_LIBZZIP_LIB

View File

@@ -15,5 +15,6 @@
<dep type='libcurl'>
<required/>
</dep>
<dep type='libmagick'/>
<dep type='libzzip'/>
</qconf>

65
qcm/libcommoncpp2.qcm Normal file
View 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;
}
};

View File

@@ -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", "");
params << "--libs";
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;

View File

@@ -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.13"; }
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))
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());
QString s;
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "libtorrent/lsd.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;
}
};

View File

@@ -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,10 +72,7 @@ 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)));
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
break;
}
case PROGRESS:{

View File

@@ -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,10 @@
#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_PRIORITY 5
#define F_HASH 6
class FinishedListDelegate: public QItemDelegate {
Q_OBJECT
@@ -64,7 +52,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,10 +64,7 @@ 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)));
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
break;
}
default:

View File

@@ -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,18 +37,18 @@ 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);
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
finishedListModel = new QStandardItemModel(0,7);
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"));
finishedListModel->setHeaderData(F_PRIORITY, Qt::Horizontal, tr("Priority"));
finishedList->setModel(finishedListModel);
finishedList->setRootIsDecorated(false);
finishedList->setAllColumnsShowFocus(true);
loadHiddenColumns();
// Hide priority column
finishedList->hideColumn(F_PRIORITY);
// Hide hash column
finishedList->hideColumn(F_HASH);
// Load last columns width for download list
@@ -67,13 +58,14 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
// Make download list header clickable for sorting
finishedList->header()->setClickable(true);
finishedList->header()->setSortIndicatorShown(true);
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(toggleFinishedListSortOrder(int)));
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortFinishedList(int)));
finishedListDelegate = new FinishedListDelegate(finishedList);
finishedList->setItemDelegate(finishedListDelegate);
connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&)));
finishedList->header()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(finishedList->header(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedHoSMenu(const QPoint&)));
connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
connect(BTSession, SIGNAL(forceFinishedListUpdate()), this, SLOT(updateFinishedList()));
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
@@ -82,20 +74,20 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
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()));
connect(actionIncreasePriority, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionIncreasePriority_triggered()));
connect(actionDecreasePriority, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDecreasePriority_triggered()));
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_triggered()));
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
connect(actionOpen_destination_folder, SIGNAL(triggered()), (GUI*)parent, SLOT(openDestinationFolder()));
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(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()));
connect(actionHOSColPriority, SIGNAL(triggered()), this, SLOT(hideOrShowColumnPriority()));
}
FinishedTorrents::~FinishedTorrents(){
@@ -111,7 +103,14 @@ void FinishedTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
emit torrentDoubleClicked(hash, true);
}
void FinishedTorrents::hidePriorityColumn(bool hide) {
finishedList->setColumnHidden(F_PRIORITY, hide);
}
void FinishedTorrents::addTorrent(QString hash){
if(!BTSession->isFinished(hash)){
BTSession->setFinishedTorrent(hash);
}
int row = getRowFromHash(hash);
if(row != -1) return;
row = finishedListModel->rowCount();
@@ -121,10 +120,10 @@ 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())));
if(BTSession->isQueueingEnabled())
finishedListModel->setData(finishedListModel->index(row, F_PRIORITY), QVariant((int)BTSession->getUpTorrentPriority(hash)));
finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash));
if(h.is_paused()) {
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(":/Icons/skin/paused.png"), Qt::DecorationRole);
@@ -136,8 +135,13 @@ void FinishedTorrents::addTorrent(QString hash){
// Update the number of finished torrents
++nbFinished;
emit finishedTorrentsNumberChanged(nbFinished);
// Sort List
sortFinishedList();
}
void FinishedTorrents::torrentAdded(QString, QTorrentHandle& h, bool) {
QString hash = h.hash();
if(BTSession->isFinished(hash)) {
addTorrent(hash);
}
}
// Set the color of a row in data model
@@ -150,8 +154,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();
@@ -181,44 +186,10 @@ bool FinishedTorrents::loadColWidthFinishedList(){
for(unsigned int i=0; i<listSize; ++i){
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;
}
void FinishedTorrents::loadLastSortedColumn() {
// Loading last sorted column
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString sortedCol = settings.value(QString::fromUtf8("FinishedListSortedCol"), QString()).toString();
if(!sortedCol.isEmpty()) {
Qt::SortOrder sortOrder;
if(sortedCol.endsWith(QString::fromUtf8("d")))
sortOrder = Qt::DescendingOrder;
else
sortOrder = Qt::AscendingOrder;
sortedCol = sortedCol.left(sortedCol.size()-1);
int index = sortedCol.toInt();
sortFinishedList(index, sortOrder);
}
}
// Save columns width in a file to remember them
// (finished list)
void FinishedTorrents::saveColWidthFinishedList() const{
@@ -233,7 +204,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) {
@@ -246,18 +217,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();
@@ -266,9 +233,15 @@ void FinishedTorrents::on_actionSet_upload_limit_triggered(){
new BandwidthAllocationDialog(this, true, BTSession, hashes);
}
void FinishedTorrents::updateTorrent(QTorrentHandle h) {
if(!h.is_valid()) return;
QString hash = h.hash();
void FinishedTorrents::updateFinishedList(){
QString hash;
QStringList finishedSHAs = BTSession->getFinishedTorrents();
foreach(hash, finishedSHAs){
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()){
qDebug("Problem: This torrent is not valid in finished list");
continue;
}
int row = getRowFromHash(hash);
if(row == -1){
qDebug("Cannot find torrent in finished list, adding it");
@@ -276,42 +249,50 @@ 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);
} 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");
// Update priority
if(BTSession->isQueueingEnabled()) {
finishedListModel->setData(finishedListModel->index(row, F_PRIORITY), QVariant((int)BTSession->getUpTorrentPriority(hash)));
if(h.is_paused() && BTSession->isUploadQueued(hash)) {
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
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);
if(h.is_paused()) continue;
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) != -1) {
continue;
}
if(h.state() == torrent_status::downloading || (h.state() != torrent_status::checking_files && h.state() != torrent_status::queued_for_checking && h.progress() < 1.)) {
// What are you doing here? go back to download tab!
int reponse = QMessageBox::question(this, tr("Incomplete torrent in seeding list"), tr("It appears that the state of '%1' torrent changed from 'seeding' to 'downloading'. Would you like to move it back to download list? (otherwise the torrent will simply be deleted)").arg(h.name()), QMessageBox::Yes | QMessageBox::No);
if (reponse == QMessageBox::Yes) {
qDebug("Info: a torrent was moved from finished to download tab");
deleteTorrent(hash);
BTSession->setUnfinishedTorrent(hash);
emit torrentMovedFromFinishedList(hash);
}
else if (reponse == QMessageBox::No) {
qDebug("Deleted from the finished");
BTSession->deleteTorrent(hash, true);
}
continue;
}
if(h.state() == torrent_status::checking_files){
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
return;
continue;
}
setRowColor(row, QString::fromUtf8("orange"));
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
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))));
}
}
}
int FinishedTorrents::getRowFromHash(QString hash) const{
@@ -331,10 +312,17 @@ 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"));
}
void FinishedTorrents::resumeTorrent(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("orange"));
}
QString FinishedTorrents::getHashFromRow(unsigned int row) const {
Q_ASSERT(row < (unsigned int)finishedListModel->rowCount());
return finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
@@ -374,31 +362,21 @@ 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);
}
}
}
void FinishedTorrents::forceRecheck(){
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
foreach(const QModelIndex &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();
@@ -429,15 +407,19 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint&){
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionSet_upload_limit);
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionForce_recheck);
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionOpen_destination_folder);
myFinishedListMenu.addAction(actionTorrent_Properties);
if(BTSession->isQueueingEnabled()) {
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionIncreasePriority);
myFinishedListMenu.addAction(actionDecreasePriority);
}
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionBuy_it);
// Call menu
myFinishedListMenu.exec(QCursor::pos());
// XXX: why mapToGlobal() is not enough?
myFinishedListMenu.exec(mapToGlobal(pos)+QPoint(10,58));
}
@@ -449,8 +431,13 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint&){
void FinishedTorrents::displayFinishedHoSMenu(const QPoint& pos){
QMenu hideshowColumn(this);
hideshowColumn.setTitle(tr("Hide or Show Column"));
int lastCol = F_RATIO;
for(int i=0; i<=lastCol; i++) {
int lastCol;
if(BTSession->isQueueingEnabled()) {
lastCol = F_PRIORITY;
} else {
lastCol = F_RATIO;
}
for(int i=0; i<=F_RATIO; i++) {
hideshowColumn.addAction(getActionHoSCol(i));
}
// Call menu
@@ -472,12 +459,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
@@ -500,22 +487,18 @@ 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() {
hideOrShowColumn(F_RATIO);
}
void FinishedTorrents::hideOrShowColumnPriority() {
hideOrShowColumn(F_PRIORITY);
}
// load the previous settings, and hide the columns
bool FinishedTorrents::loadHiddenColumns() {
bool loaded = false;
@@ -535,9 +518,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;
@@ -571,18 +554,15 @@ 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;
break;
case F_PRIORITY :
return actionHOSColPriority;
break;
default :
return NULL;
}
@@ -593,42 +573,19 @@ QAction* FinishedTorrents::getActionHoSCol(int index) {
* Sorting functions
*/
void FinishedTorrents::toggleFinishedListSortOrder(int index) {
Qt::SortOrder sortOrder = Qt::AscendingOrder;
void FinishedTorrents::sortFinishedList(int index){
static Qt::SortOrder sortOrder = Qt::AscendingOrder;
if(finishedList->header()->sortIndicatorSection() == index){
sortOrder = (Qt::SortOrder)!(bool)finishedList->header()->sortIndicatorOrder();
if(sortOrder == Qt::AscendingOrder){
sortOrder = Qt::DescendingOrder;
}else{
sortOrder = Qt::AscendingOrder;
}
}
switch(index) {
finishedList->header()->setSortIndicator(index, sortOrder);
switch(index){
case F_SIZE:
case F_UPSPEED:
case F_RATIO:
case F_UPLOAD:
sortFinishedListFloat(index, sortOrder);
break;
default:
sortFinishedListString(index, sortOrder);
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString sortOrderLetter;
if(sortOrder == Qt::AscendingOrder)
sortOrderLetter = QString::fromUtf8("a");
else
sortOrderLetter = QString::fromUtf8("d");
settings.setValue(QString::fromUtf8("FinishedListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
void FinishedTorrents::sortFinishedList(int index, Qt::SortOrder sortOrder){
if(index == -1) {
index = finishedList->header()->sortIndicatorSection();
sortOrder = finishedList->header()->sortIndicatorOrder();
} else {
finishedList->header()->setSortIndicator(index, sortOrder);
}
switch(index) {
case F_SIZE:
case F_UPSPEED:
case F_UPLOAD:
case F_RATIO:
sortFinishedListFloat(index, sortOrder);
break;
default:

View File

@@ -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
*/
@@ -69,30 +60,29 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
void displayFinishedHoSMenu(const QPoint&);
void setRowColor(int row, QString color);
void saveColWidthFinishedList() const;
void toggleFinishedListSortOrder(int index);
void sortFinishedList(int index=-1, Qt::SortOrder sortOrder=Qt::AscendingOrder);
void sortFinishedList(int index);
void sortFinishedListFloat(int index, Qt::SortOrder sortOrder);
void sortFinishedListString(int index, Qt::SortOrder sortOrder);
void updateFileSize(QString hash);
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
void on_actionSet_upload_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
void hideOrShowColumnName();
void hideOrShowColumnSize();
void hideOrShowColumnUpSpeed();
void hideOrShowColumnSwarm();
void hideOrShowColumnPeers();
void hideOrShowColumnUpload();
void hideOrShowColumnLeechers();
void hideOrShowColumnRatio();
void forceRecheck();
void hideOrShowColumnPriority();
public slots:
void addTorrent(QString hash);
void updateTorrent(QTorrentHandle h);
void updateFinishedList();
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void propertiesSelection();
void deleteTorrent(QString hash);
void showPropertiesFromHash(QString hash);
void loadLastSortedColumn();
void hidePriorityColumn(bool hide);
signals:
void torrentMovedFromFinishedList(QString);

File diff suppressed because it is too large Load Diff

View File

@@ -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,7 +24,7 @@
#include <QProcess>
#include <QSystemTrayIcon>
#include <QPointer>
#include "ui_MainWindow.h"
#include "qtorrenthandle.h"
@@ -70,13 +61,12 @@ class GUI : public QMainWindow, private Ui::MainWindow{
// Bittorrent
bittorrent *BTSession;
QTimer *checkConnect;
QTimer *scrapeTimer;
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
// GUI related
QTabWidget *tabs;
QPointer<options_imp> options;
options_imp *options;
QSystemTrayIcon *myTrayIcon;
QPointer<QTimer> systrayCreator;
QTimer *systrayCreator;
QMenu *myTrayIconMenu;
DownloadingTorrents *downloadingTorrentTab;
FinishedTorrents *finishedTorrentTab;
@@ -107,7 +97,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
// RSS
RSSImp *rssWidget;
// Web UI
QPointer<HttpServer> httpServer;
HttpServer *httpServer;
// Misc
#ifdef QT_4_4
QLocalServer *localServer;
@@ -126,7 +116,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void on_actionCreate_torrent_triggered();
void on_actionWebsite_triggered() const;
void on_actionBugReport_triggered() const;
void on_actionShow_console_triggered();
void readParamsOnSocket();
void acceptConnection();
void togglePausedState(QString hash);
@@ -138,9 +127,11 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void readSettings();
void on_actionExit_triggered();
void createTrayIcon();
void updateUnfinishedTorrentNumberCalc();
void updateFinishedTorrentNumberCalc();
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();
// Keyboard shortcuts
@@ -166,22 +157,21 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void processParams(const QStringList& params);
void addTorrent(QString path);
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
void processScannedFiles(const QStringList& params);
void processDownloadedFiles(QString path, QString url);
void downloadFromURLList(const QStringList& urls);
void deleteTorrent(QString hash);
void deleteRatioTorrent(QString fileName);
void finishedTorrent(QTorrentHandle& h) const;
void addedTorrent(QTorrentHandle& h) const;
void checkedTorrent(QTorrentHandle& h) const;
void pausedTorrent(QTorrentHandle& h) const;
void resumedTorrent(QTorrentHandle& h) const;
void updateLists(bool force=false);
void torrentChecked(QString hash) const;
void updateLists();
bool initWebUi(QString username, QString password, int port);
void pauseTorrent(QString hash);
void on_actionIncreasePriority_triggered();
void on_actionDecreasePriority_triggered();
void scrapeTrackers();
// Options slots
void on_actionOptions_triggered();
void OptionsSaved(bool deleteOptions);
void OptionsSaved(QString info, bool deleteOptions);
// HTTP slots
void on_actionDownload_from_URL_triggered();
@@ -195,7 +185,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
protected:
void closeEvent(QCloseEvent *);
void showEvent(QShowEvent *);
bool event(QEvent * event);
void displayRSSTab(bool enable);

BIN
src/Icons/bt_settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/button_cancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/button_ok.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/configure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/connection.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

BIN
src/Icons/description.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

BIN
src/Icons/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 575 B

View File

Before

Width:  |  Height:  |  Size: 750 B

After

Width:  |  Height:  |  Size: 750 B

View File

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 704 B

BIN
src/Icons/filter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

View File

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 449 B

BIN
src/Icons/gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/Icons/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/Icons/log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/Icons/newmsg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/password.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
src/Icons/proxy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,6 +1,6 @@
[Desktop Entry]
Categories=Qt;Network;P2P
Comment=V1.4.1
Comment=V1.2.0
Exec=qbittorrent %f
GenericName=Bittorrent client
GenericName[bg]=Торент клиент

View File

Before

Width:  |  Height:  |  Size: 965 B

After

Width:  |  Height:  |  Size: 965 B

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 76 KiB

BIN
src/Icons/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/Icons/style.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 739 B

BIN
src/Icons/systemtray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 856 B

After

Width:  |  Height:  |  Size: 856 B

BIN
src/Icons/unavailable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 765 B

After

Width:  |  Height:  |  Size: 765 B

BIN
src/Icons/wizard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<ui version="4.0" >
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
@@ -10,266 +9,255 @@
<height>563</height>
</rect>
</property>
<property name="contextMenuPolicy">
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="windowTitle">
<property name="windowTitle" >
<string/>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout"/>
<widget class="QWidget" name="centralwidget" >
<layout class="QVBoxLayout" />
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<widget class="QMenuBar" name="menubar" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>914</width>
<height>23</height>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menu_Edit">
<property name="title">
<widget class="QMenu" name="menu_Edit" >
<property name="title" >
<string>&amp;Edit</string>
</property>
<addaction name="actionStart_All"/>
<addaction name="actionPause_All"/>
<addaction name="separator"/>
<addaction name="actionStart"/>
<addaction name="actionPause"/>
<addaction name="separator"/>
<addaction name="actionTorrent_Properties"/>
<addaction name="separator"/>
<addaction name="actionDelete"/>
<addaction name="actionDelete_Permanently"/>
<addaction name="actionDecreasePriority"/>
<addaction name="actionIncreasePriority"/>
<addaction name="actionStart_All" />
<addaction name="actionPause_All" />
<addaction name="separator" />
<addaction name="actionStart" />
<addaction name="actionPause" />
<addaction name="separator" />
<addaction name="actionTorrent_Properties" />
<addaction name="separator" />
<addaction name="actionDelete" />
<addaction name="actionDelete_Permanently" />
<addaction name="actionDecreasePriority" />
<addaction name="actionIncreasePriority" />
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
<widget class="QMenu" name="menu_Help" >
<property name="title" >
<string>&amp;Help</string>
</property>
<addaction name="actionBugReport"/>
<addaction name="actionWebsite"/>
<addaction name="actionDocumentation"/>
<addaction name="actionAbout"/>
<addaction name="actionBugReport" />
<addaction name="actionWebsite" />
<addaction name="actionDocumentation" />
<addaction name="actionAbout" />
</widget>
<widget class="QMenu" name="menu_Options">
<property name="title">
<widget class="QMenu" name="menu_Options" >
<property name="title" >
<string>Options</string>
</property>
<addaction name="actionOptions"/>
<addaction name="actionShow_console"/>
<addaction name="actionOptions" />
</widget>
<widget class="QMenu" name="menu_File">
<property name="title">
<widget class="QMenu" name="menu_File" >
<property name="title" >
<string>&amp;File</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionDownload_from_URL"/>
<addaction name="actionCreate_torrent"/>
<addaction name="actionExit"/>
<addaction name="actionOpen" />
<addaction name="actionDownload_from_URL" />
<addaction name="actionCreate_torrent" />
<addaction name="actionExit" />
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Edit"/>
<addaction name="menu_Options"/>
<addaction name="menu_Help"/>
<addaction name="menu_File" />
<addaction name="menu_Edit" />
<addaction name="menu_Options" />
<addaction name="menu_Help" />
</widget>
<widget class="QToolBar" name="toolBar">
<property name="enabled">
<widget class="QToolBar" name="toolBar" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="contextMenuPolicy">
<property name="contextMenuPolicy" >
<enum>Qt::NoContextMenu</enum>
</property>
<property name="movable">
<property name="movable" >
<bool>false</bool>
</property>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="iconSize">
<property name="iconSize" >
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="floatable">
<property name="floatable" >
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<attribute name="toolBarArea" >
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<attribute name="toolBarBreak" >
<bool>false</bool>
</attribute>
<addaction name="actionOpen"/>
<addaction name="actionDownload_from_URL"/>
<addaction name="separator"/>
<addaction name="actionDelete"/>
<addaction name="actionDelete_Permanently"/>
<addaction name="separator"/>
<addaction name="actionTorrent_Properties"/>
<addaction name="separator"/>
<addaction name="actionStart"/>
<addaction name="actionPause"/>
<addaction name="separator"/>
<addaction name="actionStart_All"/>
<addaction name="actionPause_All"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
<addaction name="actionDecreasePriority"/>
<addaction name="actionIncreasePriority"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
<addaction name="actionOpen" />
<addaction name="actionDownload_from_URL" />
<addaction name="separator" />
<addaction name="actionDelete" />
<addaction name="actionDelete_Permanently" />
<addaction name="separator" />
<addaction name="actionTorrent_Properties" />
<addaction name="separator" />
<addaction name="actionStart" />
<addaction name="actionPause" />
<addaction name="separator" />
<addaction name="actionStart_All" />
<addaction name="actionPause_All" />
<addaction name="separator" />
<addaction name="actionOptions" />
<addaction name="actionDecreasePriority" />
<addaction name="actionIncreasePriority" />
<addaction name="separator" />
<addaction name="actionExit" />
<addaction name="separator" />
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionOpen">
<property name="text">
<widget class="QStatusBar" name="statusBar" />
<action name="actionOpen" >
<property name="text" >
<string>Open</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<action name="actionExit" >
<property name="text" >
<string>Exit</string>
</property>
</action>
<action name="actionOptions">
<property name="text">
<action name="actionOptions" >
<property name="text" >
<string>Preferences</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<action name="actionAbout" >
<property name="text" >
<string>About</string>
</property>
</action>
<action name="actionStart">
<property name="text">
<action name="actionStart" >
<property name="text" >
<string>Start</string>
</property>
</action>
<action name="actionPause">
<property name="text">
<action name="actionPause" >
<property name="text" >
<string>Pause</string>
</property>
</action>
<action name="actionDelete">
<property name="text">
<action name="actionDelete" >
<property name="text" >
<string>Delete</string>
</property>
</action>
<action name="actionPause_All">
<property name="text">
<action name="actionPause_All" >
<property name="text" >
<string>Pause All</string>
</property>
</action>
<action name="actionStart_All">
<property name="text">
<action name="actionStart_All" >
<property name="text" >
<string>Start All</string>
</property>
</action>
<action name="actionWebsite">
<property name="text">
<action name="actionWebsite" >
<property name="text" >
<string>Visit website</string>
</property>
</action>
<action name="actionDelete_Permanently">
<property name="text">
<action name="actionDelete_Permanently" >
<property name="text" >
<string>Delete Permanently</string>
</property>
</action>
<action name="actionTorrent_Properties">
<property name="text">
<action name="actionTorrent_Properties" >
<property name="text" >
<string>Torrent Properties</string>
</property>
</action>
<action name="actionDownload_from_URL">
<property name="text">
<action name="actionDownload_from_URL" >
<property name="text" >
<string>Download from URL</string>
</property>
</action>
<action name="actionCreate_torrent">
<property name="text">
<action name="actionCreate_torrent" >
<property name="text" >
<string>Create torrent</string>
</property>
</action>
<action name="actionPreview_file">
<property name="text">
<action name="actionPreview_file" >
<property name="text" >
<string>Preview file</string>
</property>
</action>
<action name="actionClearLog">
<property name="text">
<action name="actionClearLog" >
<property name="text" >
<string>Clear log</string>
</property>
</action>
<action name="actionBugReport">
<property name="text">
<action name="actionBugReport" >
<property name="text" >
<string>Report a bug</string>
</property>
</action>
<action name="actionSet_upload_limit">
<property name="text">
<action name="actionSet_upload_limit" >
<property name="text" >
<string>Set upload limit</string>
</property>
</action>
<action name="actionSet_download_limit">
<property name="text">
<action name="actionSet_download_limit" >
<property name="text" >
<string>Set download limit</string>
</property>
</action>
<action name="actionDocumentation">
<property name="text">
<action name="actionDocumentation" >
<property name="text" >
<string>Documentation</string>
</property>
</action>
<action name="actionSet_global_download_limit">
<property name="text">
<action name="actionSet_global_download_limit" >
<property name="text" >
<string>Set global download limit</string>
</property>
</action>
<action name="actionSet_global_upload_limit">
<property name="text">
<action name="actionSet_global_upload_limit" >
<property name="text" >
<string>Set global upload limit</string>
</property>
</action>
<action name="actionDecreasePriority">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/skin/decrease.png</normaloff>:/Icons/skin/decrease.png</iconset>
<action name="actionDecreasePriority" >
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/decrease.png</iconset>
</property>
<property name="text">
<property name="text" >
<string>Decrease priority</string>
</property>
<property name="visible">
<property name="visible" >
<bool>false</bool>
</property>
</action>
<action name="actionIncreasePriority">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/skin/increase.png</normaloff>:/Icons/skin/increase.png</iconset>
<action name="actionIncreasePriority" >
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/increase.png</iconset>
</property>
<property name="text">
<property name="text" >
<string>Increase priority</string>
</property>
<property name="visible">
<property name="visible" >
<bool>false</bool>
</property>
</action>
<action name="actionShow_console">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/log.png</normaloff>:/Icons/oxygen/log.png</iconset>
</property>
<property name="text">
<string>Console</string>
</property>
</action>
</widget>
<resources>
<include location="icons.qrc"/>
<include location="icons.qrc" />
</resources>
<connections/>
</ui>

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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
*/

View File

@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<ui version="4.0" >
<author>Christophe Dumez</author>
<class>AboutDlg</class>
<widget class="QDialog" name="AboutDlg">
<property name="geometry">
<widget class="QDialog" name="AboutDlg" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
@@ -11,65 +10,65 @@
<height>320</height>
</rect>
</property>
<property name="minimumSize">
<property name="minimumSize" >
<size>
<width>504</width>
<height>320</height>
</size>
</property>
<property name="maximumSize">
<property name="maximumSize" >
<size>
<width>504</width>
<height>320</height>
</size>
</property>
<property name="windowTitle">
<property name="windowTitle" >
<string>About qBittorrent</string>
</property>
<layout class="QVBoxLayout">
<layout class="QVBoxLayout" >
<item>
<layout class="QHBoxLayout">
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="logo">
<property name="minimumSize">
<widget class="QLabel" name="logo" >
<property name="minimumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<property name="maximumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lb_name">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<widget class="QLabel" name="lb_name" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;h3&gt;&lt;b&gt;qBittorrent&lt;/b&gt;&lt;/h3&gt;</string>
<property name="text" >
<string>&lt;h3>&lt;b>qBittorrent&lt;/b>&lt;/h3></string>
</property>
<property name="textFormat">
<property name="textFormat" >
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -80,90 +79,79 @@
</layout>
</item>
<item>
<widget class="QTabWidget" name="tw_tabs">
<property name="currentIndex">
<widget class="QTabWidget" name="tw_tabs" >
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="tab2">
<attribute name="title">
<widget class="QWidget" name="tab2" >
<attribute name="title" >
<string>About</string>
</attribute>
<widget class="QLabel" name="mascot_lbl">
<property name="geometry">
<widget class="QLabel" name="mascot_lbl" >
<property name="geometry" >
<rect>
<x>380</x>
<y>70</y>
<y>50</y>
<width>94</width>
<height>162</height>
</rect>
</property>
<property name="text">
<property name="text" >
<string/>
</property>
</widget>
<widget class="QLabel" name="lb_about">
<property name="geometry">
<widget class="QLabel" name="lb_about" >
<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">
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A Bittorrent client programmed in C++, based on Qt4 toolkit &lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;and libtorrent-rasterbar. &lt;br /&gt;&lt;br /&gt;Copyright ©2006-2009 Christophe Dumez&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Home Page:&lt;/span&gt; &lt;a href=&quot;http://www.qbittorrent.org&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;http://www.qbittorrent.org&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<property name="text" >
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.&lt;br>
&lt;br>
Copyright © 2006 by Christophe Dumez&lt;br>
&lt;br> &lt;u>Home Page:&lt;/u> &lt;i>http://www.qbittorrent.org&lt;/i>&lt;br></string>
</property>
<property name="textFormat">
<property name="textFormat" >
<enum>Qt::RichText</enum>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<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">
<attribute name="title">
<widget class="QWidget" name="tab3" >
<attribute name="title" >
<string>Author</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QFrame" name="te_authors">
<layout class="QHBoxLayout">
<property name="spacing">
<widget class="QFrame" name="te_authors" >
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<property name="sizeType" >
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
@@ -172,13 +160,13 @@ p, li { white-space: pre-wrap; }
</spacer>
</item>
<item>
<layout class="QVBoxLayout">
<property name="spacing">
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<widget class="QLabel" name="label_3" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
@@ -189,14 +177,14 @@ p, li { white-space: pre-wrap; }
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<property name="text" >
<string>Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<widget class="QLabel" name="label_4" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
@@ -207,14 +195,14 @@ p, li { white-space: pre-wrap; }
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<property name="text" >
<string>Country:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_birthday">
<property name="font">
<widget class="QLabel" name="lbl_birthday" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
@@ -225,14 +213,14 @@ p, li { white-space: pre-wrap; }
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<property name="text" >
<string>Birthday:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_occupation">
<property name="font">
<widget class="QLabel" name="lbl_occupation" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
@@ -243,14 +231,14 @@ p, li { white-space: pre-wrap; }
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<property name="text" >
<string>Occupation:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="font">
<widget class="QLabel" name="label_5" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
@@ -261,14 +249,14 @@ p, li { white-space: pre-wrap; }
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<property name="text" >
<string>E-mail:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="font">
<widget class="QLabel" name="label_8" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
@@ -279,7 +267,7 @@ p, li { white-space: pre-wrap; }
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<property name="text" >
<string>Home page:</string>
</property>
</widget>
@@ -288,13 +276,13 @@ p, li { white-space: pre-wrap; }
</item>
<item>
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<property name="sizeType" >
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
@@ -303,48 +291,48 @@ p, li { white-space: pre-wrap; }
</spacer>
</item>
<item>
<layout class="QVBoxLayout">
<property name="spacing">
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Christophe Dumez</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<widget class="QLabel" name="label_7" >
<property name="text" >
<string>France</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<widget class="QLabel" name="label_11" >
<property name="text" >
<string>03/05/1985</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<widget class="QLabel" name="label_10" >
<property name="text" >
<string>Student in computer science</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<widget class="QLabel" name="label_6" >
<property name="text" >
<string>chris@qbittorrent.org</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<widget class="QLabel" name="label_9" >
<property name="text" >
<string>http://www.dchris.eu</string>
</property>
</widget>
@@ -353,10 +341,10 @@ p, li { white-space: pre-wrap; }
</item>
<item>
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -369,46 +357,46 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
<widget class="QWidget" name="tab4">
<attribute name="title">
<widget class="QWidget" name="tab4" >
<attribute name="title" >
<string>Thanks to</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QTextBrowser" name="te_thanks"/>
<widget class="QTextBrowser" name="te_thanks" />
</item>
</layout>
</widget>
<widget class="QWidget" name="tab5">
<attribute name="title">
<widget class="QWidget" name="tab5" >
<attribute name="title" >
<string>Translation</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QTextBrowser" name="te_translation">
<property name="lineWrapMode">
<widget class="QTextBrowser" name="te_translation" >
<property name="lineWrapMode" >
<enum>QTextEdit::NoWrap</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab1">
<attribute name="title">
<widget class="QWidget" name="tab1" >
<attribute name="title" >
<string>License</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QTextBrowser" name="te_license"/>
<widget class="QTextBrowser" name="te_license" />
</item>
</layout>
</widget>
@@ -416,7 +404,7 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<layoutdefault spacing="6" margin="11" />
<resources/>
<connections/>
</ui>

View File

@@ -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
@@ -66,11 +57,9 @@ class about : public QDialog, private Ui::AboutDlg{
- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
- <u>Catalan:</u> Gekko Dam Beer (gekko04@users.sourceforge.net)<br>\
- <u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)<br>\
- <u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)<br>\
- <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>\
@@ -85,25 +74,13 @@ class about : public QDialog, private Ui::AboutDlg{
- <u>Slovak:</u> helix84<br>\
- <u>Spanish:</u> Vicente Raul Plata Fonseca (silverxnt@users.sourceforge.net) and Gabriel de Oliveira (deadloop@hotmail.com)<br>\
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
- <u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)<br>\
- <u>Turkish:</u> Erdem Bingöl (erdem84@gmail.com)<br>\
- <u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net)<br><br>"));
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
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>\

View File

@@ -13,6 +13,21 @@
<string>Torrent addition dialog</string>
</property>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<widget class="QLabel" name="fileNameLbl" >
<property name="text" >
@@ -95,50 +110,6 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="collapseAllButton" >
<property name="text" >
<string>Collapse all</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="expandAllButton" >
<property name="text" >
<string>Expand all</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkIncrementalDL" >
<property name="text" >

View File

@@ -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
*/

View File

@@ -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 @@ class torrent_file {
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 @@ class torrent_file {
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 @@ class torrent_file {
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 @@ class torrent_file {
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 @@ class torrent_file {
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 @@ class torrent_file {
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;
}
@@ -179,27 +172,27 @@ class arborescence {
torrent_file *root;
public:
arborescence(boost::intrusive_ptr<torrent_info> t) {
torrent_info::file_iterator fi = t->begin_files();
if(t->num_files() > 1) {
root = new torrent_file(0, misc::toQString(t->name()), true);
arborescence(torrent_info t) {
torrent_info::file_iterator fi = t.begin_files();
if(t.num_files() > 1) {
root = new torrent_file(0, misc::toQString(t.name()), true);
} else {
// XXX: Will crash if there is no file in torrent
root = new torrent_file(0, misc::toQString(t->name()), false, fi->size, 0);
root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0);
return;
}
int i = 0;
while(fi != t->end_files()) {
while(fi != t.end_files()) {
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
addFile(path, fi->size, i);
fi++;
++i;
}
qDebug("real size: %ld, tree size: %ld", (long)t->total_size(), (long)root->getSize());
Q_ASSERT(root->getSize() == t->total_size());
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
Q_ASSERT(root->getSize() == t.total_size());
}
arborescence(torrent_info const& t, std::vector<size_type> fp, int *prioritiesTab) {
arborescence(torrent_info t, std::vector<float> 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 @@ class arborescence {
} 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, prioritiesTab[0]);
root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0], 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, prioritiesTab[i]);
addFile(path, fi->size, i, fp[i], prioritiesTab[i]);
fi++;
++i;
}
@@ -246,13 +239,14 @@ class arborescence {
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 @@ class arborescence {
child = dad->addChild(fileName, false, file_size, index, progress, priority);
}
}
dad = (torrent_file*)child;
dad = child;
}
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -16,25 +16,16 @@
* 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__
#define __BITTORRENT_H__
#include <QHash>
#include <QList>
#include <QPair>
#include <QStringList>
#include <QApplication>
#include <QPalette>
#include <QPointer>
#include <QDateTime>
#include <libtorrent/session.hpp>
#include <libtorrent/ip_filter.hpp>
@@ -43,55 +34,75 @@
using namespace libtorrent;
class downloadThread;
class deleteThread;
class QTimer;
class QFileSystemWatcher;
class QMutex;
class FilterParserThread;
class bittorrent : public QObject {
class bittorrent : public QObject{
Q_OBJECT
private:
session *s;
QPointer<QFileSystemWatcher> FSWatcher;
QMutex* FSMutex;
QPointer<QTimer> timerAlerts;
QPointer<QTimer> BigRatioTimer;
QString scan_dir;
QTimer *timerScan;
QTimer *timerAlerts;
QTimer *fastResumeSaver;
QTimer *BigRatioTimer;
bool DHTEnabled;
QPointer<downloadThread> downloader;
downloadThread *downloader;
QString defaultSavePath;
QString defaultTempPath;
QStringList torrentsToPauseAfterChecking;
QHash<QString, QDateTime> TorrentsStartTime;
QHash<QString, size_type> TorrentsStartData;
QHash<QString, QPair<size_type,size_type> > ratioData;
QHash<QString, QHash<QString, QString> > trackersErrors;
QStringList consoleMessages;
QStringList peerBanMessages;
deleteThread *deleter;
QStringList finishedTorrents;
QStringList unfinishedTorrents;
bool preAllocateAll;
bool addInPause;
int maxConnecsPerTorrent;
int maxUploadsPerTorrent;
float ratio_limit;
float max_ratio;
bool UPnPEnabled;
bool NATPMPEnabled;
bool LSDEnabled;
QPointer<FilterParserThread> filterParser;
FilterParserThread *filterParser;
QString filterPath;
int folderScanInterval; // in seconds
bool queueingEnabled;
QStringList url_skippingDlg;
int maxActiveDownloads;
int maxActiveTorrents;
int currentActiveDownloads;
QStringList *downloadQueue;
QStringList *queuedDownloads;
QStringList *uploadQueue;
QStringList *queuedUploads;
bool calculateETA;
protected:
QString getSavePath(QString hash);
public:
// Constructor / Destructor
bittorrent();
~bittorrent();
QTorrentHandle getTorrentHandle(QString hash) const;
std::vector<torrent_handle> getTorrents() const;
bool isPaused(QString hash) const;
bool isFilePreviewPossible(QString fileHash) const;
bool isDHTEnabled() const;
float getPayloadDownloadRate() const;
float getPayloadUploadRate() const;
session_status getSessionStatus() const;
int getListenPort() const;
QStringList getTorrentsToPauseAfterChecking() const;
qlonglong getETA(QString hash) const;
float getRealRatio(QString hash) const;
session* getSession() const;
QHash<QString, QString> getTrackersErrors(QString hash) const;
QStringList getFinishedTorrents() const;
QStringList getUnfinishedTorrents() const;
bool isFinished(QString hash) const;
bool has_filtered_files(QString hash) const;
unsigned int getFinishedPausedTorrentsNb() const;
unsigned int getUnfinishedPausedTorrentsNb() const;
@@ -100,43 +111,43 @@ class bittorrent : public QObject {
int getUpTorrentPriority(QString hash) const;
int getMaximumActiveDownloads() const;
int getMaximumActiveTorrents() const;
bool isDownloadQueued(QString hash) const;
bool isUploadQueued(QString hash) const;
int loadTorrentPriority(QString hash);
QStringList getConsoleMessages() const;
QStringList getPeerBanMessages() const;
qlonglong getETA(QString hash) const;
bool useTemporaryFolder() const;
QString getSavePath(QString hash);
public slots:
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
void loadSessionState();
void saveSessionState();
void addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
void downloadFromUrl(QString url);
void downloadFromURLList(const QStringList& url_list);
void deleteTorrent(QString hash, bool permanent = false);
/* Needed by Web UI */
bool pauseTorrent(QString hash);
bool resumeTorrent(QString hash);
void pauseAllTorrents();
void resumeAllTorrents();
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
/* End Web UI */
void saveDHTEntry();
void preAllocateAllFiles(bool b);
void saveFastResumeData();
void saveFastResumeAndRatioData();
void saveFastResumeAndRatioData(QString hash);
void enableDirectoryScanning(QString scan_dir);
void disableDirectoryScanning();
void enablePeerExchange();
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 saveDownloadUploadForTorrent(QString hash);
void loadDownloadUploadForTorrent(QString hash);
void handleDownloadFailure(QString url, QString reason);
void loadWebSeeds(QString fileHash);
void updateDownloadQueue();
void updateUploadQueue();
void increaseDlTorrentPriority(QString hash);
void decreaseDlTorrentPriority(QString hash);
void downloadUrlAndSkipDialog(QString);
void increaseUpTorrentPriority(QString hash);
void decreaseUpTorrentPriority(QString hash);
void saveTorrentPriority(QString hash, int prio);
// Session configuration - Setters
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);
void setMaxConnections(int maxConnec);
@@ -151,39 +162,58 @@ 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);
void setUploadLimit(QString hash, long val);
void setUnfinishedTorrent(QString hash);
void setFinishedTorrent(QString hash);
void enableUPnP(bool b);
void enableNATPMP(bool b);
void enableLSD(bool b);
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 reloadTorrent(const QTorrentHandle &h, bool full_alloc);
void setTimerScanInterval(int secs);
void setMaxActiveDownloads(int val);
void setMaxActiveTorrents(int val);
void setETACalculation(bool enable);
protected slots:
void scanDirectory(QString);
void scanDirectory();
void readAlerts();
void processDownloadedFile(QString, QString);
bool loadTrackerFile(QString hash);
void saveTrackerFile(QString hash);
void deleteBigRatios();
signals:
void addedTorrent(QTorrentHandle& h);
void invalidTorrent(QString path);
void duplicateTorrent(QString path);
void addedTorrent(QString path, QTorrentHandle& h, bool fastResume);
void deletedTorrent(QString hash);
void pausedTorrent(QTorrentHandle& h);
void resumedTorrent(QTorrentHandle& h);
void pausedTorrent(QString hash);
void resumedTorrent(QString hash);
void finishedTorrent(QTorrentHandle& h);
void fullDiskError(QTorrentHandle& h, QString msg);
void fullDiskError(QTorrentHandle& h);
void trackerError(QString hash, QString time, QString msg);
void portListeningFailure();
void trackerAuthenticationRequired(QTorrentHandle& h);
void scanDirFoundTorrents(const QStringList& pathList);
void newDownloadedTorrent(QString path, QString url);
void aboutToDownloadFromUrl(QString url);
void updateFileSize(QString hash);
void peerBlocked(QString);
void downloadFromUrlFailure(QString url, QString reason);
void torrentFinishedChecking(QTorrentHandle& h);
void fastResumeDataRejected(QString name);
void urlSeedProblem(QString url, QString msg);
void torrentFinishedChecking(QString hash);
void torrent_ratio_deleted(QString fileName);
void UPnPError(QString msg);
void UPnPSuccess(QString msg);
void updateFinishedTorrentNumber();
void updateUnfinishedTorrentNumber();
void forceUnfinishedListUpdate();
void forceFinishedListUpdate();
};
#endif

View File

@@ -1,58 +0,0 @@
<ui version="4.0" >
<class>ConsoleDlg</class>
<widget class="QDialog" name="ConsoleDlg" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>512</width>
<height>497</height>
</rect>
</property>
<property name="windowTitle" >
<string>qBittorrent console</string>
</property>
<property name="windowIcon" >
<iconset resource="icons.qrc" >:/Icons/oxygen/log.png</iconset>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QTabWidget" name="tabConsole" >
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
<string>General</string>
</attribute>
<attribute name="icon" >
<iconset resource="icons.qrc" >:/Icons/oxygen/log.png</iconset>
</attribute>
<layout class="QVBoxLayout" >
<item>
<widget class="QTextBrowser" name="textConsole" />
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2" >
<attribute name="title" >
<string>Blocked IPs</string>
</attribute>
<attribute name="icon" >
<iconset resource="icons.qrc" >:/Icons/filter.png</iconset>
</attribute>
<layout class="QVBoxLayout" >
<item>
<widget class="QTextBrowser" name="textBannedPeers" />
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="icons.qrc" />
</resources>
<connections/>
</ui>

View File

@@ -1,59 +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 CONSOLE_H
#define CONSOLE_H
#include "bittorrent.h"
#include "ui_console.h"
using namespace libtorrent;
class consoleDlg : public QDialog, private Ui_ConsoleDlg{
Q_OBJECT
private:
bittorrent *BTSession;
public:
consoleDlg(QWidget *parent, bittorrent* _BTSession) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
BTSession = _BTSession;
textConsole->setHtml(BTSession->getConsoleMessages().join("<br>"));
textBannedPeers->setHtml(BTSession->getPeerBanMessages().join("<br>"));
show();
}
~consoleDlg() {}
};
#endif

View File

@@ -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
*/
@@ -35,7 +26,6 @@
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/bind.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/bencode.hpp>
@@ -44,7 +34,6 @@
#include <libtorrent/storage.hpp>
#include <libtorrent/hasher.hpp>
#include <libtorrent/file_pool.hpp>
#include <libtorrent/create_torrent.hpp>
#include "createtorrent_imp.h"
#include "misc.h"
@@ -52,23 +41,13 @@
using namespace libtorrent;
using namespace boost::filesystem;
// do not include files and folders whose
// name starts with a .
bool file_filter(boost::filesystem::path const& filename)
{
if (filename.leaf()[0] == '.') return false;
std::cerr << filename << std::endl;
return true;
}
createtorrent::createtorrent(QWidget *parent): QDialog(parent){
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
creatorThread = new torrentCreatorThread(this);
connect(creatorThread, SIGNAL(creationSuccess(QString, const char*)), this, SLOT(handleCreationSuccess(QString, const char*)));
creatorThread = new torrentCreatorThread();
connect(creatorThread, SIGNAL(creationSuccess(QString)), this, SLOT(handleCreationSucess(QString)));
connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
connect(creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
path::default_name_check(no_check);
show();
}
@@ -147,6 +126,20 @@ void createtorrent::on_addURLSeed_button_clicked(){
}
}
// Subfunction to add files to a torrent_info structure
// Written by Arvid Norberg (libtorrent Author)
void add_files(torrent_info& t, path const& p, path const& l){
qDebug("p: %s, l: %s, l.leaf(): %s", p.string().c_str(), l.string().c_str(), l.leaf().c_str());
path f(p / l);
if (is_directory(f)){
for (directory_iterator i(f), end; i != end; ++i)
add_files(t, p, l / i->leaf());
}else{
qDebug("Adding %s", l.string().c_str());
t.add_file(l, file_size(f));
}
}
QStringList createtorrent::allItems(QListWidget *list){
QStringList res;
unsigned int nbItems = list->count();
@@ -184,27 +177,20 @@ 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) {
if(checkStartSeeding->isChecked()) {
// Create save path file
boost::intrusive_ptr<torrent_info> t;
try {
t = new torrent_info(path.toLocal8Bit().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;
}
QString hash = misc::toQString(t->info_hash());
QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".savepath"));
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
savepath_file.write(branch_path);
savepath_file.close();
emit torrent_to_seed(path);
}
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+path);
close();
void createtorrent::handleCreationSuccess(QString path, const char* branch_path, QString hash) {
if(checkStartSeeding->isChecked()) {
// Create save path file
QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".savepath"));
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
savepath_file.write(branch_path);
savepath_file.close();
emit torrent_to_seed(path);
}
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+path);
hide();
}
void createtorrent::updateProgressBar(int progress) {
@@ -227,49 +213,54 @@ 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 torrentCreatorThread::run() {
emit updateProgress(0);
char const* creator_str = "qBittorrent "VERSION;
try {
file_storage fs;
file_pool fp;
path full_path = complete(path(input_path.toLocal8Bit().data()));
boost::intrusive_ptr<torrent_info> t(new torrent_info);
ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
// Adding files to the torrent
add_files(fs, full_path, file_filter);
path full_path = complete(path(input_path.toUtf8().data()));
add_files(*t, full_path.branch_path(), full_path.leaf());
if(abort) return;
create_torrent t(fs, piece_size);
// Set piece size
t->set_piece_size(piece_size);
// 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));
file_pool fp;
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
int num = t->num_pieces();
std::vector<char> buf(piece_size);
for (int i = 0; i < num; ++i) {
st->read(&buf[0], i, 0, t->piece_size(i));
hasher h(&buf[0], t->piece_size(i));
t->set_hash(i, h.final());
emit updateProgress((int)(i*100./(float)num));
if(abort) return;
}
// 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_creator(creator_str);
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);
bencode(std::ostream_iterator<char>(out), t.generate());
entry e = t->create_torrent();
libtorrent::bencode(std::ostream_iterator<char>(out), e);
out.flush();
emit updateProgress(100);
emit creationSuccess(save_path, full_path.branch_path().string().c_str());
emit creationSuccess(save_path, full_path.branch_path().string().c_str(), misc::toQString(t->info_hash()));
}
catch (std::exception& e){
emit creationFailure(QString::fromUtf8(e.what()));

View File

@@ -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,27 +37,21 @@ class torrentCreatorThread : public QThread {
bool is_private;
int piece_size;
bool abort;
QDialog *parent;
public:
torrentCreatorThread(QDialog *_parent) {
parent = _parent;
}
torrentCreatorThread() {}
~torrentCreatorThread() {
abort = true;
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();
signals:
void creationFailure(QString msg);
void creationSuccess(QString path, const char* branch_path);
signals:
void creationSuccess(QString path, const char* branch_path, QString hash);
void updateProgress(int progress);
};
@@ -85,9 +70,6 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
signals:
void torrent_to_seed(QString path);
public slots:
void updateProgressBar(int progress);
protected slots:
void on_createButton_clicked();
void on_addFile_button_clicked();
@@ -97,7 +79,8 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
void on_addURLSeed_button_clicked();
void on_removeURLSeed_button_clicked();
void handleCreationFailure(QString msg);
void handleCreationSuccess(QString path, const char* branch_path);
void handleCreationSuccess(QString path, const char* branch_path, QString hash);
void updateProgressBar(int progress);
};
#endif

125
src/deleteThread.h Normal file
View File

@@ -0,0 +1,125 @@
/*
* 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.
*
* Contact : chris@qbittorrent.org
*/
#ifndef DELETETHREAD_H
#define DELETETHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QMutexLocker>
#include <QPair>
#include "arborescence.h"
class subDeleteThread : public QThread {
Q_OBJECT
private:
QString save_path;
arborescence *arb;
bool abort;
public:
subDeleteThread(QObject *parent, QString saveDir, arborescence *arb) : QThread(parent), save_path(saveDir), arb(arb), abort(false){}
~subDeleteThread(){
abort = true;
wait();
}
signals:
// For subthreads
void deletionSuccessST(subDeleteThread* st);
void deletionFailureST(subDeleteThread* st);
protected:
void run(){
if(arb->removeFromFS(save_path))
emit deletionSuccessST(this);
else
emit deletionFailureST(this);
delete arb;
}
};
class deleteThread : public QThread {
Q_OBJECT
private:
QList<QPair<QString, arborescence*> > torrents_list;
QMutex mutex;
QWaitCondition condition;
bool abort;
QList<subDeleteThread*> subThreads;
public:
deleteThread(QObject* parent) : QThread(parent), abort(false){}
~deleteThread(){
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
qDeleteAll(subThreads);
wait();
}
void deleteTorrent(QString saveDir, arborescence *arb){
qDebug("deleteThread called");
QMutexLocker locker(&mutex);
torrents_list << QPair<QString, arborescence*>(saveDir, arb);
if(!isRunning()){
start();
}else{
condition.wakeOne();
}
}
protected:
void run(){
forever{
if(abort)
return;
mutex.lock();
if(torrents_list.size() != 0){
QPair<QString, arborescence *> torrent = torrents_list.takeFirst();
mutex.unlock();
subDeleteThread *st = new subDeleteThread(0, torrent.first, torrent.second);
subThreads << st;
connect(st, SIGNAL(deletionSuccessST(subDeleteThread*)), this, SLOT(deleteSubThread(subDeleteThread*)));
connect(st, SIGNAL(deletionFailureST(subDeleteThread*)), this, SLOT(deleteSubThread(subDeleteThread*)));
st->start();
}else{
condition.wait(&mutex);
mutex.unlock();
}
}
}
protected slots:
void deleteSubThread(subDeleteThread* st){
int index = subThreads.indexOf(st);
Q_ASSERT(index != -1);
subThreads.removeAt(index);
delete st;
}
};
#endif

View File

@@ -18,7 +18,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>
@@ -48,6 +57,95 @@
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabBottom" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>142</height>
</size>
</property>
<property name="tabPosition" >
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="log_tab" >
<attribute name="title" >
<string>Log</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<widget class="QTextBrowser" name="infoBar" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>120</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="filter_tab" >
<attribute name="title" >
<string>IP filter</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<widget class="QTextBrowser" name="textBlockedUsers" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>123</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
<action name="actionStart" >
<property name="text" >
@@ -64,6 +162,11 @@
<string>Delete</string>
</property>
</action>
<action name="actionClearLog" >
<property name="text" >
<string>Clear</string>
</property>
</action>
<action name="actionPreview_file" >
<property name="text" >
<string>Preview file</string>
@@ -91,8 +194,7 @@
</action>
<action name="actionOpen_destination_folder" >
<property name="icon" >
<iconset resource="icons.qrc" >
<normaloff>:/Icons/oxygen/folder.png</normaloff>:/Icons/oxygen/folder.png</iconset>
<iconset resource="icons.qrc" >:/Icons/folder.png</iconset>
</property>
<property name="text" >
<string>Open destination folder</string>
@@ -140,8 +242,7 @@
</action>
<action name="actionBuy_it" >
<property name="icon" >
<iconset resource="icons.qrc" >
<normaloff>:/Icons/money.png</normaloff>:/Icons/money.png</iconset>
<iconset resource="icons.qrc" >:/Icons/money.png</iconset>
</property>
<property name="text" >
<string>Buy it</string>
@@ -154,8 +255,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>
@@ -163,22 +263,12 @@
</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>
</property>
</action>
<action name="actionForce_recheck" >
<property name="icon" >
<iconset resource="icons.qrc" >
<normaloff>:/Icons/oxygen/gear.png</normaloff>:/Icons/oxygen/gear.png</iconset>
</property>
<property name="text" >
<string>Force recheck</string>
</property>
</action>
</widget>
<resources>
<include location="icons.qrc" />

View File

@@ -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
*/

View File

@@ -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,29 +75,29 @@ 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;
}
CURL *curl;
CURLcode res = (CURLcode)-1;
CURLcode res;
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);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
// PROXY SUPPORT
QSettings settings("qBittorrent", "qBittorrent");
int intValue = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxyType"), 0).toInt();
int intValue = settings.value(QString::fromUtf8("Preferences/Connection/ProxyType"), 0).toInt();
if(intValue > 0) {
// 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());
QString IP = settings.value(QString::fromUtf8("Preferences/Connection/Proxy/IP"), "0.0.0.0").toString();
QString port = settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Port"), 8080).toString();
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");
@@ -115,9 +106,9 @@ void subDownloadThread::run(){
// Authentication?
if(intValue > 2) {
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());
QString username = settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Username"), QString()).toString();
QString password = settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Password"), QString()).toString();
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, (username+QString(":")+password).toUtf8().data());
}
}
// We have to define CURLOPT_WRITEFUNCTION or it will crash on windows
@@ -131,14 +122,11 @@ 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());
if(!abort)
res = curl_easy_perform(curl);
qDebug("Downloading %s", url.toUtf8().data());
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
fclose(f);
if(abort)
return;
if(res) {
emit downloadFailureST(this, url, errorCodeToString(res));
} else {

View File

@@ -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
*/

View File

@@ -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"
@@ -42,19 +33,20 @@
#include <QTime>
#include <QMenu>
DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession) : parent(parent), BTSession(BTSession), nbTorrents(0) {
DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession) : parent(parent), BTSession(BTSession), delayedSorting(false), nbTorrents(0) {
setupUi(this);
// Setting icons
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")));
actionClearLog->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
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")));
// 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);
@@ -68,8 +60,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
@@ -78,7 +68,17 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
downloadList->hideColumn(HASH);
loadHiddenColumns();
connect(BTSession, SIGNAL(torrentFinishedChecking(QTorrentHandle&)), this, SLOT(sortProgressColumn(QTorrentHandle&)));
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
connect(BTSession, SIGNAL(duplicateTorrent(QString)), this, SLOT(torrentDuplicate(QString)));
connect(BTSession, SIGNAL(invalidTorrent(QString)), this, SLOT(torrentCorrupted(QString)));
connect(BTSession, SIGNAL(portListeningFailure()), this, SLOT(portListeningFailure()));
connect(BTSession, SIGNAL(peerBlocked(QString)), this, SLOT(addLogPeerBlocked(const QString)));
connect(BTSession, SIGNAL(fastResumeDataRejected(QString)), this, SLOT(addFastResumeRejectedAlert(QString)));
connect(BTSession, SIGNAL(aboutToDownloadFromUrl(QString)), this, SLOT(displayDownloadingUrlInfos(QString)));
connect(BTSession, SIGNAL(urlSeedProblem(QString, QString)), this, SLOT(addUrlSeedError(QString, QString)));
connect(BTSession, SIGNAL(UPnPError(QString)), this, SLOT(displayUPnPError(QString)));
connect(BTSession, SIGNAL(UPnPSuccess(QString)), this, SLOT(displayUPnPSuccess(QString)));
connect(BTSession, SIGNAL(forceUnfinishedListUpdate()), this, SLOT(updateDlList()));
// Load last columns width for download list
if(!loadColWidthDLList()) {
@@ -89,10 +89,11 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
downloadList->header()->setSortIndicatorShown(true);
// Connecting Actions to slots
connect(downloadList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
connect(downloadList->header(), SIGNAL(sectionPressed(int)), this, SLOT(toggleDownloadListSortOrder(int)));
connect(downloadList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortDownloadList(int)));
connect(downloadList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLListMenu(const QPoint&)));
downloadList->header()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(downloadList->header(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLHoSMenu(const QPoint&)));
connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&)));
// Actions
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
@@ -103,7 +104,6 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
connect(actionOpen_destination_folder, SIGNAL(triggered()), (GUI*)parent, SLOT(openDestinationFolder()));
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(actionHOSColName, SIGNAL(triggered()), this, SLOT(hideOrShowColumnName()));
@@ -117,7 +117,7 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
connect(actionHOSColPriority, SIGNAL(triggered()), this, SLOT(hideOrShowColumnPriority()));
// Set info Bar infos
BTSession->addConsoleMessage(tr("qBittorrent %1 started.", "e.g: qBittorrent v0.x started.").arg(QString::fromUtf8(""VERSION)));
setInfoBar(tr("qBittorrent %1 started.", "e.g: qBittorrent v0.x started.").arg(QString::fromUtf8(""VERSION)));
qDebug("Download tab built");
}
@@ -142,6 +142,16 @@ void DownloadingTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
emit torrentDoubleClicked(hash, false);
}
void DownloadingTorrents::addLogPeerBlocked(QString ip) {
static unsigned int nbLines = 0;
++nbLines;
if(nbLines > 200) {
textBlockedUsers->clear();
nbLines = 1;
}
textBlockedUsers->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</i>", "x.y.z.w was blocked").arg(ip));
}
unsigned int DownloadingTorrents::getNbTorrentsInList() const {
return nbTorrents;
}
@@ -157,7 +167,7 @@ void DownloadingTorrents::pauseTorrent(QString hash) {
DLListModel->setData(DLListModel->index(row, NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
QTorrentHandle h = BTSession->getTorrentHandle(hash);
//DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
setRowColor(row, QString::fromUtf8("red"));
}
@@ -166,6 +176,12 @@ QString DownloadingTorrents::getHashFromRow(unsigned int row) const {
return DLListModel->data(DLListModel->index(row, HASH)).toString();
}
void DownloadingTorrents::setBottomTabEnabled(unsigned int index, bool b){
if(index and !b)
tabBottom->setCurrentIndex(0);
tabBottom->setTabEnabled(index, b);
}
// Show torrent properties dialog
void DownloadingTorrents::showProperties(const QModelIndex &index) {
showPropertiesFromHash(DLListModel->data(DLListModel->index(index.row(), HASH)).toString());
@@ -179,6 +195,13 @@ void DownloadingTorrents::showPropertiesFromHash(QString hash) {
prop->show();
}
void DownloadingTorrents::resumeTorrent(QString hash){
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
// Remove a torrent from the download list but NOT from the BT Session
void DownloadingTorrents::deleteTorrent(QString hash) {
int row = getRowFromHash(hash);
@@ -191,10 +214,39 @@ void DownloadingTorrents::deleteTorrent(QString hash) {
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
void DownloadingTorrents::displayUPnPError(QString msg) {
setInfoBar(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(msg), QColor("red"));
}
void DownloadingTorrents::displayUPnPSuccess(QString msg) {
DownloadingTorrents::setInfoBar(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(msg), QColor("blue"));
}
// Update Info Bar information
void DownloadingTorrents::setInfoBar(QString info, QColor color) {
static unsigned int nbLines = 0;
++nbLines;
// Check log size, clear it if too big
if(nbLines > 200) {
infoBar->clear();
nbLines = 1;
}
infoBar->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + info + QString::fromUtf8("</i></font>"));
}
void DownloadingTorrents::addFastResumeRejectedAlert(QString name) {
setInfoBar(tr("Fast resume data was rejected for torrent %1, checking again...").arg(name), QString::fromUtf8("red"));
}
void DownloadingTorrents::addUrlSeedError(QString url, QString msg) {
setInfoBar(tr("Url seed lookup failed for url: %1, message: %2").arg(url).arg(msg), QString::fromUtf8("red"));
}
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();
@@ -206,8 +258,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();
@@ -220,30 +273,21 @@ 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);
}
}
}
void DownloadingTorrents::forceRecheck() {
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
foreach(const QModelIndex &index, selectedIndexes){
if(index.column() == NAME){
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
QTorrentHandle h = BTSession->getTorrentHandle(hash);
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;
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();
@@ -275,8 +319,6 @@ void DownloadingTorrents::displayDLListMenu(const QPoint&) {
myDLLlistMenu.addAction(actionSet_download_limit);
myDLLlistMenu.addAction(actionSet_upload_limit);
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionForce_recheck);
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionOpen_destination_folder);
myDLLlistMenu.addAction(actionTorrent_Properties);
if(BTSession->isQueueingEnabled()) {
@@ -287,7 +329,8 @@ void DownloadingTorrents::displayDLListMenu(const QPoint&) {
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionBuy_it);
// Call menu
myDLLlistMenu.exec(QCursor::pos());
// XXX: why mapToGlobal() is not enough?
myDLLlistMenu.exec(mapToGlobal(pos)+QPoint(10,35));
}
@@ -327,13 +370,21 @@ 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;
if(index == ETA) {
BTSession->setETACalculation(false);
qDebug("Disable ETA calculation");
}
} 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;
if(index == ETA) {
BTSession->setETACalculation(true);
qDebug("Enable ETA calculation");
}
}
//resize all others non-hidden columns
for(unsigned int i=0; i<nbCols; ++i) {
@@ -345,10 +396,6 @@ 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")));
else
getActionHoSCol(PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
}
// save the hidden columns in settings
@@ -386,9 +433,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;
@@ -430,6 +477,10 @@ void DownloadingTorrents::hideOrShowColumnPriority() {
hideOrShowColumn(PRIORITY);
}
void DownloadingTorrents::on_actionClearLog_triggered() {
infoBar->clear();
}
// getter, return the action hide or show whose id is index
QAction* DownloadingTorrents::getActionHoSCol(int index) {
switch(index) {
@@ -467,8 +518,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();
@@ -479,11 +531,33 @@ QStringList DownloadingTorrents::getSelectedTorrents(bool only_one) const{
return res;
}
void DownloadingTorrents::displayInfoBarMenu(const QPoint& pos) {
// Log Menu
QMenu myLogMenu(this);
myLogMenu.addAction(actionClearLog);
// XXX: Why mapToGlobal() is not enough?
myLogMenu.exec(mapToGlobal(pos)+QPoint(44,305));
}
void DownloadingTorrents::sortProgressColumnDelayed() {
if(delayedSorting) {
sortDownloadListFloat(PROGRESS, delayedSortingOrder);
qDebug("Delayed sorting of progress column");
}
}
// get information from torrent handles and
// update download list accordingly
bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
if(!h.is_valid()) return false;
bool added = false;
void DownloadingTorrents::updateDlList() {
// browse handles
QStringList unfinishedTorrents = BTSession->getUnfinishedTorrents();
QString hash;
foreach(hash, unfinishedTorrents) {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()){
qDebug("We have an invalid handle for: %s", qPrintable(hash));
continue;
}
try{
QString hash = h.hash();
int row = getRowFromHash(hash);
@@ -491,43 +565,69 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
qDebug("Info: Could not find filename in download list, adding it...");
addTorrent(hash);
row = getRowFromHash(hash);
added = true;
}
Q_ASSERT(row != -1);
// Update Priority
if(BTSession->isQueueingEnabled()) {
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);
if(!downloadList->isColumnHidden(PROGRESS)) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
}else {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
if(!downloadList->isColumnHidden(ETA)) {
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
}
}
// Reset speeds and seeds/leech
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant("0/0"));
setRowColor(row, QString::fromUtf8("grey"));
return added;
DLListModel->setData(DLListModel->index(row, PRIORITY), QVariant((int)BTSession->getDlTorrentPriority(hash)));
if(h.is_paused() && BTSession->isDownloadQueued(hash)) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
if(!downloadList->isColumnHidden(ETA)) {
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
}
setRowColor(row, QString::fromUtf8("grey"));
}
}
if(!downloadList->isColumnHidden(PROGRESS))
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
// No need to update a paused torrent
if(h.is_paused()) return added;
if(h.is_paused()) continue;
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) != -1) {
if(!downloadList->isColumnHidden(PROGRESS)) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
continue;
}
// Parse download state
// Setting download state
switch(h.state()) {
case torrent_status::finished:
case torrent_status::seeding:
qDebug("A torrent that was in download tab just finished, moving it to finished tab");
BTSession->setUnfinishedTorrent(hash);
emit torrentFinished(hash);
deleteTorrent(hash);
continue;
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"));
if(!downloadList->isColumnHidden(PROGRESS)) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
break;
case torrent_status::connecting_to_tracker:
if(h.download_payload_rate() > 0) {
// Display "Downloading" status when connecting if download speed > 0
if(!downloadList->isColumnHidden(ETA)) {
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
}
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("green"));
}else{
if(!downloadList->isColumnHidden(ETA)) {
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
}
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
if(!downloadList->isColumnHidden(PROGRESS)) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
if(!downloadList->isColumnHidden(DLSPEED)) {
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
}
if(!downloadList->isColumnHidden(UPSPEED)) {
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
}
break;
case torrent_status::downloading:
case torrent_status::downloading_metadata:
@@ -544,6 +644,9 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
}
setRowColor(row, QApplication::palette().color(QPalette::WindowText));
}
if(!downloadList->isColumnHidden(PROGRESS)) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
if(!downloadList->isColumnHidden(DLSPEED)) {
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
}
@@ -557,25 +660,24 @@ 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))));
}
}catch(invalid_handle e) {}
return added;
}catch(invalid_handle e) {
continue;
}
}
}
void DownloadingTorrents::addTorrent(QString hash) {
if(BTSession->isFinished(hash)){
BTSession->setUnfinishedTorrent(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
@@ -585,24 +687,20 @@ void DownloadingTorrents::addTorrent(QString hash) {
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
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)));
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
// Pause torrent if it is
if(h.is_paused()) {
// Pause torrent if it was paused last time
if(BTSession->isPaused(hash)) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("red"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/stalled.png"))), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
++nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
// sort List
sortDownloadList();
}
void DownloadingTorrents::sortDownloadListFloat(int index, Qt::SortOrder sortOrder) {
@@ -651,51 +749,27 @@ void DownloadingTorrents::sortDownloadListString(int index, Qt::SortOrder sortOr
DLListModel->removeRows(0, nbRows_old);
}
void DownloadingTorrents::toggleDownloadListSortOrder(int index) {
Qt::SortOrder sortOrder = Qt::AscendingOrder;
qDebug("Toggling column sort order");
if(downloadList->header()->sortIndicatorSection() == index) {
sortOrder = (Qt::SortOrder)!(bool)downloadList->header()->sortIndicatorOrder();
void DownloadingTorrents::sortDownloadList(int index, Qt::SortOrder startSortOrder, bool fromLoadColWidth) {
qDebug("Called sort download list");
static Qt::SortOrder sortOrder = startSortOrder;
if(!fromLoadColWidth && downloadList->header()->sortIndicatorSection() == index) {
if(sortOrder == Qt::AscendingOrder) {
sortOrder = Qt::DescendingOrder;
}else{
sortOrder = Qt::AscendingOrder;
}
}
switch(index) {
case SIZE:
case ETA:
case UPSPEED:
case DLSPEED:
case PROGRESS:
case PRIORITY:
case RATIO:
sortDownloadListFloat(index, sortOrder);
break;
default:
sortDownloadListString(index, sortOrder);
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString sortOrderLetter;
if(sortOrder == Qt::AscendingOrder)
sortOrderLetter = QString::fromUtf8("a");
else
sortOrderLetter = QString::fromUtf8("d");
settings.setValue(QString::fromUtf8("DownloadListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
void DownloadingTorrents::sortProgressColumn(QTorrentHandle& h) {
QString hash = h.hash();
int index = downloadList->header()->sortIndicatorSection();
if(index == PROGRESS) {
int row = getRowFromHash(hash);
if(row >= 0) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
Qt::SortOrder sortOrder = downloadList->header()->sortIndicatorOrder();
sortDownloadListFloat(index, sortOrder);
}
}
}
void DownloadingTorrents::sortDownloadList(int index, Qt::SortOrder sortOrder) {
if(index == -1) {
index = downloadList->header()->sortIndicatorSection();
sortOrder = downloadList->header()->sortIndicatorOrder();
if(fromLoadColWidth) {
// XXX: Why is this needed?
if(sortOrder == Qt::DescendingOrder)
downloadList->header()->setSortIndicator(index, Qt::AscendingOrder);
else
downloadList->header()->setSortIndicator(index, Qt::DescendingOrder);
} else {
downloadList->header()->setSortIndicator(index, sortOrder);
}
@@ -704,13 +778,23 @@ void DownloadingTorrents::sortDownloadList(int index, Qt::SortOrder sortOrder) {
case ETA:
case UPSPEED:
case DLSPEED:
case PRIORITY:
case PROGRESS:
sortDownloadListFloat(index, sortOrder);
break;
case PROGRESS:
if(fromLoadColWidth) {
// Progress sorting must be delayed until files are checked (on startup)
delayedSorting = true;
qDebug("Delayed sorting of the progress column");
delayedSortingOrder = sortOrder;
}else{
sortDownloadListFloat(index, sortOrder);
}
break;
default:
sortDownloadListString(index, sortOrder);
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("DownloadListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
// Save columns width in a file to remember them
@@ -726,7 +810,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) {
@@ -739,11 +823,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");
}
@@ -764,30 +843,7 @@ 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;
}
void DownloadingTorrents::loadLastSortedColumn() {
// Loading last sorted column
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString sortedCol = settings.value(QString::fromUtf8("DownloadListSortedCol"), QString()).toString();
if(!sortedCol.isEmpty()) {
Qt::SortOrder sortOrder;
@@ -797,8 +853,56 @@ void DownloadingTorrents::loadLastSortedColumn() {
sortOrder = Qt::AscendingOrder;
sortedCol = sortedCol.left(sortedCol.size()-1);
int index = sortedCol.toInt();
sortDownloadList(index, sortOrder);
sortDownloadList(index, sortOrder, true);
}
qDebug("Download list columns width loaded");
return true;
}
// Called when a torrent is added
void DownloadingTorrents::torrentAdded(QString path, QTorrentHandle& h, bool fastResume) {
QString hash = h.hash();
if(BTSession->isFinished(hash)) {
return;
}
if(getRowFromHash(hash) != -1) return;
int row = DLListModel->rowCount();
// Adding torrent to download list
DLListModel->insertRow(row);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
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, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
// Pause torrent if it was paused last time
// Not using isPaused function because torrents are paused after checking now
if(QFile::exists(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".paused"))) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("red"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
if(!fastResume) {
setInfoBar(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(path));
}else{
setInfoBar(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(path));
}
++nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
// Called when trying to add a duplicate torrent
void DownloadingTorrents::torrentDuplicate(QString path) {
setInfoBar(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(path));
}
void DownloadingTorrents::torrentCorrupted(QString path) {
setInfoBar(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(path), QString::fromUtf8("red"));
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red"));
}
void DownloadingTorrents::updateFileSizeAndProgress(QString hash) {
@@ -806,7 +910,13 @@ void DownloadingTorrents::updateFileSizeAndProgress(QString hash) {
Q_ASSERT(row != -1);
QTorrentHandle h = BTSession->getTorrentHandle(hash);
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
//DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
// Called when we couldn't listen on any port
// in the given range.
void DownloadingTorrents::portListeningFailure() {
setInfoBar(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
}
// Set the color of a row in data model
@@ -828,3 +938,7 @@ int DownloadingTorrents::getRowFromHash(QString hash) const{
}
return -1;
}
void DownloadingTorrents::displayDownloadingUrlInfos(QString url) {
setInfoBar(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(url), QPalette::WindowText);
}

View File

@@ -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
*/
@@ -47,7 +38,9 @@ class DownloadingTorrents : public QWidget, public Ui::downloading{
bittorrent *BTSession;
DLListDelegate *DLDelegate;
QStandardItemModel *DLListModel;
bool delayedSorting;
unsigned int nbTorrents;
Qt::SortOrder delayedSortingOrder;
void hideOrShowColumn(int index);
bool loadHiddenColumns();
void saveHiddenColumns();
@@ -67,19 +60,30 @@ class DownloadingTorrents : public QWidget, public Ui::downloading{
signals:
void unfinishedTorrentsNumberChanged(unsigned int);
void torrentDoubleClicked(QString hash, bool finished);
void torrentFinished(QString hash);
protected slots:
void addLogPeerBlocked(QString);
void addFastResumeRejectedAlert(QString);
void addUrlSeedError(QString url, QString msg);
void on_actionSet_download_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
void on_actionSet_upload_limit_triggered();
void displayDLListMenu(const QPoint& pos);
void displayDLHoSMenu(const QPoint&);
void sortDownloadList(int index=-1, Qt::SortOrder startSortOrder=Qt::AscendingOrder);
void toggleDownloadListSortOrder(int index);
void on_actionClearLog_triggered();
void displayInfoBarMenu(const QPoint& pos);
void addTorrent(QString hash);
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
void saveColWidthDLList() const;
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
void torrentDuplicate(QString path);
void torrentCorrupted(QString path);
void portListeningFailure();
void setRowColor(int row, QColor color);
void displayDownloadingUrlInfos(QString url);
void showProperties(const QModelIndex &index);
void hideOrShowColumnName();
void hideOrShowColumnSize();
@@ -90,19 +94,21 @@ class DownloadingTorrents : public QWidget, public Ui::downloading{
void hideOrShowColumnRatio();
void hideOrShowColumnEta();
void hideOrShowColumnPriority();
void forceRecheck();
void displayUPnPError(QString msg);
void displayUPnPSuccess(QString msg);
public slots:
bool updateTorrent(QTorrentHandle h);
void updateDlList();
void setInfoBar(QString info, QColor color=QApplication::palette().color(QPalette::WindowText));
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void deleteTorrent(QString hash);
void setBottomTabEnabled(unsigned int index, bool b);
void propertiesSelection();
void sortProgressColumnDelayed();
void updateFileSizeAndProgress(QString hash);
void showPropertiesFromHash(QString hash);
void hidePriorityColumn(bool hide);
void sortProgressColumn(QTorrentHandle& h);
void loadLastSortedColumn();
void addTorrent(QString hash);
};

View File

@@ -16,22 +16,12 @@
* 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 "engineSelectDlg.h"
#include "downloadThread.h"
#include "misc.h"
#include "ico.h"
#include "pluginSource.h"
#include <QProcess>
#include <QHeaderView>
@@ -42,6 +32,11 @@
#include <QDropEvent>
#include <QInputDialog>
#ifdef HAVE_MAGICK
#include <Magick++.h>
using namespace Magick;
#endif
#ifdef HAVE_ZZIP
#include <zzip/zzip.h>
#endif
@@ -57,8 +52,8 @@ engineSelectDlg::engineSelectDlg(QWidget *parent) : QDialog(parent) {
pluginsTree->header()->resizeSection(0, 170);
pluginsTree->header()->resizeSection(1, 220);
pluginsTree->hideColumn(ENGINE_ID);
actionEnable->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
actionDisable->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
actionEnable->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
actionDisable->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
actionUninstall->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
connect(actionEnable, SIGNAL(triggered()), this, SLOT(enableSelection()));
connect(actionDisable, SIGNAL(triggered()), this, SLOT(disableSelection()));
@@ -85,7 +80,7 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
QStringList files=event->mimeData()->text().split(QString::fromUtf8("\n"));
QString file;
foreach(file, files) {
qDebug("dropped %s", file.toLocal8Bit().data());
qDebug("dropped %s", file.toUtf8().data());
file = file.replace("file://", "");
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
downloader->downloadUrl(file);
@@ -108,7 +103,7 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
QString mime;
foreach(mime, event->mimeData()->formats()){
qDebug("mimeData: %s", mime.toLocal8Bit().data());
qDebug("mimeData: %s", mime.toUtf8().data());
}
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
event->acceptProposedAction();
@@ -123,7 +118,7 @@ void engineSelectDlg::saveSettings() {
foreach(engine, installed_engines.keys()) {
known_engines << engine;
known_enginesEnabled << QVariant(installed_engines.value(engine, true));
qDebug("Engine %s has state: %d", engine.toLocal8Bit().data(), installed_engines.value(engine, true));
qDebug("Engine %s has state: %d", engine.toUtf8().data(), installed_engines.value(engine, true));
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("SearchEngines/knownEngines"), known_engines);
@@ -132,7 +127,7 @@ void engineSelectDlg::saveSettings() {
void engineSelectDlg::on_updateButton_clicked() {
// Download version file from primary server
downloader->downloadUrl("http://www.dchris.eu/search_engine2/versions.txt");
downloader->downloadUrl("http://www.dchris.eu/search_engine/versions.txt");
}
void engineSelectDlg::toggleEngineState(QTreeWidgetItem *item, int) {
@@ -264,7 +259,7 @@ bool engineSelectDlg::checkInstalled(QString plugin_name) const {
result = result.replace("\r", "");
result = result.replace("\n", "");
QList<QByteArray> plugins_list = result.split(',');
return plugins_list.contains(plugin_name.toLocal8Bit());
return plugins_list.contains(plugin_name.toUtf8());
}
void engineSelectDlg::loadSupportedSearchEngines(bool first) {
@@ -333,13 +328,8 @@ void engineSelectDlg::loadSupportedSearchEngines(bool first) {
// Good, we already have the icon
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
} else {
iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".ico";
if(QFile::exists(iconPath)) { // ICO support
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
} else {
// Icon is missing, we must download it
downloader->downloadUrl(line.at(1)+"/favicon.ico");
}
// Icon is missing, we must download it
downloader->downloadUrl(line.at(1)+"/favicon.ico");
}
if(installed_engines.value(id, true))
setRowColor(i, "green");
@@ -379,7 +369,7 @@ bool engineSelectDlg::isUpdateNeeded(QString plugin_name, float new_version) con
void engineSelectDlg::installZipPlugin(QString path) {
QStringList plugins;
QStringList favicons;
ZZIP_DIR* dir = zzip_dir_open(path.toLocal8Bit().data(), 0);
ZZIP_DIR* dir = zzip_dir_open(path.toUtf8().data(), 0);
if(!dir) {
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("Search engine plugin archive could not be read."));
return;
@@ -412,8 +402,8 @@ void engineSelectDlg::installZipPlugin(QString path) {
foreach(plugin, plugins) {
QString plugin_name = plugin.split(QDir::separator()).last();
plugin_name.chop(3); // Remove .py extension
qDebug("Detected plugin %s in archive", plugin_name.toLocal8Bit().data());
ZZIP_FILE* fp = zzip_file_open(dir, plugin.toLocal8Bit().data(), 0);
qDebug("Detected plugin %s in archive", plugin_name.toUtf8().data());
ZZIP_FILE* fp = zzip_file_open(dir, plugin.toUtf8().data(), 0);
if(fp) {
QTemporaryFile *tmpfile = new QTemporaryFile();
QString tmpPath;
@@ -430,7 +420,7 @@ void engineSelectDlg::installZipPlugin(QString path) {
tmpfile->close();
} else {
qDebug("Could not open tmp file");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
delete tmpfile;
continue;
}
@@ -441,12 +431,12 @@ void engineSelectDlg::installZipPlugin(QString path) {
qDebug("Deleted tmpfile");
} else {
qDebug("Cannot read file in archive");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
}
}
QString favicon;
foreach(favicon, favicons) {
qDebug("Detected favicon %s in archive", favicon.toLocal8Bit().data());
qDebug("Detected favicon %s in archive", favicon.toUtf8().data());
// Ok we have a favicon here
QString plugin_name = favicon.split(QDir::separator()).last();
plugin_name.chop(4); // Remove .png extension
@@ -454,10 +444,8 @@ void engineSelectDlg::installZipPlugin(QString path) {
continue;
// Check if we already have a favicon for this plugin
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".png";
if(QFile::exists(iconPath)) {
QFile::remove(iconPath);
}
ZZIP_FILE* fp = zzip_file_open(dir, favicon.toLocal8Bit().data(), 0);
if(QFile::exists(iconPath)) continue;
ZZIP_FILE* fp = zzip_file_open(dir, favicon.toUtf8().data(), 0);
if(fp) {
QFile dest_icon(iconPath);
// Write icon
@@ -482,12 +470,12 @@ void engineSelectDlg::installZipPlugin(QString path) {
#endif
void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
qDebug("Asked to install plugin at %s", path.toLocal8Bit().data());
qDebug("Asked to install plugin at %s", path.toUtf8().data());
float new_version = misc::getPluginVersion(path);
qDebug("Version to be installed: %.2f", new_version);
if(!isUpdateNeeded(plugin_name, new_version)) {
qDebug("Apparently update it not needed, we have a more recent version");
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
}
// Process with install
@@ -509,12 +497,12 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
// restore backup
QFile::copy(dest_path+".bak", dest_path);
QFile::remove(dest_path+".bak");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
} else {
// Remove broken file
QFile::remove(dest_path);
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
}
}
@@ -525,10 +513,10 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
// Refresh plugin list
loadSupportedSearchEngines();
if(update) {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
} else {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
}
}
@@ -595,17 +583,17 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file, QString updateSer
plugin_name.chop(1); // remove trailing ':'
bool ok;
float version = list.last().toFloat(&ok);
qDebug("read line %s: %.2f", plugin_name.toLocal8Bit().data(), version);
qDebug("read line %s: %.2f", plugin_name.toUtf8().data(), version);
if(!ok) continue;
file_correct = true;
if(isUpdateNeeded(plugin_name, version)) {
qDebug("Plugin: %s is outdated", plugin_name.toLocal8Bit().data());
qDebug("Plugin: %s is outdated", plugin_name.toUtf8().data());
// Downloading update
downloader->downloadUrl(updateServer+plugin_name+".pyqBT"); // Actually this is really a .py
downloader->downloadUrl(updateServer+plugin_name+".png");
updated = true;
}else {
qDebug("Plugin: %s is up to date", plugin_name.toLocal8Bit().data());
qDebug("Plugin: %s is up to date", plugin_name.toUtf8().data());
}
}
// Close file
@@ -619,22 +607,30 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file, QString updateSer
}
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
qDebug("engineSelectDlg received %s", url.toLocal8Bit().data());
qDebug("engineSelectDlg received %s", url.toUtf8().data());
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
// Icon downloaded
QImage fileIcon;
#ifdef HAVE_MAGICK
try{
QFile::copy(filePath, filePath+".ico");
Image image(QDir::cleanPath(filePath+".ico").toUtf8().data());
// Convert to PNG since we can't read ICO format
image.magick("PNG");
// Resize to 16x16px
image.sample(Geometry(16, 16));
image.write(filePath.toUtf8().data());
QFile::remove(filePath+".ico");
}catch(Magick::Exception &error_){
qDebug("favicon conversion to PNG failure: %s", error_.what());
}
#endif
if(fileIcon.load(filePath)) {
QList<QTreeWidgetItem*> items = findItemsWithUrl(url);
QTreeWidgetItem *item;
foreach(item, items){
QString id = item->text(ENGINE_ID);
QString iconPath;
QFile icon(filePath);
icon.open(QIODevice::ReadOnly);
if(ICOHandler::canRead(&icon))
iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".ico";
else
iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".png";
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".png";
QFile::copy(filePath, iconPath);
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
}
@@ -643,16 +639,16 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
QFile::remove(filePath);
return;
}
if(url == "http://www.dchris.eu/search_engine2/versions.txt") {
if(!parseVersionsFile(filePath, "http://www.dchris.eu/search_engine2/")) {
if(url == "http://www.dchris.eu/search_engine/versions.txt") {
if(!parseVersionsFile(filePath, "http://www.dchris.eu/search_engine/")) {
qDebug("Primary update server failed, try secondary");
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine2/versions.txt");
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine/versions.txt");
}
QFile::remove(filePath);
return;
}
if(url == "http://hydr0g3n.free.fr/search_engine2/versions.txt") {
if(!parseVersionsFile(filePath, "http://hydr0g3n.free.fr/search_engine2/")) {
if(url == "http://hydr0g3n.free.fr/search_engine/versions.txt") {
if(!parseVersionsFile(filePath, "http://hydr0g3n.free.fr/search_engine/")) {
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
}
QFile::remove(filePath);
@@ -677,16 +673,16 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
qDebug("Could not download favicon: %s, reason: %s", url.toLocal8Bit().data(), reason.toLocal8Bit().data());
qDebug("Could not download favicon: %s, reason: %s", url.toUtf8().data(), reason.toUtf8().data());
return;
}
if(url == "http://www.dchris.eu/search_engine2/versions.txt") {
if(url == "http://www.dchris.eu/search_engine/versions.txt") {
// Primary update server failed, try secondary
qDebug("Primary update server failed, try secondary");
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine2/versions.txt");
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine/versions.txt");
return;
}
if(url == "http://hydr0g3n.free.fr/search_engine2/versions.txt") {
if(url == "http://hydr0g3n.free.fr/search_engine/versions.txt") {
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
return;
}
@@ -695,13 +691,13 @@ void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
QString plugin_name = url.split('/').last();
plugin_name.replace(".pyqBT", "", Qt::CaseInsensitive);
plugin_name.replace(".py", "", Qt::CaseInsensitive);
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
}
#ifdef HAVE_ZZIP
if(url.endsWith(".zip", Qt::CaseInsensitive)) {
QString plugin_name = url.split('/').last();
plugin_name.replace(".zip", "", Qt::CaseInsensitive);
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
}
#endif
}

View File

@@ -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
*/

View File

@@ -1,105 +1,189 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
* Copyright (C) 2007 by Ishan Arora
* ishanarora@gmail.com
*
* 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 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.
* 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
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "eventmanager.h"
#include "bittorrent.h"
#include "json.h"
#include <QDebug>
EventManager::EventManager(QObject *parent, bittorrent *BTSession)
: QObject(parent), BTSession(BTSession)
{
revision = 0;
}
QList<QVariantMap> EventManager::getEventList() const {
return event_list.values();
}
void EventManager::addedTorrent(QTorrentHandle& h)
void EventManager::update(QVariantMap event)
{
modifiedTorrent(h);
revision++;
events << QPair<ulong, QVariantMap>(revision, event);
emit updated();
qDebug("Added the following event");
qDebug() << event;
/* QLinkedList<QPair<ulong, QVariantMap> >::iterator i;
for (i = events.begin(); i != events.end(); i++)
qDebug() << *i;*/
}
QVariant EventManager::querySince(ulong r) const
{
QVariantList list;
QLinkedListIterator<QPair<ulong, QVariantMap> > i(events);
i.toBack();
while (i.hasPrevious())
{
QPair<ulong, QVariantMap> pair = i.previous();
if (pair.first <= r)
break;
list.prepend(QVariant(pair.second));
}
QVariantMap map;
map["events"] = QVariant(list);
map["revision"] = QVariant((qulonglong) revision);
return QVariant(map);
}
bool EventManager::isUpdated(ulong r) const
{
return (r < revision);
}
void EventManager::addedTorrent(QString, QTorrentHandle& h)
{
QVariantMap event;
event["type"] = QVariant("add");
event["hash"] = QVariant(h.hash());
event["name"] = QVariant(h.name());
update(event);
}
void EventManager::deletedTorrent(QString hash)
{
event_list.remove(hash);
QVariantMap event;
event["type"] = QVariant("delete");
event["hash"] = QVariant(hash);
QLinkedList<QPair<ulong, QVariantMap> >::iterator i = events.end();
bool loop = true;
while (loop && i != events.begin()) {
--i;
QVariantMap oldevent = i->second;
if(oldevent["hash"] == QVariant(hash))
{
if(oldevent["type"] == QVariant("add"))
loop = false;
i = events.erase(i);
}
}
update(event);
}
void EventManager::modifiedTorrent(QTorrentHandle h)
{
QString hash = h.hash();
QVariantMap event;
if(h.is_paused()) {
event["state"] = QVariant("paused");
} else {
if(BTSession->isQueueingEnabled() && h.is_queued()) {
event["state"] = QVariant("queued");
} else {
switch(h.state())
{
case torrent_status::finished:
case torrent_status::seeding:
event["state"] = QVariant("seeding");
break;
case torrent_status::checking_files:
case torrent_status::queued_for_checking:
event["state"] = QVariant("checking");
break;
case torrent_status::allocating:
case torrent_status::downloading:
case torrent_status::downloading_metadata:
if(h.download_payload_rate() > 0)
event["state"] = QVariant("downloading");
else
event["state"] = QVariant("stalled");
break;
default:
qDebug("No status, should not happen!!! status is %d", h.state());
event["state"] = QVariant();
}
}
}
event["name"] = QVariant(h.name());
event["size"] = QVariant((qlonglong)h.actual_size());
if(!h.is_seed()) {
event["progress"] = QVariant(h.progress());
event["dlspeed"] = QVariant(h.download_payload_rate());
if(BTSession->isQueueingEnabled()) {
event["priority"] = QVariant(h.queue_position());
} else {
event["priority"] = -1;
}
QString hash = h.hash();
QVariantMap event;
QVariant v;
if(h.is_paused()) {
if(BTSession->isDownloadQueued(hash) || BTSession->isUploadQueued(hash))
v = QVariant("queued");
else
v = QVariant("paused");
} else {
switch(h.state())
{
case torrent_status::finished:
case torrent_status::seeding:
v = QVariant("seeding");
break;
case torrent_status::checking_files:
case torrent_status::queued_for_checking:
v = QVariant("checking");
break;
case torrent_status::connecting_to_tracker:
if(h.download_payload_rate() > 0)
v = QVariant("downloading");
else
v = QVariant("connecting");
break;
case torrent_status::downloading:
case torrent_status::downloading_metadata:
if(h.download_payload_rate() > 0)
v = QVariant("downloading");
else
v = QVariant("stalled");
break;
default:
v = QVariant();
}
}
if(modify(hash, "state", v))
event["state"] = v;
v = QVariant((qlonglong)h.actual_size());
if(modify(hash, "size", v))
event["size"] = v;
v = QVariant(h.progress());
if(modify(hash, "progress", v))
event["progress"] = v;
v = QVariant(h.download_payload_rate());
if(modify(hash, "dlspeed", v))
event["dlspeed"] = v;
v = QVariant(h.upload_payload_rate());
if(modify(hash, "upspeed", v))
event["upspeed"] = v;
if(event.size() > 0)
{
event["type"] = QVariant("modify");
event["hash"] = QVariant(hash);
update(event);
}
event["upspeed"] = QVariant(h.upload_payload_rate());
event["seed"] = QVariant(h.is_seed());
event["hash"] = QVariant(hash);
event_list[hash] = event;
}
bool EventManager::modify(QString hash, QString key, QVariant value)
{
QLinkedList<QPair<ulong, QVariantMap> >::iterator i = events.end();
while (i != events.begin()) {
--i;
QVariantMap event = i->second;
if(event["hash"] == QVariant(hash))
{
if(event["type"] == QVariant("add"))
return true;
if(event.contains(key))
{
if(event[key] == value)
return false;
else
{
if(event.size() <= 3)
i = events.erase(i);
else
i->second.remove(key);
return true;
}
}
}
}
return true;
}

Some files were not shown because too many files have changed in this diff Show More