mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-22 16:37:21 -06:00
Compare commits
44 Commits
release-1.
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
603b14dd4c | ||
|
|
faa33b0d7e | ||
|
|
8fdf3d520c | ||
|
|
b238a4ed69 | ||
|
|
ba53bdc708 | ||
|
|
f2a65e07b5 | ||
|
|
62afd4f98b | ||
|
|
6c11fd5a0d | ||
|
|
cc39504a61 | ||
|
|
1baec5378f | ||
|
|
b60b4fafff | ||
|
|
3325dd0550 | ||
|
|
29dc0fede0 | ||
|
|
19f6b8491e | ||
|
|
01b1e78dcd | ||
|
|
bd546e3d18 | ||
|
|
6ca93dfbae | ||
|
|
f175ce5249 | ||
|
|
940a8b28e4 | ||
|
|
9ee9c7d362 | ||
|
|
2899494ef3 | ||
|
|
624e2b287a | ||
|
|
681d538163 | ||
|
|
60f1a1989c | ||
|
|
050dc9de44 | ||
|
|
d80f94643f | ||
|
|
1b4bb7655f | ||
|
|
e8ffaa2f87 | ||
|
|
a89188acc3 | ||
|
|
993002a151 | ||
|
|
8bcaf55439 | ||
|
|
48aac758c9 | ||
|
|
4ba2c3d385 | ||
|
|
d96e21c07f | ||
|
|
1204cebaa1 | ||
|
|
1695e85bdf | ||
|
|
33305cca9f | ||
|
|
04b683c38c | ||
|
|
d55cd9aec8 | ||
|
|
0b5652bd72 | ||
|
|
878787e965 | ||
|
|
3536577af6 | ||
|
|
9f2d9e4d3f | ||
|
|
efe0dbabaa |
@@ -42,12 +42,12 @@
|
|||||||
- FEATURE: Added an option to display current transfer speeds in title bar
|
- FEATURE: Added an option to display current transfer speeds in title bar
|
||||||
- FEATURE: Torrent content is now displayed as a tree
|
- FEATURE: Torrent content is now displayed as a tree
|
||||||
- FEATURE: Better media file preview (player detected automatically)
|
- FEATURE: Better media file preview (player detected automatically)
|
||||||
|
- FEATURE: Greatly improved ETA calculation algorithm (use GASA)
|
||||||
- I18N: Added Hungarian translation
|
- I18N: Added Hungarian translation
|
||||||
- I18N: Added Brazilian translation
|
- I18N: Added Brazilian translation
|
||||||
- BUGFIX: Progress of paused torrents is now correct on restart
|
- BUGFIX: Progress of paused torrents is now correct on restart
|
||||||
- BUGFIX: clear the results of a search stops searching
|
- BUGFIX: clear the results of a search stops searching
|
||||||
- BUGFIX: Progress column gets sorted on restart it is was during last execution
|
- BUGFIX: Progress column gets sorted on restart it is was during last execution
|
||||||
- BUGFIX: Made ETA more reliable using stats instead of instant values
|
|
||||||
- BUGFIX: Remove torrent from hard drive used to delete parent folder if empty
|
- BUGFIX: Remove torrent from hard drive used to delete parent folder if empty
|
||||||
- BUGFIX: Fixed a crash when filtering all the files in a torrent
|
- BUGFIX: Fixed a crash when filtering all the files in a torrent
|
||||||
- BUGFIX: Reload torrent only when necessary (properties)
|
- BUGFIX: Reload torrent only when necessary (properties)
|
||||||
|
|||||||
2
INSTALL
2
INSTALL
@@ -25,7 +25,7 @@ Dependencies:
|
|||||||
|
|
||||||
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
|
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
|
||||||
|
|
||||||
- libcommoncpp2
|
- libcurl
|
||||||
|
|
||||||
- python >= 2.3 (needed by search engine)
|
- python >= 2.3 (needed by search engine)
|
||||||
|
|
||||||
|
|||||||
25
TODO
25
TODO
@@ -50,19 +50,14 @@
|
|||||||
-> in download list
|
-> in download list
|
||||||
-> in seeding list
|
-> in seeding list
|
||||||
|
|
||||||
// TODO v1.0.0
|
TODO:
|
||||||
- Fix libcommoncpp proxy support
|
- Check search engine cpu usage
|
||||||
- Fix layout in preferences/Proxy
|
|
||||||
|
|
||||||
rc8->rc9 changelog:
|
rc10->rc11? changelog:
|
||||||
- FEATURE: Better media file preview (player detected automatically)
|
- BUGFIX: Bypass exit confirmation on system shutdown
|
||||||
- BUGFIX: Remember properties window size and position
|
- BUGFIX: Download from urls are now able to follow redirections
|
||||||
- BUGFIX: Added proxy support in search engine, RSS, downloads from urls
|
- BUGFIX: Clean up for failed torrents downloaded from urls
|
||||||
- BUGFIX: Do no pause torrents before saving fastresume data anymore (no longer needed)
|
- BUGFIX: Fixed downloads from URLs on Windows
|
||||||
- BUGFIX: Save fast resume data regularly (every 60 seconds) to avoid downloading from scratch if qBittorrent crashes
|
- BUGFIX: Fixed search engine on Windows
|
||||||
- BUGFIX: Do not save fastresume data for checking torrents anymore
|
- BUGFIX: Fixed torrent creation from a directory
|
||||||
- BUGFIX: Saving trackers file only when necessary
|
- BUGFIX: Fixed save path when seeding automatically after torrent creation
|
||||||
- BUGFIX: Fixed possible segfault when unfiltering files in torrent addition dialog
|
|
||||||
- BUGFIX: Fixed possible overflow in ETA calculation
|
|
||||||
- BUGFIX: title bar is now reset when "Display speed in title" is disabled
|
|
||||||
- BUGFIX: Fixed HTTP_PW and SOCKS5_PW in proxy combobox
|
|
||||||
|
|||||||
58
configure
vendored
58
configure
vendored
@@ -22,8 +22,8 @@ Dependency options:
|
|||||||
--with-libtorrent-lib=[path] Path to libtorrent library files
|
--with-libtorrent-lib=[path] Path to libtorrent library files
|
||||||
--with-libtorrent-static-lib=[path] Path to libtorrent .a file
|
--with-libtorrent-static-lib=[path] Path to libtorrent .a file
|
||||||
--with-libboost-inc=[path] Path to libboost include files
|
--with-libboost-inc=[path] Path to libboost include files
|
||||||
--with-libcommoncpp2-inc=[path] Path to libcommoncpp2 include files
|
--with-libcurl-inc=[path] Path to libcurl include files
|
||||||
--with-libcommoncpp2-lib=[path] Path to libcommoncpp2 library files
|
--with-libcurl-lib=[path] Path to libcurl library files
|
||||||
--disable-libmagick Disable use of libmagick
|
--disable-libmagick Disable use of libmagick
|
||||||
--with-libmagick-inc=[path] Path to libmagick++ include files
|
--with-libmagick-inc=[path] Path to libmagick++ include files
|
||||||
--with-libmagick-lib=[path] Path to libmagick++ library files
|
--with-libmagick-lib=[path] Path to libmagick++ library files
|
||||||
@@ -166,13 +166,13 @@ while [ $# -gt 0 ]; do
|
|||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
|
||||||
--with-libcommoncpp2-inc=*)
|
--with-libcurl-inc=*)
|
||||||
QC_WITH_LIBCOMMONCPP2_INC=$optarg
|
QC_WITH_LIBCURL_INC=$optarg
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
|
||||||
--with-libcommoncpp2-lib=*)
|
--with-libcurl-lib=*)
|
||||||
QC_WITH_LIBCOMMONCPP2_LIB=$optarg
|
QC_WITH_LIBCURL_LIB=$optarg
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -231,8 +231,8 @@ echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC
|
|||||||
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
|
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
|
||||||
echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB
|
echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB
|
||||||
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
|
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
|
||||||
echo QC_WITH_LIBCOMMONCPP2_INC=$QC_WITH_LIBCOMMONCPP2_INC
|
echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC
|
||||||
echo QC_WITH_LIBCOMMONCPP2_LIB=$QC_WITH_LIBCOMMONCPP2_LIB
|
echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB
|
||||||
echo QC_DISABLE_libmagick=$QC_DISABLE_libmagick
|
echo QC_DISABLE_libmagick=$QC_DISABLE_libmagick
|
||||||
echo QC_WITH_LIBMAGICK_INC=$QC_WITH_LIBMAGICK_INC
|
echo QC_WITH_LIBMAGICK_INC=$QC_WITH_LIBMAGICK_INC
|
||||||
echo QC_WITH_LIBMAGICK_LIB=$QC_WITH_LIBMAGICK_LIB
|
echo QC_WITH_LIBMAGICK_LIB=$QC_WITH_LIBMAGICK_LIB
|
||||||
@@ -485,25 +485,25 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#line 1 "libcommoncpp2.qcm"
|
#line 1 "libcurl.qcm"
|
||||||
/*
|
/*
|
||||||
-----BEGIN QCMOD-----
|
-----BEGIN QCMOD-----
|
||||||
name: libcommoncpp2
|
name: libcommoncpp2
|
||||||
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
|
arg: with-libcurl-inc=[path], Path to libcurl include files
|
||||||
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
|
arg: with-libcurl-lib=[path], Path to libcurl library files
|
||||||
-----END QCMOD-----
|
-----END QCMOD-----
|
||||||
*/
|
*/
|
||||||
class qc_libcommoncpp2 : public ConfObj
|
class qc_libcurl : public ConfObj
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
qc_libcommoncpp2(Conf *c) : ConfObj(c) {}
|
qc_libcurl(Conf *c) : ConfObj(c) {}
|
||||||
QString name() const { return "GNU Common C++ library (libcommoncpp2)"; }
|
QString name() const { return "libcurl"; }
|
||||||
QString shortname() const { return "libcommoncpp2"; }
|
QString shortname() const { return "libcurl"; }
|
||||||
bool exec(){
|
bool exec(){
|
||||||
QString s;
|
QString s;
|
||||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
|
s = conf->getenv("QC_WITH_LIBCURL_INC");
|
||||||
if(!s.isEmpty()) {
|
if(!s.isEmpty()) {
|
||||||
if(!conf->checkHeader(s, "cc++/url.h")) {
|
if(!conf->checkHeader(s, "curl/curl.h")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -512,7 +512,7 @@ public:
|
|||||||
sl << "/usr/local/include";
|
sl << "/usr/local/include";
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach(s, sl){
|
foreach(s, sl){
|
||||||
if(conf->checkHeader(s, "cc++/url.h")){
|
if(conf->checkHeader(s, "curl/curl.h")){
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -523,12 +523,10 @@ public:
|
|||||||
}
|
}
|
||||||
conf->addIncludePath(s);
|
conf->addIncludePath(s);
|
||||||
|
|
||||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
|
s = conf->getenv("QC_WITH_LIBCURL_LIB");
|
||||||
if(!s.isEmpty()) {
|
if(!s.isEmpty()) {
|
||||||
if(!QFile::exists(s+QString("/libccext2.so")))
|
if(!QFile::exists(s+QString("/libcurl.so")))
|
||||||
return false;
|
return false;
|
||||||
if(!QFile::exists(s+QString("/libccgnu2.so")))
|
|
||||||
return false;
|
|
||||||
conf->addLib(QString("-L") + s);
|
conf->addLib(QString("-L") + s);
|
||||||
}else{
|
}else{
|
||||||
QStringList sl;
|
QStringList sl;
|
||||||
@@ -538,11 +536,9 @@ public:
|
|||||||
sl << "/usr/local/lib64/";
|
sl << "/usr/local/lib64/";
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach(s, sl){
|
foreach(s, sl){
|
||||||
if(QFile::exists(s+QString("libccext2.so"))){
|
if(QFile::exists(s+QString("libcurl.so"))){
|
||||||
if(QFile::exists(s+QString("libccgnu2.so"))){
|
found = true;
|
||||||
found = true;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!found) return false;
|
if(!found) return false;
|
||||||
@@ -715,7 +711,7 @@ cat >$1/modules_new.cpp <<EOT
|
|||||||
o = new qc_libboost(conf);
|
o = new qc_libboost(conf);
|
||||||
o->required = true;
|
o->required = true;
|
||||||
o->disabled = false;
|
o->disabled = false;
|
||||||
o = new qc_libcommoncpp2(conf);
|
o = new qc_libcurl(conf);
|
||||||
o->required = true;
|
o->required = true;
|
||||||
o->disabled = false;
|
o->disabled = false;
|
||||||
o = new qc_libmagick(conf);
|
o = new qc_libmagick(conf);
|
||||||
@@ -1673,8 +1669,8 @@ export QC_WITH_LIBTORRENT_INC
|
|||||||
export QC_WITH_LIBTORRENT_LIB
|
export QC_WITH_LIBTORRENT_LIB
|
||||||
export QC_WITH_LIBTORRENT_STATIC_LIB
|
export QC_WITH_LIBTORRENT_STATIC_LIB
|
||||||
export QC_WITH_LIBBOOST_INC
|
export QC_WITH_LIBBOOST_INC
|
||||||
export QC_WITH_LIBCOMMONCPP2_INC
|
export QC_WITH_LIBCURL_INC
|
||||||
export QC_WITH_LIBCOMMONCPP2_LIB
|
export QC_WITH_LIBCURL_LIB
|
||||||
export QC_DISABLE_libmagick
|
export QC_DISABLE_libmagick
|
||||||
export QC_WITH_LIBMAGICK_INC
|
export QC_WITH_LIBMAGICK_INC
|
||||||
export QC_WITH_LIBMAGICK_LIB
|
export QC_WITH_LIBMAGICK_LIB
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<dep type='libboost'>
|
<dep type='libboost'>
|
||||||
<required/>
|
<required/>
|
||||||
</dep>
|
</dep>
|
||||||
<dep type='libcommoncpp2'>
|
<dep type='libcurl'>
|
||||||
<required/>
|
<required/>
|
||||||
</dep>
|
</dep>
|
||||||
<dep type='libmagick'/>
|
<dep type='libmagick'/>
|
||||||
|
|||||||
61
qcm/libcurl.qcm
Normal file
61
qcm/libcurl.qcm
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
-----BEGIN QCMOD-----
|
||||||
|
name: libcommoncpp2
|
||||||
|
arg: with-libcurl-inc=[path], Path to libcurl include files
|
||||||
|
arg: with-libcurl-lib=[path], Path to libcurl library files
|
||||||
|
-----END QCMOD-----
|
||||||
|
*/
|
||||||
|
class qc_libcurl : public ConfObj
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
qc_libcurl(Conf *c) : ConfObj(c) {}
|
||||||
|
QString name() const { return "libcurl"; }
|
||||||
|
QString shortname() const { return "libcurl"; }
|
||||||
|
bool exec(){
|
||||||
|
QString s;
|
||||||
|
s = conf->getenv("QC_WITH_LIBCURL_INC");
|
||||||
|
if(!s.isEmpty()) {
|
||||||
|
if(!conf->checkHeader(s, "curl/curl.h")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
QStringList sl;
|
||||||
|
sl << "/usr/include";
|
||||||
|
sl << "/usr/local/include";
|
||||||
|
bool found = false;
|
||||||
|
foreach(s, sl){
|
||||||
|
if(conf->checkHeader(s, "curl/curl.h")){
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conf->addIncludePath(s);
|
||||||
|
|
||||||
|
s = conf->getenv("QC_WITH_LIBCURL_LIB");
|
||||||
|
if(!s.isEmpty()) {
|
||||||
|
if(!QFile::exists(s+QString("/libcurl.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("libcurl.so"))){
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) return false;
|
||||||
|
conf->addLib(QString("-L") + s);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
34
src/GUI.cpp
34
src/GUI.cpp
@@ -392,10 +392,10 @@ void GUI::on_actionExit_triggered() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GUI::previewFile(QString filePath) {
|
void GUI::previewFile(QString filePath) {
|
||||||
QDesktopServices::openUrl(filePath);
|
QDesktopServices::openUrl(QString("file://")+filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int GUI::getCurrentTabIndex() const{
|
int GUI::getCurrentTabIndex() const{
|
||||||
if(isMinimized() || isHidden())
|
if(isMinimized() || isHidden())
|
||||||
return -1;
|
return -1;
|
||||||
return tabs->currentIndex();
|
return tabs->currentIndex();
|
||||||
@@ -449,7 +449,7 @@ void GUI::on_actionAbout_triggered() {
|
|||||||
|
|
||||||
// Called when we close the program
|
// Called when we close the program
|
||||||
void GUI::closeEvent(QCloseEvent *e) {
|
void GUI::closeEvent(QCloseEvent *e) {
|
||||||
qDebug("Mainwindow received closeEvent");
|
|
||||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||||
bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool();
|
bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool();
|
||||||
if(!force_exit && systrayIntegration && goToSystrayOnExit && !this->isHidden()) {
|
if(!force_exit && systrayIntegration && goToSystrayOnExit && !this->isHidden()) {
|
||||||
@@ -461,13 +461,16 @@ void GUI::closeEvent(QCloseEvent *e) {
|
|||||||
show();
|
show();
|
||||||
if(!isMaximized())
|
if(!isMaximized())
|
||||||
showNormal();
|
showNormal();
|
||||||
if(QMessageBox::question(this,
|
if(e->spontaneous() == true || force_exit == true) {
|
||||||
tr("Are you sure you want to quit?")+QString::fromUtf8(" -- ")+tr("qBittorrent"),
|
if(QMessageBox::question(this,
|
||||||
tr("The download list is not empty.\nAre you sure you want to quit qBittorrent?"),
|
tr("Are you sure you want to quit?")+QString::fromUtf8(" -- ")+tr("qBittorrent"),
|
||||||
tr("&Yes"), tr("&No"),
|
tr("The download list is not empty.\nAre you sure you want to quit qBittorrent?"),
|
||||||
QString(), 0, 1)) {
|
tr("&Yes"), tr("&No"),
|
||||||
e->ignore();
|
QString(), 0, 1)) {
|
||||||
return;
|
e->ignore();
|
||||||
|
force_exit = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hide();
|
hide();
|
||||||
@@ -485,6 +488,7 @@ void GUI::closeEvent(QCloseEvent *e) {
|
|||||||
qApp->exit();
|
qApp->exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Display window to create a torrent
|
// Display window to create a torrent
|
||||||
void GUI::on_actionCreate_torrent_triggered() {
|
void GUI::on_actionCreate_torrent_triggered() {
|
||||||
createtorrent *ct = new createtorrent(this);
|
createtorrent *ct = new createtorrent(this);
|
||||||
@@ -855,10 +859,20 @@ void GUI::configureSession(bool deleteOptions) {
|
|||||||
}
|
}
|
||||||
if(!proxy_str.isEmpty()) {
|
if(!proxy_str.isEmpty()) {
|
||||||
// We need this for urllib in search engine plugins
|
// We need this for urllib in search engine plugins
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
char proxystr[512];
|
||||||
|
snprintf(proxystr, 512, "http_proxy=%s", proxy_str.toUtf8().data());
|
||||||
|
putenv(proxystr);
|
||||||
|
#else
|
||||||
setenv("http_proxy", proxy_str.toUtf8().data(), 1);
|
setenv("http_proxy", proxy_str.toUtf8().data(), 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
putenv("http_proxy=");
|
||||||
|
#else
|
||||||
unsetenv("http_proxy");
|
unsetenv("http_proxy");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
BTSession->setProxySettings(proxySettings, options->useProxyForTrackers(), options->useProxyForPeers(), options->useProxyForWebseeds(), options->useProxyForDHT());
|
BTSession->setProxySettings(proxySettings, options->useProxyForTrackers(), options->useProxyForPeers(), options->useProxyForWebseeds(), options->useProxyForDHT());
|
||||||
// * Session settings
|
// * Session settings
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
|||||||
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
|
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
|
||||||
~GUI();
|
~GUI();
|
||||||
// Methods
|
// Methods
|
||||||
unsigned int getCurrentTabIndex() const;
|
int getCurrentTabIndex() const;
|
||||||
QPoint screenCenter() const;
|
QPoint screenCenter() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,10 @@
|
|||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
#include <boost/filesystem/exception.hpp>
|
#include <boost/filesystem/exception.hpp>
|
||||||
|
|
||||||
#define ETAS_MAX_VALUES 3
|
|
||||||
#define ETA_REFRESH_INTERVAL 10000
|
|
||||||
#define MAX_TRACKER_ERRORS 2
|
#define MAX_TRACKER_ERRORS 2
|
||||||
|
|
||||||
// Main constructor
|
// Main constructor
|
||||||
bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1) {
|
bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false) {
|
||||||
// To avoid some exceptions
|
// To avoid some exceptions
|
||||||
fs::path::default_name_check(fs::no_check);
|
fs::path::default_name_check(fs::no_check);
|
||||||
// Creating bittorrent session
|
// Creating bittorrent session
|
||||||
@@ -55,11 +53,8 @@ bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false
|
|||||||
timerAlerts = new QTimer();
|
timerAlerts = new QTimer();
|
||||||
connect(timerAlerts, SIGNAL(timeout()), this, SLOT(readAlerts()));
|
connect(timerAlerts, SIGNAL(timeout()), this, SLOT(readAlerts()));
|
||||||
timerAlerts->start(3000);
|
timerAlerts->start(3000);
|
||||||
ETARefresher = new QTimer();
|
|
||||||
connect(ETARefresher, SIGNAL(timeout()), this, SLOT(updateETAs()));
|
|
||||||
ETARefresher->start(ETA_REFRESH_INTERVAL);
|
|
||||||
fastResumeSaver = new QTimer();
|
fastResumeSaver = new QTimer();
|
||||||
connect(fastResumeSaver, SIGNAL(timeout()), this, SLOT(saveFastResumeAndRatioDataUnfinished()));
|
connect(fastResumeSaver, SIGNAL(timeout()), this, SLOT(saveFastResumeAndRatioData()));
|
||||||
fastResumeSaver->start(60000);
|
fastResumeSaver->start(60000);
|
||||||
// To download from urls
|
// To download from urls
|
||||||
downloader = new downloadThread(this);
|
downloader = new downloadThread(this);
|
||||||
@@ -67,6 +62,7 @@ bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false
|
|||||||
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||||
// File deleter (thread)
|
// File deleter (thread)
|
||||||
deleter = new deleteThread(this);
|
deleter = new deleteThread(this);
|
||||||
|
BigRatioTimer = 0;
|
||||||
qDebug("* BTSession constructed");
|
qDebug("* BTSession constructed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +74,8 @@ bittorrent::~bittorrent() {
|
|||||||
delete deleter;
|
delete deleter;
|
||||||
delete fastResumeSaver;
|
delete fastResumeSaver;
|
||||||
delete timerAlerts;
|
delete timerAlerts;
|
||||||
delete ETARefresher;
|
if(BigRatioTimer != 0)
|
||||||
|
delete BigRatioTimer;
|
||||||
delete downloader;
|
delete downloader;
|
||||||
// Delete BT session
|
// Delete BT session
|
||||||
delete s;
|
delete s;
|
||||||
@@ -143,57 +140,34 @@ void bittorrent::startTorrentsInPause(bool b) {
|
|||||||
addInPause = b;
|
addInPause = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bittorrent::updateETAs() {
|
// Calculate the ETA using GASA
|
||||||
QString hash;
|
// GASA: global Average Speed Algorithm
|
||||||
foreach(hash, unfinishedTorrents) {
|
qlonglong bittorrent::getETA(QString hash) const {
|
||||||
QTorrentHandle h = getTorrentHandle(hash);
|
QTorrentHandle h = getTorrentHandle(hash);
|
||||||
if(h.is_valid()) {
|
if(!h.is_valid()) return -1;
|
||||||
if(h.is_paused()) continue;
|
switch(h.state()) {
|
||||||
QString hash = h.hash();
|
case torrent_status::downloading:
|
||||||
QList<qlonglong> listEtas = ETAstats.value(hash, QList<qlonglong>());
|
case torrent_status::connecting_to_tracker: {
|
||||||
// XXX: We can still get an overflow if remaining file size is approximately
|
if(!TorrentsStartTime.contains(hash)) return -1;
|
||||||
// 8.38*10^5 TiB (let's assume this can't happen)
|
int timeElapsed = TorrentsStartTime.value(hash).secsTo(QDateTime::currentDateTime());
|
||||||
if(h.download_payload_rate() > 0.1) {
|
double avg_speed;
|
||||||
if(listEtas.size() == ETAS_MAX_VALUES) {
|
if(timeElapsed) {
|
||||||
listEtas.removeFirst();
|
size_type data_origin = TorrentsStartData.value(hash, 0);
|
||||||
}
|
avg_speed = (double)(h.total_payload_download()-data_origin) / (double)timeElapsed;
|
||||||
listEtas << (qlonglong)((h.actual_size()-h.total_wanted_done())/(double)h.download_payload_rate());
|
|
||||||
ETAstats[hash] = listEtas;
|
|
||||||
qlonglong moy = 0;
|
|
||||||
qlonglong val;
|
|
||||||
unsigned int nbETAs = listEtas.size();
|
|
||||||
Q_ASSERT(nbETAs);
|
|
||||||
foreach(val, listEtas) {
|
|
||||||
moy += (qlonglong)((double)val/(double)nbETAs);
|
|
||||||
}
|
|
||||||
if(moy < 0) {
|
|
||||||
if(ETAstats.contains(hash)) {
|
|
||||||
ETAstats.remove(hash);
|
|
||||||
}
|
|
||||||
if(ETAs.contains(hash)) {
|
|
||||||
ETAs.remove(hash);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ETAs[hash] = moy;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Speed is too low, we don't want an overflow.
|
return -1;
|
||||||
if(ETAstats.contains(hash)) {
|
|
||||||
ETAstats.remove(hash);
|
|
||||||
}
|
|
||||||
if(ETAs.contains(hash)) {
|
|
||||||
ETAs.remove(hash);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if(avg_speed) {
|
||||||
|
return (qlonglong) floor((double) (h.actual_size() - h.total_wanted_done()) / avg_speed);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
// Delete big ratios
|
|
||||||
if(max_ratio != -1)
|
|
||||||
deleteBigRatios();
|
|
||||||
}
|
|
||||||
|
|
||||||
long bittorrent::getETA(QString hash) const{
|
|
||||||
return ETAs.value(hash, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the torrent handle, given its hash
|
// Return the torrent handle, given its hash
|
||||||
@@ -240,9 +214,9 @@ void bittorrent::deleteTorrent(QString hash, bool permanent) {
|
|||||||
foreach(file, files) {
|
foreach(file, files) {
|
||||||
torrentBackup.remove(file);
|
torrentBackup.remove(file);
|
||||||
}
|
}
|
||||||
// Remove it from ETAs hash tables
|
// Remove it from TorrentsStartTime hash table
|
||||||
ETAstats.remove(hash);
|
TorrentsStartTime.remove(hash);
|
||||||
ETAs.remove(hash);
|
TorrentsStartData.remove(hash);
|
||||||
// Remove tracker errors
|
// Remove tracker errors
|
||||||
trackersErrors.remove(hash);
|
trackersErrors.remove(hash);
|
||||||
// Remove it from ratio table
|
// Remove it from ratio table
|
||||||
@@ -290,6 +264,9 @@ void bittorrent::setUnfinishedTorrent(QString hash) {
|
|||||||
}
|
}
|
||||||
if(!unfinishedTorrents.contains(hash)) {
|
if(!unfinishedTorrents.contains(hash)) {
|
||||||
unfinishedTorrents << hash;
|
unfinishedTorrents << hash;
|
||||||
|
QTorrentHandle h = getTorrentHandle(hash);
|
||||||
|
TorrentsStartData[hash] = h.total_payload_download();
|
||||||
|
TorrentsStartTime[hash] = QDateTime::currentDateTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,9 +284,9 @@ void bittorrent::setFinishedTorrent(QString hash) {
|
|||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
unfinishedTorrents.removeAt(index);
|
unfinishedTorrents.removeAt(index);
|
||||||
}
|
}
|
||||||
// Remove it from ETAs hash tables
|
// Remove it from TorrentsStartTime hash table
|
||||||
ETAstats.remove(hash);
|
TorrentsStartTime.remove(hash);
|
||||||
ETAs.remove(hash);
|
TorrentsStartData.remove(hash);
|
||||||
// Save fast resume data
|
// Save fast resume data
|
||||||
saveFastResumeAndRatioData(hash);
|
saveFastResumeAndRatioData(hash);
|
||||||
}
|
}
|
||||||
@@ -321,6 +298,8 @@ bool bittorrent::pauseTorrent(QString hash) {
|
|||||||
if(h.is_valid() && !h.is_paused()) {
|
if(h.is_valid() && !h.is_paused()) {
|
||||||
h.pause();
|
h.pause();
|
||||||
change = true;
|
change = true;
|
||||||
|
// Save fast resume data
|
||||||
|
saveFastResumeAndRatioData(hash);
|
||||||
qDebug("Torrent paused successfully");
|
qDebug("Torrent paused successfully");
|
||||||
}else{
|
}else{
|
||||||
if(!h.is_valid()) {
|
if(!h.is_valid()) {
|
||||||
@@ -335,9 +314,9 @@ bool bittorrent::pauseTorrent(QString hash) {
|
|||||||
paused_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
paused_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
paused_file.close();
|
paused_file.close();
|
||||||
}
|
}
|
||||||
// Remove it from ETAs hash tables
|
// Remove it from TorrentsStartTime hash table
|
||||||
ETAstats.remove(hash);
|
TorrentsStartTime.remove(hash);
|
||||||
ETAs.remove(hash);
|
TorrentsStartData.remove(hash);
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +325,9 @@ bool bittorrent::resumeTorrent(QString hash) {
|
|||||||
bool success = false;
|
bool success = false;
|
||||||
QTorrentHandle h = getTorrentHandle(hash);
|
QTorrentHandle h = getTorrentHandle(hash);
|
||||||
if(h.is_valid() && h.is_paused()) {
|
if(h.is_valid() && h.is_paused()) {
|
||||||
|
// Save Addition DateTime
|
||||||
|
TorrentsStartData[hash] = h.total_payload_download();
|
||||||
|
TorrentsStartTime[hash] = QDateTime::currentDateTime();
|
||||||
h.resume();
|
h.resume();
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@@ -537,6 +519,7 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bo
|
|||||||
// Display warning to tell user we can't decode the torrent file
|
// Display warning to tell user we can't decode the torrent file
|
||||||
if(!from_url.isNull()) {
|
if(!from_url.isNull()) {
|
||||||
emit invalidTorrent(from_url);
|
emit invalidTorrent(from_url);
|
||||||
|
QFile::remove(file);
|
||||||
}else{
|
}else{
|
||||||
emit invalidTorrent(file);
|
emit invalidTorrent(file);
|
||||||
}
|
}
|
||||||
@@ -551,6 +534,8 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bo
|
|||||||
// Display warning to tell user we can't decode the torrent file
|
// Display warning to tell user we can't decode the torrent file
|
||||||
if(!from_url.isNull()) {
|
if(!from_url.isNull()) {
|
||||||
emit invalidTorrent(from_url);
|
emit invalidTorrent(from_url);
|
||||||
|
qDebug("File path is: %s", file.toUtf8().data());
|
||||||
|
QFile::remove(file);
|
||||||
}else{
|
}else{
|
||||||
emit invalidTorrent(file);
|
emit invalidTorrent(file);
|
||||||
}
|
}
|
||||||
@@ -629,25 +614,49 @@ bool bittorrent::isDHTEnabled() const{
|
|||||||
|
|
||||||
void bittorrent::enableUPnP(bool b) {
|
void bittorrent::enableUPnP(bool b) {
|
||||||
if(b) {
|
if(b) {
|
||||||
s->start_upnp();
|
if(!UPnPEnabled) {
|
||||||
|
qDebug("Enabling UPnP");
|
||||||
|
s->start_upnp();
|
||||||
|
UPnPEnabled = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s->stop_upnp();
|
if(UPnPEnabled) {
|
||||||
|
qDebug("Disabling UPnP");
|
||||||
|
s->stop_upnp();
|
||||||
|
UPnPEnabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bittorrent::enableNATPMP(bool b) {
|
void bittorrent::enableNATPMP(bool b) {
|
||||||
if(b) {
|
if(b) {
|
||||||
s->start_natpmp();
|
if(!NATPMPEnabled) {
|
||||||
|
qDebug("Enabling NAT-PMP");
|
||||||
|
s->start_natpmp();
|
||||||
|
NATPMPEnabled = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s->stop_natpmp();
|
if(NATPMPEnabled) {
|
||||||
|
qDebug("Disabling NAT-PMP");
|
||||||
|
s->stop_natpmp();
|
||||||
|
NATPMPEnabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bittorrent::enableLSD(bool b) {
|
void bittorrent::enableLSD(bool b) {
|
||||||
if(b) {
|
if(b) {
|
||||||
s->start_lsd();
|
if(!LSDEnabled) {
|
||||||
|
qDebug("Enabling LSD");
|
||||||
|
s->start_lsd();
|
||||||
|
LSDEnabled = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s->stop_lsd();
|
if(LSDEnabled) {
|
||||||
|
qDebug("Disabling LSD");
|
||||||
|
s->stop_lsd();
|
||||||
|
LSDEnabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,7 +756,7 @@ void bittorrent::loadFilesPriorities(QTorrentHandle &h) {
|
|||||||
if( priority < 0 || priority > 7) {
|
if( priority < 0 || priority > 7) {
|
||||||
priority = 1;
|
priority = 1;
|
||||||
}
|
}
|
||||||
//qDebug("Setting piece piority to %d", priority);
|
qDebug("Setting piece piority to %d", priority);
|
||||||
v.push_back(priority);
|
v.push_back(priority);
|
||||||
}
|
}
|
||||||
h.prioritize_files(v);
|
h.prioritize_files(v);
|
||||||
@@ -833,32 +842,23 @@ void bittorrent::saveDownloadUploadForTorrent(QString hash) {
|
|||||||
ratio_file.close();
|
ratio_file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only save fast resume data for unfinished torrents (Optimization)
|
// Only save fast resume data for unfinished and unpaused torrents (Optimization)
|
||||||
void bittorrent::saveFastResumeAndRatioDataUnfinished() {
|
// Called periodically and on exit
|
||||||
|
void bittorrent::saveFastResumeAndRatioData() {
|
||||||
QString hash;
|
QString hash;
|
||||||
QStringList hashes = getUnfinishedTorrents();
|
QStringList hashes = getUnfinishedTorrents();
|
||||||
foreach(hash, hashes) {
|
foreach(hash, hashes) {
|
||||||
saveFastResumeAndRatioData(hash);
|
QTorrentHandle h = getTorrentHandle(hash);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save fastresume data for all torrents (called periodically)
|
|
||||||
void bittorrent::saveFastResumeAndRatioData() {
|
|
||||||
qDebug("Saving fast resume and ratio data");
|
|
||||||
std::vector<torrent_handle> handles = s->get_torrents();
|
|
||||||
// It is not necessary to pause the torrents before saving fastresume data anymore
|
|
||||||
// because we either use Full allocation or sparse mode.
|
|
||||||
// Write fast resume data
|
|
||||||
for(unsigned int i=0; i<handles.size(); ++i) {
|
|
||||||
QTorrentHandle h = handles[i];
|
|
||||||
if(!h.is_valid()) {
|
if(!h.is_valid()) {
|
||||||
qDebug("/!\\ Error: Invalid handle");
|
qDebug("/!\\ Error: Invalid handle");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QString hash = h.hash();
|
if(h.is_paused()) {
|
||||||
|
// Do not need to save fast resume data for paused torrents
|
||||||
|
continue;
|
||||||
|
}
|
||||||
saveFastResumeAndRatioData(hash);
|
saveFastResumeAndRatioData(hash);
|
||||||
}
|
}
|
||||||
qDebug("Fast resume and ratio data saved");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bittorrent::saveFastResumeAndRatioData(QString hash) {
|
void bittorrent::saveFastResumeAndRatioData(QString hash) {
|
||||||
@@ -1001,9 +1001,22 @@ void bittorrent::setGlobalRatio(float ratio) {
|
|||||||
// be automatically deleted
|
// be automatically deleted
|
||||||
void bittorrent::setDeleteRatio(float ratio) {
|
void bittorrent::setDeleteRatio(float ratio) {
|
||||||
if(ratio != -1 && ratio < 1.) ratio = 1.;
|
if(ratio != -1 && ratio < 1.) ratio = 1.;
|
||||||
max_ratio = ratio;
|
if(max_ratio == -1 && ratio != -1) {
|
||||||
qDebug("* Set deleteRatio to %.1f", max_ratio);
|
Q_ASSERT(!BigRatioTimer);
|
||||||
deleteBigRatios();
|
BigRatioTimer = new QTimer(this);
|
||||||
|
connect(BigRatioTimer, SIGNAL(timeout()), this, SLOT(deleteBigRatios()));
|
||||||
|
BigRatioTimer->start(5000);
|
||||||
|
} else {
|
||||||
|
if(max_ratio != -1 && ratio == -1) {
|
||||||
|
delete BigRatioTimer;
|
||||||
|
BigRatioTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(max_ratio != ratio) {
|
||||||
|
max_ratio = ratio;
|
||||||
|
qDebug("* Set deleteRatio to %.1f", max_ratio);
|
||||||
|
deleteBigRatios();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bittorrent::loadTrackerFile(QString hash) {
|
bool bittorrent::loadTrackerFile(QString hash) {
|
||||||
@@ -1158,6 +1171,10 @@ void bittorrent::readAlerts() {
|
|||||||
// Pause torrent
|
// Pause torrent
|
||||||
pauseTorrent(hash);
|
pauseTorrent(hash);
|
||||||
qDebug("%s was paused after checking", hash.toUtf8().data());
|
qDebug("%s was paused after checking", hash.toUtf8().data());
|
||||||
|
} else {
|
||||||
|
// Save Addition DateTime
|
||||||
|
TorrentsStartTime[hash] = QDateTime::currentDateTime();
|
||||||
|
TorrentsStartData[hash] = h.total_payload_download();
|
||||||
}
|
}
|
||||||
emit torrentFinishedChecking(hash);
|
emit torrentFinishedChecking(hash);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
#include <libtorrent/session.hpp>
|
#include <libtorrent/session.hpp>
|
||||||
#include <libtorrent/ip_filter.hpp>
|
#include <libtorrent/ip_filter.hpp>
|
||||||
@@ -45,14 +46,14 @@ class bittorrent : public QObject{
|
|||||||
QTimer *timerScan;
|
QTimer *timerScan;
|
||||||
QTimer *timerAlerts;
|
QTimer *timerAlerts;
|
||||||
QTimer *fastResumeSaver;
|
QTimer *fastResumeSaver;
|
||||||
|
QTimer *BigRatioTimer;
|
||||||
bool DHTEnabled;
|
bool DHTEnabled;
|
||||||
downloadThread *downloader;
|
downloadThread *downloader;
|
||||||
QString defaultSavePath;
|
QString defaultSavePath;
|
||||||
QStringList torrentsToPauseAfterChecking;
|
QStringList torrentsToPauseAfterChecking;
|
||||||
QHash<QString, QList<qlonglong> > ETAstats;
|
QHash<QString, QDateTime> TorrentsStartTime;
|
||||||
QHash<QString, qlonglong> ETAs;
|
QHash<QString, size_type> TorrentsStartData;
|
||||||
QHash<QString, QPair<size_type,size_type> > ratioData;
|
QHash<QString, QPair<size_type,size_type> > ratioData;
|
||||||
QTimer *ETARefresher;
|
|
||||||
QHash<QString, QList<QPair<QString, QString> > > trackersErrors;
|
QHash<QString, QList<QPair<QString, QString> > > trackersErrors;
|
||||||
deleteThread *deleter;
|
deleteThread *deleter;
|
||||||
QStringList finishedTorrents;
|
QStringList finishedTorrents;
|
||||||
@@ -62,6 +63,9 @@ class bittorrent : public QObject{
|
|||||||
int maxConnecsPerTorrent;
|
int maxConnecsPerTorrent;
|
||||||
int maxUploadsPerTorrent;
|
int maxUploadsPerTorrent;
|
||||||
float max_ratio;
|
float max_ratio;
|
||||||
|
bool UPnPEnabled;
|
||||||
|
bool NATPMPEnabled;
|
||||||
|
bool LSDEnabled;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString getSavePath(QString hash);
|
QString getSavePath(QString hash);
|
||||||
@@ -79,7 +83,7 @@ class bittorrent : public QObject{
|
|||||||
session_status getSessionStatus() const;
|
session_status getSessionStatus() const;
|
||||||
int getListenPort() const;
|
int getListenPort() const;
|
||||||
QStringList getTorrentsToPauseAfterChecking() const;
|
QStringList getTorrentsToPauseAfterChecking() const;
|
||||||
long getETA(QString hash) const;
|
qlonglong getETA(QString hash) const;
|
||||||
float getRealRatio(QString hash) const;
|
float getRealRatio(QString hash) const;
|
||||||
session* getSession() const;
|
session* getSession() const;
|
||||||
QList<QPair<QString, QString> > getTrackersErrors(QString hash) const;
|
QList<QPair<QString, QString> > getTrackersErrors(QString hash) const;
|
||||||
@@ -99,14 +103,12 @@ class bittorrent : public QObject{
|
|||||||
void preAllocateAllFiles(bool b);
|
void preAllocateAllFiles(bool b);
|
||||||
void saveFastResumeAndRatioData();
|
void saveFastResumeAndRatioData();
|
||||||
void saveFastResumeAndRatioData(QString hash);
|
void saveFastResumeAndRatioData(QString hash);
|
||||||
void saveFastResumeAndRatioDataUnfinished();
|
|
||||||
void enableDirectoryScanning(QString scan_dir);
|
void enableDirectoryScanning(QString scan_dir);
|
||||||
void disableDirectoryScanning();
|
void disableDirectoryScanning();
|
||||||
void enablePeerExchange();
|
void enablePeerExchange();
|
||||||
void enableIPFilter(ip_filter filter);
|
void enableIPFilter(ip_filter filter);
|
||||||
void disableIPFilter();
|
void disableIPFilter();
|
||||||
void resumeUnfinishedTorrents();
|
void resumeUnfinishedTorrents();
|
||||||
void updateETAs();
|
|
||||||
void saveTorrentSpeedLimits(QString hash);
|
void saveTorrentSpeedLimits(QString hash);
|
||||||
void loadTorrentSpeedLimits(QString hash);
|
void loadTorrentSpeedLimits(QString hash);
|
||||||
void saveDownloadUploadForTorrent(QString hash);
|
void saveDownloadUploadForTorrent(QString hash);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <libtorrent/file_pool.hpp>
|
#include <libtorrent/file_pool.hpp>
|
||||||
|
|
||||||
#include "createtorrent_imp.h"
|
#include "createtorrent_imp.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
using namespace boost::filesystem;
|
using namespace boost::filesystem;
|
||||||
@@ -120,11 +121,13 @@ void createtorrent::on_addURLSeed_button_clicked(){
|
|||||||
// Subfunction to add files to a torrent_info structure
|
// Subfunction to add files to a torrent_info structure
|
||||||
// Written by Arvid Norberg (libtorrent Author)
|
// Written by Arvid Norberg (libtorrent Author)
|
||||||
void add_files(torrent_info& t, path const& p, path const& l){
|
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);
|
path f(p / l);
|
||||||
if (is_directory(f)){
|
if (is_directory(f)){
|
||||||
for (directory_iterator i(f), end; i != end; ++i)
|
for (directory_iterator i(f), end; i != end; ++i)
|
||||||
add_files(t, p, l / i->leaf());
|
add_files(t, p, l / i->leaf());
|
||||||
}else{
|
}else{
|
||||||
|
qDebug("Adding %s", l.string().c_str());
|
||||||
t.add_file(l, file_size(f));
|
t.add_file(l, file_size(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,6 +144,8 @@ QStringList createtorrent::allItems(QListWidget *list){
|
|||||||
// Main function that create a .torrent file
|
// Main function that create a .torrent file
|
||||||
void createtorrent::on_createButton_clicked(){
|
void createtorrent::on_createButton_clicked(){
|
||||||
QString input = textInputPath->text().trimmed();
|
QString input = textInputPath->text().trimmed();
|
||||||
|
if (input.endsWith(QDir::separator()))
|
||||||
|
input.chop(1);
|
||||||
if(input.isEmpty()){
|
if(input.isEmpty()){
|
||||||
QMessageBox::critical(0, tr("No input path set"), tr("Please type an input path first"));
|
QMessageBox::critical(0, tr("No input path set"), tr("Please type an input path first"));
|
||||||
return;
|
return;
|
||||||
@@ -161,9 +166,8 @@ void createtorrent::on_createButton_clicked(){
|
|||||||
try {
|
try {
|
||||||
boost::intrusive_ptr<torrent_info> t(new torrent_info);
|
boost::intrusive_ptr<torrent_info> t(new torrent_info);
|
||||||
ofstream out(complete(path((const char*)destination.toUtf8())), std::ios_base::binary);
|
ofstream out(complete(path((const char*)destination.toUtf8())), std::ios_base::binary);
|
||||||
path full_path;
|
|
||||||
// Adding files to the torrent
|
// Adding files to the torrent
|
||||||
full_path = complete(path(input.toUtf8().data()));
|
path full_path = complete(path(input.toUtf8().data()));
|
||||||
add_files(*t, full_path.branch_path(), full_path.leaf());
|
add_files(*t, full_path.branch_path(), full_path.leaf());
|
||||||
// Set piece size
|
// Set piece size
|
||||||
int piece_size = getPieceSize();
|
int piece_size = getPieceSize();
|
||||||
@@ -200,8 +204,14 @@ void createtorrent::on_createButton_clicked(){
|
|||||||
entry e = t->create_torrent();
|
entry e = t->create_torrent();
|
||||||
libtorrent::bencode(std::ostream_iterator<char>(out), e);
|
libtorrent::bencode(std::ostream_iterator<char>(out), e);
|
||||||
out.flush();
|
out.flush();
|
||||||
if(checkStartSeeding->isChecked())
|
if(checkStartSeeding->isChecked()) {
|
||||||
|
// Create save path file
|
||||||
|
QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+misc::toQString(t->info_hash())+QString::fromUtf8(".savepath"));
|
||||||
|
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
|
savepath_file.write(full_path.branch_path().string().c_str());
|
||||||
|
savepath_file.close();
|
||||||
emit torrent_to_seed(destination);
|
emit torrent_to_seed(destination);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& e){
|
catch (std::exception& e){
|
||||||
std::cerr << e.what() << "\n";
|
std::cerr << e.what() << "\n";
|
||||||
|
|||||||
@@ -21,56 +21,48 @@
|
|||||||
|
|
||||||
#include "downloadThread.h"
|
#include "downloadThread.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cc++/common.h>
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
QString subDownloadThread::errorCodeToString(int status) {
|
// http://curl.rtin.bz/libcurl/c/libcurl-errors.html
|
||||||
|
QString subDownloadThread::errorCodeToString(CURLcode status) {
|
||||||
switch(status){
|
switch(status){
|
||||||
case 1://ost::URLStream::errUnreachable:
|
case CURLE_FTP_CANT_GET_HOST:
|
||||||
|
case CURLE_COULDNT_RESOLVE_HOST:
|
||||||
return tr("Host is unreachable");
|
return tr("Host is unreachable");
|
||||||
case 2://ost::URLStream::errMissing:
|
case CURLE_READ_ERROR:
|
||||||
|
case CURLE_FILE_COULDNT_READ_FILE:
|
||||||
return tr("File was not found (404)");
|
return tr("File was not found (404)");
|
||||||
case 3://ost::URLStream::errDenied:
|
case CURLE_FTP_ACCESS_DENIED:
|
||||||
|
case CURLE_LOGIN_DENIED:
|
||||||
|
case CURLE_FTP_USER_PASSWORD_INCORRECT:
|
||||||
return tr("Connection was denied");
|
return tr("Connection was denied");
|
||||||
case 4://ost::URLStream::errInvalid:
|
case CURLE_URL_MALFORMAT:
|
||||||
return tr("Url is invalid");
|
return tr("Url is invalid");
|
||||||
case 5://ost::URLStream::errForbidden:
|
case CURLE_COULDNT_RESOLVE_PROXY:
|
||||||
return tr("Connection forbidden (403)");
|
return tr("Could not resolve proxy");
|
||||||
case 6://ost::URLStream::errUnauthorized:
|
//case 5:
|
||||||
return tr("Connection was not authorized (401)");
|
// return tr("Connection forbidden (403)");
|
||||||
case 7://ost::URLStream::errRelocated:
|
//case 6:
|
||||||
return tr("Content has moved (301)");
|
// return tr("Connection was not authorized (401)");
|
||||||
case 8://ost::URLStream::errFailure:
|
//case 7:
|
||||||
|
// return tr("Content has moved (301)");
|
||||||
|
case CURLE_COULDNT_CONNECT:
|
||||||
return tr("Connection failure");
|
return tr("Connection failure");
|
||||||
case 9://ost::URLStream::errTimeout:
|
case CURLE_OPERATION_TIMEOUTED:
|
||||||
return tr("Connection was timed out");
|
return tr("Connection was timed out");
|
||||||
case 10://ost::URLStream::errInterface:
|
case CURLE_INTERFACE_FAILED:
|
||||||
return tr("Incorrect network interface");
|
return tr("Incorrect network interface");
|
||||||
default:
|
default:
|
||||||
return tr("Unknown error");
|
return tr("Unknown error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subDownloadThread::subDownloadThread(QObject *parent, QString url) : QThread(parent), url(url), abort(false){
|
subDownloadThread::subDownloadThread(QObject *parent, QString url) : QThread(parent), url(url), abort(false){}
|
||||||
url_stream = new ost::URLStream();
|
|
||||||
// Proxy support
|
|
||||||
QSettings settings("qBittorrent", "qBittorrent");
|
|
||||||
int intValue = settings.value(QString::fromUtf8("Preferences/Connection/ProxyType"), 0).toInt();
|
|
||||||
if(intValue > 0) {
|
|
||||||
// Proxy enabled
|
|
||||||
url_stream->setProxy(settings.value(QString::fromUtf8("Preferences/Connection/Proxy/IP"), "0.0.0.0").toString().toUtf8().data(), settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Port"), 8080).toInt());
|
|
||||||
if(settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Authentication"), false).toBool()) {
|
|
||||||
// Authentication required
|
|
||||||
url_stream->setProxyUser(settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Username"), QString()).toString().toUtf8().data());
|
|
||||||
url_stream->setProxyPassword(settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Password"), QString()).toString().toUtf8().data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subDownloadThread::~subDownloadThread(){
|
subDownloadThread::~subDownloadThread(){
|
||||||
abort = true;
|
abort = true;
|
||||||
wait();
|
wait();
|
||||||
delete url_stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subDownloadThread::run(){
|
void subDownloadThread::run(){
|
||||||
@@ -81,38 +73,66 @@ void subDownloadThread::run(){
|
|||||||
filePath = tmpfile->fileName();
|
filePath = tmpfile->fileName();
|
||||||
}
|
}
|
||||||
delete tmpfile;
|
delete tmpfile;
|
||||||
QFile dest_file(filePath);
|
FILE *f = fopen(filePath.toUtf8().data(), "wb");
|
||||||
if(!dest_file.open(QIODevice::WriteOnly | QIODevice::Text)){
|
if(!f) {
|
||||||
std::cerr << "Error: could't create temporary file: " << (const char*)filePath.toUtf8() << '\n';
|
std::cerr << "couldn't open destination file" << "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ost::URLStream::Error status = url_stream->get((const char*)url.toUtf8());
|
CURL *curl;
|
||||||
if(status){
|
CURLcode res;
|
||||||
// Failure
|
curl = curl_easy_init();
|
||||||
QString error_msg = errorCodeToString((int)status);
|
if(curl) {
|
||||||
qDebug("Download failed for %s, reason: %s", (const char*)url.toUtf8(), (const char*)error_msg.toUtf8());
|
std::string c_url = url.toUtf8().data();
|
||||||
url_stream->close();
|
curl_easy_setopt(curl, CURLOPT_URL, c_url.c_str());
|
||||||
emit downloadFailureST(this, url, error_msg);
|
// SSL support
|
||||||
return;
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||||
}
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
qDebug("Downloading %s...", (const char*)url.toUtf8());
|
// PROXY SUPPORT
|
||||||
char cbuf[1024];
|
QSettings settings("qBittorrent", "qBittorrent");
|
||||||
int len;
|
int intValue = settings.value(QString::fromUtf8("Preferences/Connection/ProxyType"), 0).toInt();
|
||||||
while(!url_stream->eof()) {
|
if(intValue > 0) {
|
||||||
url_stream->read(cbuf, sizeof(cbuf));
|
// Proxy enabled
|
||||||
len = url_stream->gcount();
|
QString IP = settings.value(QString::fromUtf8("Preferences/Connection/Proxy/IP"), "0.0.0.0").toString();
|
||||||
if(len > 0)
|
QString port = settings.value(QString::fromUtf8("Preferences/Connection/Proxy/Port"), 8080).toString();
|
||||||
dest_file.write(cbuf, len);
|
qDebug("Using proxy: %s", (IP+QString(":")+port).toUtf8().data());
|
||||||
if(abort){
|
curl_easy_setopt(curl, CURLOPT_PROXYPORT, (IP+QString(":")+port).toUtf8().data());
|
||||||
dest_file.close();
|
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||||
url_stream->close();
|
if(intValue%2==0) {
|
||||||
return;
|
qDebug("Proxy is SOCKS5, not HTTP");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
|
||||||
|
}
|
||||||
|
// Authentication?
|
||||||
|
if(intValue > 2) {
|
||||||
|
qDebug("Proxy requires authentication, authenticating");
|
||||||
|
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
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
|
||||||
|
// Verbose
|
||||||
|
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
// No progress info (we don't use it)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
|
||||||
|
// Redirections
|
||||||
|
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.toUtf8().data());
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
fclose(f);
|
||||||
|
if(res) {
|
||||||
|
emit downloadFailureST(this, url, errorCodeToString(res));
|
||||||
|
} else {
|
||||||
|
emit downloadFinishedST(this, url, filePath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Could not initialize CURL" << "\n";
|
||||||
}
|
}
|
||||||
dest_file.close();
|
|
||||||
url_stream->close();
|
|
||||||
emit downloadFinishedST(this, url, filePath);
|
|
||||||
qDebug("download completed here: %s", (const char*)filePath.toUtf8());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Download Thread **/
|
/** Download Thread **/
|
||||||
|
|||||||
@@ -29,29 +29,18 @@
|
|||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <curl/curl.h>
|
||||||
namespace ost {
|
|
||||||
class URLStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
QString IP;
|
|
||||||
int port;
|
|
||||||
QString username;
|
|
||||||
QString password;
|
|
||||||
} tmp_proxy;
|
|
||||||
|
|
||||||
class subDownloadThread : public QThread {
|
class subDownloadThread : public QThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QString url;
|
QString url;
|
||||||
ost::URLStream *url_stream;
|
|
||||||
bool abort;
|
bool abort;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
subDownloadThread(QObject *parent, QString url);
|
subDownloadThread(QObject *parent, QString url);
|
||||||
~subDownloadThread();
|
~subDownloadThread();
|
||||||
QString errorCodeToString(int status);
|
QString errorCodeToString(CURLcode status);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// For subthreads
|
// For subthreads
|
||||||
@@ -90,7 +79,6 @@ class downloadThread : public QThread {
|
|||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void propagateDownloadedFile(subDownloadThread* st, QString url, QString path);
|
void propagateDownloadedFile(subDownloadThread* st, QString url, QString path);
|
||||||
|
|
||||||
void propagateDownloadFailure(subDownloadThread* st, QString url, QString reason);
|
void propagateDownloadFailure(subDownloadThread* st, QString url, QString reason);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,6 @@ void DownloadingTorrents::setInfoBar(QString info, QColor color) {
|
|||||||
infoBar->clear();
|
infoBar->clear();
|
||||||
nbLines = 1;
|
nbLines = 1;
|
||||||
}
|
}
|
||||||
qDebug("Color is %s", color.name().toUtf8().data());
|
|
||||||
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>"));
|
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>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +414,7 @@ void DownloadingTorrents::updateDlList() {
|
|||||||
}else{
|
}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/stalled.png"))), Qt::DecorationRole);
|
||||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||||
setRowColor(row, QPalette::WindowText);
|
setRowColor(row, QApplication::palette().color(QPalette::WindowText));
|
||||||
}
|
}
|
||||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
|
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class DownloadingTorrents : public QWidget, public Ui::downloading{
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateDlList();
|
void updateDlList();
|
||||||
void setInfoBar(QString info, QColor color=QPalette::WindowText);
|
void setInfoBar(QString info, QColor color=QApplication::palette().color(QPalette::WindowText));
|
||||||
void pauseTorrent(QString hash);
|
void pauseTorrent(QString hash);
|
||||||
void resumeTorrent(QString hash);
|
void resumeTorrent(QString hash);
|
||||||
void updateRatio();
|
void updateRatio();
|
||||||
|
|||||||
@@ -250,11 +250,13 @@ void engineSelectDlg::setRowColor(int row, QString color){
|
|||||||
bool engineSelectDlg::checkInstalled(QString plugin_name) const {
|
bool engineSelectDlg::checkInstalled(QString plugin_name) const {
|
||||||
QProcess nova;
|
QProcess nova;
|
||||||
QStringList params;
|
QStringList params;
|
||||||
|
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
|
||||||
params << "--supported_engines";
|
params << "--supported_engines";
|
||||||
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
nova.start("python", params, QIODevice::ReadOnly);
|
||||||
nova.waitForStarted();
|
nova.waitForStarted();
|
||||||
nova.waitForFinished();
|
nova.waitForFinished();
|
||||||
QByteArray result = nova.readAll();
|
QByteArray result = nova.readAll();
|
||||||
|
result = result.replace("\r", "");
|
||||||
result = result.replace("\n", "");
|
result = result.replace("\n", "");
|
||||||
QList<QByteArray> plugins_list = result.split(',');
|
QList<QByteArray> plugins_list = result.split(',');
|
||||||
return plugins_list.contains(plugin_name.toUtf8());
|
return plugins_list.contains(plugin_name.toUtf8());
|
||||||
@@ -280,11 +282,13 @@ void engineSelectDlg::loadSupportedSearchEngines(bool first) {
|
|||||||
QStringList params;
|
QStringList params;
|
||||||
// Ask nova core for the supported search engines
|
// Ask nova core for the supported search engines
|
||||||
QProcess nova;
|
QProcess nova;
|
||||||
|
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
|
||||||
params << "--supported_engines";
|
params << "--supported_engines";
|
||||||
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
nova.start("python", params, QIODevice::ReadOnly);
|
||||||
nova.waitForStarted();
|
nova.waitForStarted();
|
||||||
nova.waitForFinished();
|
nova.waitForFinished();
|
||||||
QByteArray result = nova.readAll();
|
QByteArray result = nova.readAll();
|
||||||
|
result = result.replace("\r", "");
|
||||||
result = result.replace("\n", "");
|
result = result.replace("\n", "");
|
||||||
qDebug("read: %s", result.data());
|
qDebug("read: %s", result.data());
|
||||||
QByteArray e;
|
QByteArray e;
|
||||||
@@ -295,11 +299,13 @@ void engineSelectDlg::loadSupportedSearchEngines(bool first) {
|
|||||||
installed_engines[en] = old_engines.value(en, true);
|
installed_engines[en] = old_engines.value(en, true);
|
||||||
}
|
}
|
||||||
params.clear();
|
params.clear();
|
||||||
|
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
|
||||||
params << "--supported_engines_infos";
|
params << "--supported_engines_infos";
|
||||||
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
nova.start("python", params, QIODevice::ReadOnly);
|
||||||
nova.waitForStarted();
|
nova.waitForStarted();
|
||||||
nova.waitForFinished();
|
nova.waitForFinished();
|
||||||
result = nova.readAll();
|
result = nova.readAll();
|
||||||
|
result = result.replace("\r", "");
|
||||||
result = result.replace("\n", "");
|
result = result.replace("\n", "");
|
||||||
qDebug("read: %s", result.data());
|
qDebug("read: %s", result.data());
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ class misc : public QObject{
|
|||||||
|
|
||||||
// Take a number of seconds and return an user-friendly
|
// Take a number of seconds and return an user-friendly
|
||||||
// time duration like "1d 2h 10m".
|
// time duration like "1d 2h 10m".
|
||||||
static QString userFriendlyDuration(const long int seconds) {
|
static QString userFriendlyDuration(qlonglong seconds) {
|
||||||
if(seconds < 0) {
|
if(seconds < 0) {
|
||||||
return tr("Unknown");
|
return tr("Unknown");
|
||||||
}
|
}
|
||||||
|
|||||||
134
src/options.ui
134
src/options.ui
@@ -794,10 +794,10 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>0.0.0.0</string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="maxLength" >
|
<property name="maxLength" >
|
||||||
<number>15</number>
|
<number>75</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="echoMode" >
|
<property name="echoMode" >
|
||||||
<enum>QLineEdit::Normal</enum>
|
<enum>QLineEdit::Normal</enum>
|
||||||
@@ -947,70 +947,72 @@
|
|||||||
<property name="title" >
|
<property name="title" >
|
||||||
<string>Affected connections</string>
|
<string>Affected connections</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QCheckBox" name="checkProxyTrackers" >
|
<layout class="QVBoxLayout" >
|
||||||
<property name="geometry" >
|
<item>
|
||||||
<rect>
|
<widget class="QCheckBox" name="checkProxyTrackers" >
|
||||||
<x>10</x>
|
<property name="sizePolicy" >
|
||||||
<y>20</y>
|
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||||
<width>341</width>
|
<horstretch>0</horstretch>
|
||||||
<height>22</height>
|
<verstretch>0</verstretch>
|
||||||
</rect>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Use proxy for connections to trackers</string>
|
<string>Use proxy for connections to trackers</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked" >
|
<property name="checked" >
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QCheckBox" name="checkProxyPeers" >
|
</item>
|
||||||
<property name="geometry" >
|
<item>
|
||||||
<rect>
|
<widget class="QCheckBox" name="checkProxyPeers" >
|
||||||
<x>10</x>
|
<property name="sizePolicy" >
|
||||||
<y>40</y>
|
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||||
<width>341</width>
|
<horstretch>0</horstretch>
|
||||||
<height>22</height>
|
<verstretch>0</verstretch>
|
||||||
</rect>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Use proxy for connections to regular peers</string>
|
<string>Use proxy for connections to regular peers</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked" >
|
<property name="checked" >
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QCheckBox" name="checkProxyWebseeds" >
|
</item>
|
||||||
<property name="geometry" >
|
<item>
|
||||||
<rect>
|
<widget class="QCheckBox" name="checkProxyDHT" >
|
||||||
<x>10</x>
|
<property name="sizePolicy" >
|
||||||
<y>60</y>
|
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||||
<width>341</width>
|
<horstretch>0</horstretch>
|
||||||
<height>22</height>
|
<verstretch>0</verstretch>
|
||||||
</rect>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Use proxy for connections to web seeds</string>
|
<string>Use proxy for DHT messages</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked" >
|
<property name="checked" >
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QCheckBox" name="checkProxyDHT" >
|
</item>
|
||||||
<property name="geometry" >
|
<item>
|
||||||
<rect>
|
<widget class="QCheckBox" name="checkProxyWebseeds" >
|
||||||
<x>10</x>
|
<property name="sizePolicy" >
|
||||||
<y>80</y>
|
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||||
<width>341</width>
|
<horstretch>0</horstretch>
|
||||||
<height>22</height>
|
<verstretch>0</verstretch>
|
||||||
</rect>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Use proxy for DHT messages</string>
|
<string>Use proxy for connections to web seeds</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked" >
|
<property name="checked" >
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -871,6 +871,7 @@ void options_imp::enableProxy(int index){
|
|||||||
textProxyIP->setEnabled(false);
|
textProxyIP->setEnabled(false);
|
||||||
lblProxyPort->setEnabled(false);
|
lblProxyPort->setEnabled(false);
|
||||||
spinProxyPort->setEnabled(false);
|
spinProxyPort->setEnabled(false);
|
||||||
|
checkProxyAuth->setChecked(false);
|
||||||
checkProxyAuth->setEnabled(false);
|
checkProxyAuth->setEnabled(false);
|
||||||
ProxyConnecsBox->setEnabled(false);
|
ProxyConnecsBox->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class QGnomeLookStyle : public QCleanlooksStyle {
|
|||||||
vertical = (pb2->orientation == Qt::Vertical);
|
vertical = (pb2->orientation == Qt::Vertical);
|
||||||
}
|
}
|
||||||
if (!vertical) {
|
if (!vertical) {
|
||||||
QPalette::ColorRole textRole = QPalette::Dark;/*
|
QPalette::ColorRole textRole = QPalette::WindowText;/*
|
||||||
if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible
|
if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible
|
||||||
&& ((qint64(pb->progress) - qint64(pb->minimum)) * 2 >= (qint64(pb->maximum) - qint64(pb->minimum)))) {
|
&& ((qint64(pb->progress) - qint64(pb->minimum)) * 2 >= (qint64(pb->maximum) - qint64(pb->minimum)))) {
|
||||||
textRole = QPalette::HighlightedText;
|
textRole = QPalette::HighlightedText;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "SearchListDelegate.h"
|
#include "SearchListDelegate.h"
|
||||||
#include "searchEngine.h"
|
#include "searchEngine.h"
|
||||||
@@ -79,6 +80,9 @@ SearchEngine::SearchEngine(bittorrent *BTSession, QSystemTrayIcon *myTrayIcon, b
|
|||||||
connect(searchProcess, SIGNAL(started()), this, SLOT(searchStarted()));
|
connect(searchProcess, SIGNAL(started()), this, SLOT(searchStarted()));
|
||||||
connect(searchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readSearchOutput()));
|
connect(searchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readSearchOutput()));
|
||||||
connect(searchProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(searchFinished(int,QProcess::ExitStatus)));
|
connect(searchProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(searchFinished(int,QProcess::ExitStatus)));
|
||||||
|
searchTimeout = new QTimer(this);
|
||||||
|
searchTimeout->setSingleShot(true);
|
||||||
|
connect(searchTimeout, SIGNAL(timeout()), this, SLOT(on_stop_search_button_clicked()));
|
||||||
// Check last enabled search engines
|
// Check last enabled search engines
|
||||||
loadEngineSettings();
|
loadEngineSettings();
|
||||||
// Update nova.py search plugin if necessary
|
// Update nova.py search plugin if necessary
|
||||||
@@ -92,6 +96,7 @@ SearchEngine::~SearchEngine(){
|
|||||||
saveColWidthSearchList();
|
saveColWidthSearchList();
|
||||||
searchProcess->kill();
|
searchProcess->kill();
|
||||||
searchProcess->waitForFinished();
|
searchProcess->waitForFinished();
|
||||||
|
delete searchTimeout;
|
||||||
delete searchProcess;
|
delete searchProcess;
|
||||||
delete searchCompleter;
|
delete searchCompleter;
|
||||||
delete SearchListModel;
|
delete SearchListModel;
|
||||||
@@ -245,6 +250,9 @@ void SearchEngine::on_search_button_clicked(){
|
|||||||
searchProcess->kill();
|
searchProcess->kill();
|
||||||
searchProcess->waitForFinished();
|
searchProcess->waitForFinished();
|
||||||
}
|
}
|
||||||
|
if(searchTimeout->isActive()) {
|
||||||
|
searchTimeout->stop();
|
||||||
|
}
|
||||||
QString pattern = search_pattern->text().trimmed();
|
QString pattern = search_pattern->text().trimmed();
|
||||||
// No search pattern entered
|
// No search pattern entered
|
||||||
if(pattern.isEmpty()){
|
if(pattern.isEmpty()){
|
||||||
@@ -269,7 +277,7 @@ void SearchEngine::on_search_button_clicked(){
|
|||||||
QStringList params;
|
QStringList params;
|
||||||
QStringList engineNames;
|
QStringList engineNames;
|
||||||
search_stopped = false;
|
search_stopped = false;
|
||||||
|
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
|
||||||
params << enabled_engines.join(",");
|
params << enabled_engines.join(",");
|
||||||
params << pattern.split(" ");
|
params << pattern.split(" ");
|
||||||
// Update SearchEngine widgets
|
// Update SearchEngine widgets
|
||||||
@@ -278,7 +286,8 @@ void SearchEngine::on_search_button_clicked(){
|
|||||||
search_result_line_truncated.clear();
|
search_result_line_truncated.clear();
|
||||||
results_lbl->setText(tr("Results")+" <i>(0)</i>:");
|
results_lbl->setText(tr("Results")+" <i>(0)</i>:");
|
||||||
// Launch search
|
// Launch search
|
||||||
searchProcess->start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
searchProcess->start("python", params, QIODevice::ReadOnly);
|
||||||
|
searchTimeout->start(180000); // 3min
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngine::searchStarted(){
|
void SearchEngine::searchStarted(){
|
||||||
@@ -309,6 +318,7 @@ void SearchEngine::downloadSelectedItem(const QModelIndex& index){
|
|||||||
// line to search results calling appendSearchResult().
|
// line to search results calling appendSearchResult().
|
||||||
void SearchEngine::readSearchOutput(){
|
void SearchEngine::readSearchOutput(){
|
||||||
QByteArray output = searchProcess->readAllStandardOutput();
|
QByteArray output = searchProcess->readAllStandardOutput();
|
||||||
|
output.replace("\r", "");
|
||||||
QList<QByteArray> lines_list = output.split('\n');
|
QList<QByteArray> lines_list = output.split('\n');
|
||||||
QByteArray line;
|
QByteArray line;
|
||||||
if(!search_result_line_truncated.isEmpty()){
|
if(!search_result_line_truncated.isEmpty()){
|
||||||
@@ -361,7 +371,7 @@ void SearchEngine::updateNova() {
|
|||||||
QStringList files = shipped_subDir.entryList();
|
QStringList files = shipped_subDir.entryList();
|
||||||
QString file;
|
QString file;
|
||||||
foreach(file, files){
|
foreach(file, files){
|
||||||
QString shipped_file = shipped_subDir.path()+QDir::separator()+file;
|
QString shipped_file = shipped_subDir.path()+"/"+file;
|
||||||
// Copy python classes
|
// Copy python classes
|
||||||
if(file.endsWith(".py")) {
|
if(file.endsWith(".py")) {
|
||||||
if(misc::getPluginVersion(shipped_file) > misc::getPluginVersion(destDir+file) ) {
|
if(misc::getPluginVersion(shipped_file) > misc::getPluginVersion(destDir+file) ) {
|
||||||
@@ -448,6 +458,7 @@ void SearchEngine::on_stop_search_button_clicked(){
|
|||||||
// Kill process
|
// Kill process
|
||||||
searchProcess->terminate();
|
searchProcess->terminate();
|
||||||
search_stopped = true;
|
search_stopped = true;
|
||||||
|
searchTimeout->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear search results list
|
// Clear search results list
|
||||||
@@ -455,12 +466,13 @@ void SearchEngine::on_clear_button_clicked(){
|
|||||||
// Kill process
|
// Kill process
|
||||||
searchProcess->terminate();
|
searchProcess->terminate();
|
||||||
search_stopped = true;
|
search_stopped = true;
|
||||||
|
searchTimeout->stop();
|
||||||
searchResultsUrls.clear();
|
searchResultsUrls.clear();
|
||||||
SearchListModel->removeRows(0, SearchListModel->rowCount());
|
SearchListModel->removeRows(0, SearchListModel->rowCount());
|
||||||
// Disable clear & download buttons
|
// Disable clear & download buttons
|
||||||
clear_button->setEnabled(false);
|
clear_button->setEnabled(false);
|
||||||
download_button->setEnabled(false);
|
download_button->setEnabled(false);
|
||||||
|
nb_search_results = 0;
|
||||||
results_lbl->setText(tr("Results")+" <i>(0)</i>:");
|
results_lbl->setText(tr("Results")+" <i>(0)</i>:");
|
||||||
// focus on search pattern
|
// focus on search pattern
|
||||||
search_pattern->clear();
|
search_pattern->clear();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class SearchListDelegate;
|
|||||||
class bittorrent;
|
class bittorrent;
|
||||||
class QSystemTrayIcon;
|
class QSystemTrayIcon;
|
||||||
class downloadThread;
|
class downloadThread;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
class SearchEngine : public QWidget, public Ui::search_engine{
|
class SearchEngine : public QWidget, public Ui::search_engine{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -54,6 +55,7 @@ class SearchEngine : public QWidget, public Ui::search_engine{
|
|||||||
bool systrayIntegration;
|
bool systrayIntegration;
|
||||||
downloadThread *downloader;
|
downloadThread *downloader;
|
||||||
QStringList enabled_engines;
|
QStringList enabled_engines;
|
||||||
|
QTimer *searchTimeout;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SearchEngine(bittorrent *BTSession, QSystemTrayIcon *myTrayIcon, bool systrayIntegration);
|
SearchEngine(bittorrent *BTSession, QSystemTrayIcon *myTrayIcon, bool systrayIntegration);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#VERSION: 1.10
|
#VERSION: 1.12
|
||||||
#AUTHORS: Fabien Devaux (fab@gnux.info)
|
#AUTHORS: Fabien Devaux (fab@gnux.info)
|
||||||
from novaprinter import prettyPrinter
|
from novaprinter import prettyPrinter
|
||||||
import urllib
|
import urllib
|
||||||
@@ -10,11 +10,11 @@ class btjunkie(object):
|
|||||||
|
|
||||||
def search(self, what):
|
def search(self, what):
|
||||||
i = 1
|
i = 1
|
||||||
while True:
|
while True and i<11:
|
||||||
res = 0
|
res = 0
|
||||||
dat = urllib.urlopen(self.url+'/search?q=%s&o=52&p=%d'%(what,i)).read().decode('utf8', 'replace')
|
dat = urllib.urlopen(self.url+'/search?q=%s&o=52&p=%d'%(what,i)).read().decode('utf8', 'replace')
|
||||||
# I know it's not very readable, but the SGML parser feels in pain
|
# I know it's not very readable, but the SGML parser feels in pain
|
||||||
section_re = re.compile('(?s)href="/torrent.*?<tr>')
|
section_re = re.compile('(?s)href="http://dl.btjunkie.org/torrent/.*?<tr>')
|
||||||
torrent_re = re.compile('(?s)href="(?P<link>.*?[^"]+).*?'
|
torrent_re = re.compile('(?s)href="(?P<link>.*?[^"]+).*?'
|
||||||
'class="BlckUnd">(?P<name>.*?)</a>.*?'
|
'class="BlckUnd">(?P<name>.*?)</a>.*?'
|
||||||
'>(?P<size>\d+MB)</font>.*?'
|
'>(?P<size>\d+MB)</font>.*?'
|
||||||
@@ -27,9 +27,9 @@ class btjunkie(object):
|
|||||||
torrent_infos = m.groupdict()
|
torrent_infos = m.groupdict()
|
||||||
torrent_infos['name'] = re.sub('</?font.*?>', '', torrent_infos['name'])
|
torrent_infos['name'] = re.sub('</?font.*?>', '', torrent_infos['name'])
|
||||||
torrent_infos['engine_url'] = self.url
|
torrent_infos['engine_url'] = self.url
|
||||||
torrent_infos['link'] = self.url+torrent_infos['link']
|
#torrent_infos['link'] = self.url+torrent_infos['link']
|
||||||
prettyPrinter(torrent_infos)
|
prettyPrinter(torrent_infos)
|
||||||
res = res + 1
|
res = res + 1
|
||||||
if res == 0:
|
if res == 0:
|
||||||
break
|
break
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#VERSION: 1.00
|
#VERSION: 1.01
|
||||||
#AUTHORS: Gekko Dam Beer (gekko04@users.sourceforge.net)
|
#AUTHORS: Gekko Dam Beer (gekko04@users.sourceforge.net)
|
||||||
from novaprinter import prettyPrinter
|
from novaprinter import prettyPrinter
|
||||||
import sgmllib
|
import sgmllib
|
||||||
@@ -67,7 +67,7 @@ class isohunt(object):
|
|||||||
|
|
||||||
def search(self, what):
|
def search(self, what):
|
||||||
i = 1
|
i = 1
|
||||||
while True:
|
while True and i<11:
|
||||||
results = []
|
results = []
|
||||||
parser = self.SimpleSGMLParser(results, self.url)
|
parser = self.SimpleSGMLParser(results, self.url)
|
||||||
dat = urllib.urlopen(self.url+'/torrents.php?ihq=%s&ihp=%s'%(what,i)).read().decode('utf-8', 'replace')
|
dat = urllib.urlopen(self.url+'/torrents.php?ihq=%s&ihp=%s'%(what,i)).read().decode('utf-8', 'replace')
|
||||||
@@ -75,4 +75,4 @@ class isohunt(object):
|
|||||||
parser.close()
|
parser.close()
|
||||||
if len(results) <= 0:
|
if len(results) <= 0:
|
||||||
break
|
break
|
||||||
i += 1
|
i += 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#VERSION: 1.11
|
#VERSION: 1.12
|
||||||
#AUTHORS: Fabien Devaux (fab@gnux.info)
|
#AUTHORS: Fabien Devaux (fab@gnux.info)
|
||||||
from novaprinter import prettyPrinter
|
from novaprinter import prettyPrinter
|
||||||
import urllib
|
import urllib
|
||||||
@@ -29,7 +29,7 @@ class mininova(object):
|
|||||||
else:
|
else:
|
||||||
return ''.join([ get_text(n) for n in txt.childNodes])
|
return ''.join([ get_text(n) for n in txt.childNodes])
|
||||||
page = 1
|
page = 1
|
||||||
while True:
|
while True and page<11:
|
||||||
res = 0
|
res = 0
|
||||||
dat = urllib.urlopen(self.url+'/search/%s/seeds/%d'%(what, page)).read().decode('utf-8', 'replace')
|
dat = urllib.urlopen(self.url+'/search/%s/seeds/%d'%(what, page)).read().decode('utf-8', 'replace')
|
||||||
dat = re.sub("<a href=\"http://www.boardreader.com/index.php.*\"", "<a href=\"plop\"", dat)
|
dat = re.sub("<a href=\"http://www.boardreader.com/index.php.*\"", "<a href=\"plop\"", dat)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#VERSION: 1.00
|
#VERSION: 1.01
|
||||||
#AUTHORS: Fabien Devaux (fab@gnux.info)
|
#AUTHORS: Fabien Devaux (fab@gnux.info)
|
||||||
from novaprinter import prettyPrinter
|
from novaprinter import prettyPrinter
|
||||||
import sgmllib
|
import sgmllib
|
||||||
@@ -68,7 +68,7 @@ class piratebay(object):
|
|||||||
ret = []
|
ret = []
|
||||||
i = 0
|
i = 0
|
||||||
order = 'se'
|
order = 'se'
|
||||||
while True:
|
while True and i<11:
|
||||||
results = []
|
results = []
|
||||||
parser = self.SimpleSGMLParser(results, self.url)
|
parser = self.SimpleSGMLParser(results, self.url)
|
||||||
dat = urllib.urlopen(self.url+'/search/%s/%u/0/0' % (what, i)).read()
|
dat = urllib.urlopen(self.url+'/search/%s/%u/0/0' % (what, i)).read()
|
||||||
@@ -76,4 +76,4 @@ class piratebay(object):
|
|||||||
parser.close()
|
parser.close()
|
||||||
if len(results) <= 0:
|
if len(results) <= 0:
|
||||||
break
|
break
|
||||||
i += 1
|
i += 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#VERSION: 1.00
|
#VERSION: 1.02
|
||||||
#AUTHORS: Gekko Dam Beer (gekko04@users.sourceforge.net)
|
#AUTHORS: Gekko Dam Beer (gekko04@users.sourceforge.net)
|
||||||
from novaprinter import prettyPrinter
|
from novaprinter import prettyPrinter
|
||||||
import sgmllib
|
import sgmllib
|
||||||
@@ -22,9 +22,7 @@ class torrentreactor(object):
|
|||||||
if params['href'].startswith('http://dl.torrentreactor.net/download.php'):
|
if params['href'].startswith('http://dl.torrentreactor.net/download.php'):
|
||||||
self.current_item = {}
|
self.current_item = {}
|
||||||
self.td_counter = 0
|
self.td_counter = 0
|
||||||
equal = params['href'].find("=")
|
self.current_item['link'] = params['href'].strip()
|
||||||
amp = params['href'].find("&", equal+1)
|
|
||||||
self.id = str(int(params['href'][equal+1:amp]))
|
|
||||||
|
|
||||||
def handle_data(self, data):
|
def handle_data(self, data):
|
||||||
if self.td_counter == 0:
|
if self.td_counter == 0:
|
||||||
@@ -47,11 +45,10 @@ class torrentreactor(object):
|
|||||||
def start_td(self,attr):
|
def start_td(self,attr):
|
||||||
if isinstance(self.td_counter,int):
|
if isinstance(self.td_counter,int):
|
||||||
self.td_counter += 1
|
self.td_counter += 1
|
||||||
if self.td_counter > 7:
|
if self.td_counter > 3:
|
||||||
self.td_counter = None
|
self.td_counter = None
|
||||||
# add item to results
|
# add item to results
|
||||||
if self.current_item:
|
if self.current_item:
|
||||||
self.current_item['link']='http://download.torrentreactor.net/download.php?id=%s&name=%s'%(self.id, urllib.quote(self.current_item['name']))
|
|
||||||
self.current_item['engine_url'] = self.url
|
self.current_item['engine_url'] = self.url
|
||||||
if not self.current_item['seeds'].isdigit():
|
if not self.current_item['seeds'].isdigit():
|
||||||
self.current_item['seeds'] = 0
|
self.current_item['seeds'] = 0
|
||||||
@@ -67,12 +64,13 @@ class torrentreactor(object):
|
|||||||
|
|
||||||
def search(self, what):
|
def search(self, what):
|
||||||
i = 0
|
i = 0
|
||||||
while True:
|
while True and i<11:
|
||||||
results = []
|
results = []
|
||||||
parser = self.SimpleSGMLParser(results, self.url)
|
parser = self.SimpleSGMLParser(results, self.url)
|
||||||
dat = urllib.urlopen(self.url+'/search.php?search=&words=%s&cid=&sid=&type=2&orderby=a.seeds&asc=0&skip=%s'%(what,(i*35))).read().decode('utf-8', 'replace')
|
dat = urllib.urlopen(self.url+'/search.php?search=&words=%s&cid=&sid=&type=2&orderby=a.seeds&asc=0&skip=%s'%(what,(i*35))).read().decode('utf-8', 'replace')
|
||||||
|
#print "loading page: "+self.url+'/search.php?search=&words=%s&cid=&sid=&type=2&orderby=a.seeds&asc=0&skip=%s'%(what,(i*35))
|
||||||
parser.feed(dat)
|
parser.feed(dat)
|
||||||
parser.close()
|
parser.close()
|
||||||
if len(results) <= 0:
|
if len(results) <= 0:
|
||||||
break
|
break
|
||||||
i += 1
|
i += 1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
isohunt: 1.00
|
isohunt: 1.01
|
||||||
torrentreactor: 1.00
|
torrentreactor: 1.02
|
||||||
btjunkie: 1.10
|
btjunkie: 1.12
|
||||||
mininova: 1.11
|
mininova: 1.12
|
||||||
piratebay: 1.00
|
piratebay: 1.01
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ TARGET = qbittorrent
|
|||||||
CONFIG += qt thread x11 network
|
CONFIG += qt thread x11 network
|
||||||
|
|
||||||
# Update this VERSION for each release
|
# Update this VERSION for each release
|
||||||
DEFINES += VERSION=\\\"v1.0.0rc8\\\"
|
DEFINES += VERSION=\\\"v1.0.0rc11\\\"
|
||||||
DEFINES += VERSION_MAJOR=1
|
DEFINES += VERSION_MAJOR=1
|
||||||
DEFINES += VERSION_MINOR=0
|
DEFINES += VERSION_MINOR=0
|
||||||
DEFINES += VERSION_BUGFIX=0
|
DEFINES += VERSION_BUGFIX=0
|
||||||
@@ -81,7 +81,7 @@ QMAKE_CXXFLAGS_RELEASE += -fwrapv -O2
|
|||||||
QMAKE_CXXFLAGS_DEBUG += -fwrapv -O1
|
QMAKE_CXXFLAGS_DEBUG += -fwrapv -O1
|
||||||
|
|
||||||
CONFIG += link_pkgconfig
|
CONFIG += link_pkgconfig
|
||||||
PKGCONFIG += libtorrent libccext2 libccgnu2
|
PKGCONFIG += "libtorrent libcurl"
|
||||||
|
|
||||||
!contains(DEFINES, HAVE_MAGICK){
|
!contains(DEFINES, HAVE_MAGICK){
|
||||||
message(ImageMagick disabled)
|
message(ImageMagick disabled)
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
|
|||||||
// Display warning to tell user we can't decode the torrent file
|
// Display warning to tell user we can't decode the torrent file
|
||||||
if(!from_url.isNull()){
|
if(!from_url.isNull()){
|
||||||
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
||||||
|
QFile::remove(filePath);
|
||||||
}else{
|
}else{
|
||||||
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
||||||
}
|
}
|
||||||
@@ -142,9 +143,11 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
|
|||||||
// Display warning to tell user we can't decode the torrent file
|
// Display warning to tell user we can't decode the torrent file
|
||||||
if(!from_url.isNull()){
|
if(!from_url.isNull()){
|
||||||
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
||||||
|
QFile::remove(filePath);
|
||||||
}else{
|
}else{
|
||||||
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
emit setInfoBarGUI(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
|
||||||
}
|
}
|
||||||
|
qDebug("path is %s", filePath.toUtf8().data());
|
||||||
emit setInfoBarGUI(tr("This file is either corrupted or this isn't a torrent."), QString::fromUtf8("red"));
|
emit setInfoBarGUI(tr("This file is either corrupted or this isn't a torrent."), QString::fromUtf8("red"));
|
||||||
if(fromScanDir){
|
if(fromScanDir){
|
||||||
// Remove .corrupt file in case it already exists
|
// Remove .corrupt file in case it already exists
|
||||||
|
|||||||
Reference in New Issue
Block a user