1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-10-12 03:12:18 +02:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Christophe Dumez
6ecb5fe1e1 - Tagged rc8 2007-11-14 21:51:47 +00:00
89 changed files with 6865 additions and 7040 deletions

View File

@@ -41,25 +41,22 @@
- FEATURE: Added an option to automatically delete torrents when they reach a given ratio (>= 1.0)
- FEATURE: Added an option to display current transfer speeds in title bar
- FEATURE: Torrent content is now displayed as a tree
- FEATURE: Better media file preview (player detected automatically)
- FEATURE: Greatly improved ETA calculation algorithm (use GASA)
- I18N: Added Hungarian translation
- I18N: Added Brazilian translation
- BUGFIX: Progress of paused torrents is now correct on restart
- BUGFIX: clear the results of a search stops searching
- 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: Fixed a crash when filtering all the files in a torrent
- BUGFIX: Reload torrent only when necessary (properties)
- BUGFIX: qBittorrent is not exiting anymore when a dialog is closed and main window is hidden
- BUGFIX: Catch all possible exceptions when adding a torrent to avoid crashing
- BUGFIX: Search plugin update is not making the GUI freeze anymore (moved to a thread)
- BUGFIX: DHT settings were not saved correctly
- BUGFIX: Workaround to build on Fedora system (pkg-config problem)
- BUGFIX: search plugin update - do not display only last version changelog
- BUGFIX: Search plugin update - fixed missing new lines in changelog
- BUGFIX: The number of search results was not reset when clicking on 'Clear' button
- BUGFIX: Fixed systray integration when qbittorrent is launched on system startup
- BUGFIX: Update torrent progress when its content changed (filtered files)
- BUGFIX: Improved the way menu icons are installed to avoid problems on some systems
- BUGFIX: Improved incremental download
@@ -70,8 +67,6 @@
- BUGFIX: Fixed drag'n drop on non-KDE systems
- BUGFIX: Removed build dependency on Python
- BUGFIX: Catching DHT exception in case there is a problem
- BUGFIX: Remember properties window size and position
- BUGFIX: Improved proxy support in search engine (HTTP only)
- COSMETIC: Redesigned torrent properties a little
- COSMETIC: Totally redesigned program preferences
- COSMETIC: Display more logs messages concerning features

View File

@@ -25,7 +25,7 @@ Dependencies:
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
- libcurl
- libcommoncpp2
- python >= 2.3 (needed by search engine)

20
TODO
View File

@@ -8,9 +8,11 @@
- Skins support? (contact Mateusz)
// Harder
- Display a progress bar that really represents the pieces we have (like in eMule)
- Torrent scheduler ala µtorrent/Bitcomet
// Waiting for libtorrent
- File selection in a torrent in compact mode
- Allow to prioritize torrents (may code this in qBittorrent?)
// Unsure
@@ -30,6 +32,7 @@
// in v1.1.0
- Tabs support in search
- Allow to hide columns?
- Allow to scan multiple directories? (useful?)
- Web interface (turbogears? php? python?)
* Webserver? Try to write a webserver as a plugin for qBittorrent in Python
@@ -43,7 +46,18 @@
- Display in torrent addition dialog:
* free disk space on selected drive
* free disk space after torrent download (and/or torrent size)
- Start minimized option in program preferences
- In finished list, replace "Seeds/Leechs" column by "Leechers" because Seeds are always 0.
- Allow to change action on double-click
-> in download list
-> in seeding list
rc11 -> final? changelog:
BUGFIX: Fixed systray integration when qbittorrent is launched on system startup
BUGFIX: Catch all possible exceptions when adding a torrent to avoid crashing
// in v1.0.0 - FEATURE FREEZE
- Fix all (or almost all) opened bugs in bug tracker
- Recheck doc
- Translations update (IN PROGRESS)
rc7->rc8 changelog:
- BUGFIX: Fixed torrent files filtering
- BUGFIX: Stop search when clearing results
- BUGFIX: Fixed compilation on Fedora 8

68
configure vendored
View File

@@ -22,8 +22,8 @@ Dependency options:
--with-libtorrent-lib=[path] Path to libtorrent library files
--with-libtorrent-static-lib=[path] Path to libtorrent .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
--with-libcommoncpp2-inc=[path] Path to libcommoncpp2 include files
--with-libcommoncpp2-lib=[path] Path to libcommoncpp2 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
@@ -166,13 +166,13 @@ while [ $# -gt 0 ]; do
shift
;;
--with-libcurl-inc=*)
QC_WITH_LIBCURL_INC=$optarg
--with-libcommoncpp2-inc=*)
QC_WITH_LIBCOMMONCPP2_INC=$optarg
shift
;;
--with-libcurl-lib=*)
QC_WITH_LIBCURL_LIB=$optarg
--with-libcommoncpp2-lib=*)
QC_WITH_LIBCOMMONCPP2_LIB=$optarg
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_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_WITH_LIBCOMMONCPP2_INC=$QC_WITH_LIBCOMMONCPP2_INC
echo QC_WITH_LIBCOMMONCPP2_LIB=$QC_WITH_LIBCOMMONCPP2_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
@@ -485,25 +485,25 @@ public:
return true;
}
};
#line 1 "libcurl.qcm"
#line 1 "libcommoncpp2.qcm"
/*
-----BEGIN QCMOD-----
name: libcommoncpp2
arg: with-libcurl-inc=[path], Path to libcurl include files
arg: with-libcurl-lib=[path], Path to libcurl library files
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
-----END QCMOD-----
*/
class qc_libcurl : public ConfObj
class qc_libcommoncpp2 : public ConfObj
{
public:
qc_libcurl(Conf *c) : ConfObj(c) {}
QString name() const { return "libcurl"; }
QString shortname() const { return "libcurl"; }
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_LIBCURL_INC");
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "curl/curl.h")) {
if(!conf->checkHeader(s, "cc++/url.h")) {
return false;
}
}else{
@@ -512,7 +512,7 @@ public:
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "curl/curl.h")){
if(conf->checkHeader(s, "cc++/url.h")){
found = true;
break;
}
@@ -523,10 +523,12 @@ public:
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBCURL_LIB");
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
if(!s.isEmpty()) {
if(!QFile::exists(s+QString("/libcurl.so")))
return false;
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;
@@ -536,9 +538,11 @@ public:
sl << "/usr/local/lib64/";
bool found = false;
foreach(s, sl){
if(QFile::exists(s+QString("libcurl.so"))){
found = true;
break;
if(QFile::exists(s+QString("libccext2.so"))){
if(QFile::exists(s+QString("libccgnu2.so"))){
found = true;
break;
}
}
}
if(!found) return false;
@@ -594,9 +598,9 @@ public:
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "Magick++")) {
return false;
}
if(!QFile::exists(s+QString("/libMagick++.so"))){
return false;
}
}else{
QStringList sl;
sl << "/usr/lib/";
@@ -605,9 +609,9 @@ public:
sl << "/usr/local/lib64/";
bool found = false;
foreach(s, sl){
if(conf->checkLibrary(s, "Magick++")) {
if(QFile::exists(s+QString("libMagick++.so"))){
found = true;
break;
break;
}
}
if(!found)
@@ -711,7 +715,7 @@ cat >$1/modules_new.cpp <<EOT
o = new qc_libboost(conf);
o->required = true;
o->disabled = false;
o = new qc_libcurl(conf);
o = new qc_libcommoncpp2(conf);
o->required = true;
o->disabled = false;
o = new qc_libmagick(conf);
@@ -1669,8 +1673,8 @@ 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_WITH_LIBCOMMONCPP2_INC
export QC_WITH_LIBCOMMONCPP2_LIB
export QC_DISABLE_libmagick
export QC_WITH_LIBMAGICK_INC
export QC_WITH_LIBMAGICK_LIB

View File

@@ -12,7 +12,7 @@
<dep type='libboost'>
<required/>
</dep>
<dep type='libcurl'>
<dep type='libcommoncpp2'>
<required/>
</dep>
<dep type='libmagick'/>

View File

@@ -1,61 +0,0 @@
/*
-----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;
}
};

View File

@@ -44,9 +44,9 @@ public:
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "Magick++")) {
return false;
}
if(!QFile::exists(s+QString("/libMagick++.so"))){
return false;
}
}else{
QStringList sl;
sl << "/usr/lib/";
@@ -55,9 +55,9 @@ public:
sl << "/usr/local/lib64/";
bool found = false;
foreach(s, sl){
if(conf->checkLibrary(s, "Magick++")) {
if(QFile::exists(s+QString("libMagick++.so"))){
found = true;
break;
break;
}
}
if(!found)

View File

@@ -313,6 +313,8 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
QModelIndex index;
// Enable/disable pause/start action given the DL state
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
QSettings settings("qBittorrent", "qBittorrent");
QString previewProgram = settings.value("Preferences/general/MediaPlayer", QString()).toString();
bool has_pause = false, has_start = false, has_preview = false;
foreach(index, selectedIndexes) {
if(index.column() == F_NAME) {
@@ -332,7 +334,7 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
has_pause = true;
}
}
if(BTSession->isFilePreviewPossible(hash) && !has_preview) {
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
myFinishedListMenu.addAction(actionPreview_file);
has_preview = true;
}

View File

@@ -45,7 +45,6 @@
#include "options_imp.h"
#include "previewSelect.h"
#include "allocationDlg.h"
#include "stdlib.h"
using namespace libtorrent;
@@ -61,21 +60,14 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION)));
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
systrayIntegration = settings.value(QString::fromUtf8("Preferences/General/SystrayEnabled"), true).toBool();
systrayCreator = 0;
// Create tray icon
if (QSystemTrayIcon::isSystemTrayAvailable()) {
if(systrayIntegration) {
createTrayIcon();
}
}else{
if(systrayIntegration) {
// May be system startup, check again later
systrayCreator = new QTimer(this);
connect(systrayCreator, SIGNAL(timeout()), this, SLOT(createSystrayDelayed()));
systrayCreator->start(1000);
}
systrayIntegration = false;
qDebug("Info: System tray unavailable");
qDebug("Info: System tray unavailable\n");
}
// Setting icons
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent32.png")));
@@ -167,6 +159,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
checkConnect = new QTimer(this);
connect(checkConnect, SIGNAL(timeout()), this, SLOT(checkConnectionStatus()));
checkConnect->start(5000);
previewProcess = new QProcess(this);
connect(previewProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cleanTempPreviewFile(int, QProcess::ExitStatus)));
// Accept drag 'n drops
setAcceptDrops(true);
show();
@@ -183,14 +177,14 @@ GUI::~GUI() {
delete downloadingTorrentTab;
delete finishedTorrentTab;
delete checkConnect;
if(systrayCreator) {
delete systrayCreator;
}
if(systrayIntegration) {
delete myTrayIcon;
delete myTrayIconMenu;
}
delete tcpServer;
previewProcess->kill();
previewProcess->waitForFinished();
delete previewProcess;
delete connecStatusLblIcon;
delete tabs;
// Keyboard shortcuts
@@ -394,6 +388,12 @@ void GUI::on_actionPreview_file_triggered() {
new previewSelect(this, h);
}
void GUI::cleanTempPreviewFile(int, QProcess::ExitStatus) const {
if(!QFile::remove(QDir::tempPath()+QDir::separator()+QString::fromUtf8("qBT_preview.tmp"))) {
std::cerr << "Couldn't remove temporary file: " << (QDir::tempPath()+QDir::separator()+QString::fromUtf8("qBT_preview.tmp")).toUtf8().data() << "\n";
}
}
// Necessary if we want to close the window
// in one time if "close to systray" is enabled
void GUI::on_actionExit_triggered() {
@@ -402,10 +402,24 @@ void GUI::on_actionExit_triggered() {
}
void GUI::previewFile(QString filePath) {
QDesktopServices::openUrl(QString("file://")+filePath);
// Check if there is already one preview running
if(previewProcess->state() == QProcess::NotRunning) {
// First copy temporarily (XXX: is it necessary?)
QString tmpPath = QDir::tempPath()+QDir::separator()+QString::fromUtf8("qBT_preview.tmp");
QFile::remove(tmpPath);
QFile::copy(filePath, tmpPath);
// Launch program preview
QStringList params;
params << tmpPath;
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString previewProgram = settings.value(QString::fromUtf8("Preferences/General/MediaPlayer"), QString()).toString();
previewProcess->start(previewProgram, params, QIODevice::ReadOnly);
}else{
QMessageBox::critical(0, tr("Preview process already running"), tr("There is already another preview process running.\nPlease close the other one first."));
}
}
int GUI::getCurrentTabIndex() const{
unsigned int GUI::getCurrentTabIndex() const{
if(isMinimized() || isHidden())
return -1;
return tabs->currentIndex();
@@ -459,7 +473,7 @@ void GUI::on_actionAbout_triggered() {
// Called when we close the program
void GUI::closeEvent(QCloseEvent *e) {
qDebug("Mainwindow received closeEvent");
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool();
if(!force_exit && systrayIntegration && goToSystrayOnExit && !this->isHidden()) {
@@ -471,16 +485,13 @@ void GUI::closeEvent(QCloseEvent *e) {
show();
if(!isMaximized())
showNormal();
if(e->spontaneous() == true || force_exit == true) {
if(QMessageBox::question(this,
tr("Are you sure you want to quit?")+QString::fromUtf8(" -- ")+tr("qBittorrent"),
tr("The download list is not empty.\nAre you sure you want to quit qBittorrent?"),
tr("&Yes"), tr("&No"),
QString(), 0, 1)) {
e->ignore();
force_exit = false;
return;
}
if(QMessageBox::question(this,
tr("Are you sure you want to quit?")+QString::fromUtf8(" -- ")+tr("qBittorrent"),
tr("The download list is not empty.\nAre you sure you want to quit qBittorrent?"),
tr("&Yes"), tr("&No"),
QString(), 0, 1)) {
e->ignore();
return;
}
}
hide();
@@ -498,7 +509,6 @@ void GUI::closeEvent(QCloseEvent *e) {
qApp->exit();
}
// Display window to create a torrent
void GUI::on_actionCreate_torrent_triggered() {
createtorrent *ct = new createtorrent(this);
@@ -778,12 +788,7 @@ void GUI::processDownloadedFiles(QString path, QString url) {
void GUI::configureSession(bool deleteOptions) {
qDebug("Configuring session");
// General
bool new_displaySpeedInTitle = options->speedInTitleBar();
if(!new_displaySpeedInTitle && new_displaySpeedInTitle != displaySpeedInTitle) {
// Reset title
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION)));
}
displaySpeedInTitle = new_displaySpeedInTitle;
displaySpeedInTitle = options->speedInTitleBar();
unsigned int new_refreshInterval = options->getRefreshInterval();
if(refreshInterval != new_refreshInterval) {
refreshInterval = new_refreshInterval;
@@ -844,21 +849,12 @@ void GUI::configureSession(bool deleteOptions) {
// * Proxy settings
proxy_settings proxySettings;
if(options->isProxyEnabled()) {
proxySettings.hostname = options->getProxyIp().toStdString();
proxySettings.port = options->getProxyPort();
if(options->isProxyAuthEnabled()) {
proxySettings.username = options->getProxyUsername().toStdString();
proxySettings.password = options->getProxyPassword().toStdString();
}
QString proxy_str;
switch(options->getProxyType()) {
case HTTP:
proxySettings.type = proxy_settings::http;
proxy_str = misc::toQString("http://")+options->getProxyIp()+":"+misc::toQString(proxySettings.port);
break;
case HTTP_PW:
proxySettings.type = proxy_settings::http_pw;
proxy_str = misc::toQString("http://")+options->getProxyUsername()+":"+options->getProxyPassword()+"@"+options->getProxyIp()+":"+misc::toQString(proxySettings.port);
break;
case SOCKS5:
proxySettings.type = proxy_settings::socks5;
@@ -867,22 +863,12 @@ void GUI::configureSession(bool deleteOptions) {
proxySettings.type = proxy_settings::socks5_pw;
break;
}
if(!proxy_str.isEmpty()) {
// 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);
#endif
proxySettings.hostname = options->getProxyIp().toStdString();
proxySettings.port = options->getProxyPort();
if(options->isProxyAuthEnabled()) {
proxySettings.username = options->getProxyUsername().toStdString();
proxySettings.password = options->getProxyPassword().toStdString();
}
} else {
#ifdef Q_WS_WIN
putenv("http_proxy=");
#else
unsetenv("http_proxy");
#endif
}
BTSession->setProxySettings(proxySettings, options->useProxyForTrackers(), options->useProxyForPeers(), options->useProxyForWebseeds(), options->useProxyForDHT());
// * Session settings
@@ -1193,37 +1179,9 @@ void GUI::downloadFromURLList(const QStringList& urls) {
* *
*****************************************************/
void GUI::createSystrayDelayed() {
static int timeout = 10;
if(QSystemTrayIcon::isSystemTrayAvailable()) {
// Ok, systray integration is now supported
// Create systray icon
createTrayIcon();
systrayIntegration = true;
delete systrayCreator;
systrayCreator = 0;
} else {
if(timeout) {
// Retry a bit later
systrayCreator->start(1000);
--timeout;
} else {
// Timed out, apparently system really does not
// support systray icon
delete systrayCreator;
systrayCreator = 0;
}
}
}
void GUI::createTrayIcon() {
// Tray icon
#ifdef Q_WS_WIN
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent16.png")), this);
#endif
#ifndef Q_WS_WIN
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent22.png")), this);
#endif
// Tray icon Menu
myTrayIconMenu = new QMenu(this);
myTrayIconMenu->addAction(actionOpen);

View File

@@ -59,7 +59,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
QTabWidget *tabs;
options_imp *options;
QSystemTrayIcon *myTrayIcon;
QTimer *systrayCreator;
QMenu *myTrayIconMenu;
DownloadingTorrents *downloadingTorrentTab;
FinishedTorrents *finishedTorrentTab;
@@ -75,6 +74,8 @@ class GUI : public QMainWindow, private Ui::MainWindow{
QShortcut *switchDownShortcut;
QShortcut *switchUpShortcut;
QShortcut *switchRSSShortcut;
// Preview
QProcess *previewProcess;
// Search
SearchEngine *searchEngine;
// RSS
@@ -97,6 +98,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void togglePausedState(QString hash);
void on_actionPreview_file_triggered();
void previewFile(QString filePath);
void cleanTempPreviewFile(int, QProcess::ExitStatus) const;
void balloonClicked();
void writeSettings();
void readSettings();
@@ -106,7 +108,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void updateFinishedTorrentNumber(unsigned int nb);
void fullDiskError(QTorrentHandle& h) const;
void handleDownloadFromUrlFailure(QString, QString) const;
void createSystrayDelayed();
// Keyboard shortcuts
void createKeyboardShortcuts();
void displayDownTab() const;
@@ -157,7 +158,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
~GUI();
// Methods
int getCurrentTabIndex() const;
unsigned int getCurrentTabIndex() const;
QPoint screenCenter() const;
};

View File

@@ -181,8 +181,7 @@ class PropListDelegate: public QItemDelegate {
// } else {
model->setData(index, QVariant(HIGH));
model->setData(index, QVariant(NORMAL));
if(filteredFilesChanged != 0)
*filteredFilesChanged = true;
*filteredFilesChanged = true;
// }
break;
case 2:

View File

@@ -27,19 +27,19 @@
#include <QDir>
#include "misc.h"
class torrent_file {
class file {
private:
torrent_file *parent;
file *parent;
bool is_dir;
QString rel_path;
QList<torrent_file*> children;
QList<file*> children;
size_type size;
float progress;
int priority;
int index; // Index in torrent_info
public:
torrent_file(torrent_file *parent, QString path, bool dir, size_type size=0, int index=-1, float progress=0., int priority=1): parent(parent), is_dir(dir), size(size), progress(progress), priority(priority), index(index){
file(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);
if(parent) {
@@ -48,7 +48,7 @@ class torrent_file {
}
}
~torrent_file() {
~file() {
qDeleteAll(children);
}
@@ -68,7 +68,7 @@ class torrent_file {
}
float wanted = 0.;
float done = 0.;
torrent_file *child;
file *child;
foreach(child, children) {
wanted += child->getSize();
done += child->getSize()*child->getProgress();
@@ -80,7 +80,7 @@ class torrent_file {
void updatePriority(int prio) {
Q_ASSERT(is_dir);
torrent_file *child;
file *child;
foreach(child, children) {
if(child->getPriority() != prio) return;
}
@@ -111,13 +111,13 @@ class torrent_file {
return (!children.isEmpty());
}
QList<torrent_file*> getChildren() const {
QList<file*> getChildren() const {
return children;
}
torrent_file* getChild(QString fileName) const {
file* getChild(QString fileName) const {
Q_ASSERT(is_dir);
torrent_file* f;
file* f;
foreach(f, children) {
if(f->name() == fileName) return f;
}
@@ -130,10 +130,10 @@ class torrent_file {
parent->addBytes(b);
}
torrent_file* addChild(QString fileName, bool dir, size_type size=0, int index = -1, float progress=0., int priority=1) {
file* addChild(QString fileName, bool dir, size_type size=0, int index = -1, float progress=0., int priority=1) {
Q_ASSERT(is_dir);
qDebug("Adding a new child of size: %ld", (long)size);
torrent_file *f = new torrent_file(this, QDir::cleanPath(rel_path+QDir::separator()+fileName), dir, size, index, progress, priority);
file *f = new file(this, QDir::cleanPath(rel_path+QDir::separator()+fileName), dir, size, index, progress, priority);
children << f;
if(size) {
addBytes(size);
@@ -148,7 +148,7 @@ class torrent_file {
return true;
}
bool success = true;
torrent_file *f;
file *f;
qDebug("We have %d children", children.size());
foreach(f, children) {
bool s = f->removeFromFS(saveDir);
@@ -169,16 +169,16 @@ class torrent_file {
class arborescence {
private:
torrent_file *root;
file *root;
public:
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);
root = new 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 file(0, misc::toQString(t.name()), false, fi->size, 0);
return;
}
int i = 0;
@@ -196,11 +196,11 @@ class arborescence {
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");
root = new torrent_file(0, misc::toQString(t.name()), true);
root = new file(0, misc::toQString(t.name()), true);
} 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, fp[0], prioritiesTab[0]);
root = new file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0], prioritiesTab[0]);
return;
}
int i = 0;
@@ -218,7 +218,7 @@ class arborescence {
delete root;
}
torrent_file* getRoot() const {
file* getRoot() const {
return root;
}
@@ -240,13 +240,13 @@ class arborescence {
relative_path.remove(0, 1);
QStringList fileNames = relative_path.split(QDir::separator());
QString fileName;
torrent_file *dad = root;
file *dad = root;
unsigned int nb_i = 0;
unsigned int size = fileNames.size();
foreach(fileName, fileNames) {
++nb_i;
if(fileName == ".") continue;
torrent_file* child = dad->getChild(fileName);
file* child = dad->getChild(fileName);
if(!child) {
if(nb_i != size) {
// Folder

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,6 @@
#include <QList>
#include <QPair>
#include <QStringList>
#include <QDateTime>
#include <libtorrent/session.hpp>
#include <libtorrent/ip_filter.hpp>
@@ -45,17 +44,18 @@ class bittorrent : public QObject{
QString scan_dir;
QTimer *timerScan;
QTimer *timerAlerts;
QTimer *fastResumeSaver;
QTimer *BigRatioTimer;
bool DHTEnabled;
downloadThread *downloader;
QString defaultSavePath;
QStringList torrentsToPauseAfterChecking;
QHash<QString, QDateTime> TorrentsStartTime;
QHash<QString, size_type> TorrentsStartData;
QHash<QString, bool> reloadingTorrents;
QHash<QString, QList<qlonglong> > ETAstats;
QHash<QString, qlonglong> ETAs;
QHash<QString, QPair<size_type,size_type> > ratioData;
QTimer *ETARefresher;
QHash<QString, QList<QPair<QString, QString> > > trackersErrors;
deleteThread *deleter;
QStringList waitingForPause;
QStringList finishedTorrents;
QStringList unfinishedTorrents;
bool preAllocateAll;
@@ -63,9 +63,6 @@ class bittorrent : public QObject{
int maxConnecsPerTorrent;
int maxUploadsPerTorrent;
float max_ratio;
bool UPnPEnabled;
bool NATPMPEnabled;
bool LSDEnabled;
protected:
QString getSavePath(QString hash);
@@ -83,7 +80,7 @@ class bittorrent : public QObject{
session_status getSessionStatus() const;
int getListenPort() const;
QStringList getTorrentsToPauseAfterChecking() const;
qlonglong getETA(QString hash) const;
long getETA(QString hash) const;
float getRealRatio(QString hash) const;
session* getSession() const;
QList<QPair<QString, QString> > getTrackersErrors(QString hash) const;
@@ -102,13 +99,13 @@ class bittorrent : public QObject{
void saveDHTEntry();
void preAllocateAllFiles(bool b);
void saveFastResumeAndRatioData();
void saveFastResumeAndRatioData(QString hash);
void enableDirectoryScanning(QString scan_dir);
void disableDirectoryScanning();
void enablePeerExchange();
void enableIPFilter(ip_filter filter);
void disableIPFilter();
void resumeUnfinishedTorrents();
void updateETAs();
void saveTorrentSpeedLimits(QString hash);
void loadTorrentSpeedLimits(QString hash);
void saveDownloadUploadForTorrent(QString hash);
@@ -139,7 +136,6 @@ class bittorrent : public QObject{
void enableNATPMP(bool b);
void enableLSD(bool b);
bool enableDHT(bool b);
void reloadTorrent(const QTorrentHandle &h, bool full_alloc);
protected slots:
void scanDirectory();
@@ -147,6 +143,8 @@ class bittorrent : public QObject{
void processDownloadedFile(QString, QString);
bool loadTrackerFile(QString hash);
void saveTrackerFile(QString hash);
void pauseAndReloadTorrent(QTorrentHandle h, bool full_alloc);
void reloadTorrent(const QTorrentHandle &h, bool full_alloc); // This is protected now, call pauseAndReloadTorrent() instead
void deleteBigRatios();
signals:

View File

@@ -36,7 +36,6 @@
#include <libtorrent/file_pool.hpp>
#include "createtorrent_imp.h"
#include "misc.h"
using namespace libtorrent;
using namespace boost::filesystem;
@@ -121,13 +120,11 @@ 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));
}
}
@@ -144,8 +141,6 @@ QStringList createtorrent::allItems(QListWidget *list){
// Main function that create a .torrent file
void createtorrent::on_createButton_clicked(){
QString input = textInputPath->text().trimmed();
if (input.endsWith(QDir::separator()))
input.chop(1);
if(input.isEmpty()){
QMessageBox::critical(0, tr("No input path set"), tr("Please type an input path first"));
return;
@@ -166,8 +161,9 @@ void createtorrent::on_createButton_clicked(){
try {
boost::intrusive_ptr<torrent_info> t(new torrent_info);
ofstream out(complete(path((const char*)destination.toUtf8())), std::ios_base::binary);
path full_path;
// Adding files to the torrent
path full_path = complete(path(input.toUtf8().data()));
full_path = complete(path(input.toUtf8().data()));
add_files(*t, full_path.branch_path(), full_path.leaf());
// Set piece size
int piece_size = getPieceSize();
@@ -204,14 +200,8 @@ void createtorrent::on_createButton_clicked(){
entry e = t->create_torrent();
libtorrent::bencode(std::ostream_iterator<char>(out), e);
out.flush();
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();
if(checkStartSeeding->isChecked())
emit torrent_to_seed(destination);
}
}
catch (std::exception& e){
std::cerr << e.what() << "\n";

View File

@@ -21,48 +21,43 @@
#include "downloadThread.h"
#include <iostream>
#include <QSettings>
#include <stdio.h>
#include <cc++/common.h>
// http://curl.rtin.bz/libcurl/c/libcurl-errors.html
QString subDownloadThread::errorCodeToString(CURLcode status) {
QString subDownloadThread::errorCodeToString(int status) {
switch(status){
case CURLE_FTP_CANT_GET_HOST:
case CURLE_COULDNT_RESOLVE_HOST:
case 1://ost::URLStream::errUnreachable:
return tr("Host is unreachable");
case CURLE_READ_ERROR:
case CURLE_FILE_COULDNT_READ_FILE:
case 2://ost::URLStream::errMissing:
return tr("File was not found (404)");
case CURLE_FTP_ACCESS_DENIED:
case CURLE_LOGIN_DENIED:
case CURLE_FTP_USER_PASSWORD_INCORRECT:
case 3://ost::URLStream::errDenied:
return tr("Connection was denied");
case CURLE_URL_MALFORMAT:
case 4://ost::URLStream::errInvalid:
return tr("Url is invalid");
case CURLE_COULDNT_RESOLVE_PROXY:
return tr("Could not resolve proxy");
//case 5:
// return tr("Connection forbidden (403)");
//case 6:
// return tr("Connection was not authorized (401)");
//case 7:
// return tr("Content has moved (301)");
case CURLE_COULDNT_CONNECT:
case 5://ost::URLStream::errForbidden:
return tr("Connection forbidden (403)");
case 6://ost::URLStream::errUnauthorized:
return tr("Connection was not authorized (401)");
case 7://ost::URLStream::errRelocated:
return tr("Content has moved (301)");
case 8://ost::URLStream::errFailure:
return tr("Connection failure");
case CURLE_OPERATION_TIMEOUTED:
case 9://ost::URLStream::errTimeout:
return tr("Connection was timed out");
case CURLE_INTERFACE_FAILED:
case 10://ost::URLStream::errInterface:
return tr("Incorrect network interface");
default:
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();
}
subDownloadThread::~subDownloadThread(){
abort = true;
wait();
delete url_stream;
}
void subDownloadThread::run(){
@@ -73,66 +68,38 @@ void subDownloadThread::run(){
filePath = tmpfile->fileName();
}
delete tmpfile;
FILE *f = fopen(filePath.toUtf8().data(), "wb");
if(!f) {
std::cerr << "couldn't open destination file" << "\n";
QFile dest_file(filePath);
if(!dest_file.open(QIODevice::WriteOnly | QIODevice::Text)){
std::cerr << "Error: could't create temporary file: " << (const char*)filePath.toUtf8() << '\n';
return;
}
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
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/ProxyType"), 0).toInt();
if(intValue > 0) {
// Proxy enabled
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");
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";
ost::URLStream::Error status = url_stream->get((const char*)url.toUtf8());
if(status){
// Failure
QString error_msg = errorCodeToString((int)status);
qDebug("Download failed for %s, reason: %s", (const char*)url.toUtf8(), (const char*)error_msg.toUtf8());
url_stream->close();
emit downloadFailureST(this, url, error_msg);
return;
}
qDebug("Downloading %s...", (const char*)url.toUtf8());
char cbuf[1024];
int len;
while(!url_stream->eof()) {
url_stream->read(cbuf, sizeof(cbuf));
len = url_stream->gcount();
if(len > 0)
dest_file.write(cbuf, len);
if(abort){
dest_file.close();
url_stream->close();
return;
}
}
dest_file.close();
url_stream->close();
emit downloadFinishedST(this, url, filePath);
qDebug("download completed here: %s", (const char*)filePath.toUtf8());
}
/** Download Thread **/

View File

@@ -29,18 +29,22 @@
#include <QMutexLocker>
#include <QWaitCondition>
#include <QStringList>
#include <curl/curl.h>
namespace ost {
class URLStream;
}
class subDownloadThread : public QThread {
Q_OBJECT
private:
QString url;
ost::URLStream *url_stream;
bool abort;
public:
subDownloadThread(QObject *parent, QString url);
~subDownloadThread();
QString errorCodeToString(CURLcode status);
QString errorCodeToString(int status);
signals:
// For subthreads
@@ -72,13 +76,13 @@ class downloadThread : public QThread {
~downloadThread();
void downloadUrl(QString url);
void setProxy(QString IP, int port, QString username, QString password);
protected:
void run();
protected slots:
void propagateDownloadedFile(subDownloadThread* st, QString url, QString path);
void propagateDownloadFailure(subDownloadThread* st, QString url, QString reason);
};

View File

@@ -190,6 +190,7 @@ void DownloadingTorrents::setInfoBar(QString info, QColor color) {
infoBar->clear();
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>"));
}
@@ -245,6 +246,8 @@ void DownloadingTorrents::displayDLListMenu(const QPoint& pos) {
QModelIndex index;
// Enable/disable pause/start action given the DL state
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString previewProgram = settings.value(QString::fromUtf8("Preferences/general/MediaPlayer"), QString()).toString();
bool has_pause = false, has_start = false, has_preview = false;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
@@ -264,7 +267,7 @@ void DownloadingTorrents::displayDLListMenu(const QPoint& pos) {
has_pause = true;
}
}
if(BTSession->isFilePreviewPossible(hash) && !has_preview) {
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
myDLLlistMenu.addAction(actionPreview_file);
has_preview = true;
}
@@ -414,7 +417,7 @@ void DownloadingTorrents::updateDlList() {
}else{
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));
setRowColor(row, QApplication::palette().color(QPalette::WindowText));
setRowColor(row, QPalette::WindowText);
}
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));

View File

@@ -82,7 +82,7 @@ class DownloadingTorrents : public QWidget, public Ui::downloading{
public slots:
void updateDlList();
void setInfoBar(QString info, QColor color=QApplication::palette().color(QPalette::WindowText));
void setInfoBar(QString info, QColor color=QPalette::WindowText);
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void updateRatio();

View File

@@ -250,13 +250,11 @@ void engineSelectDlg::setRowColor(int row, QString color){
bool engineSelectDlg::checkInstalled(QString plugin_name) const {
QProcess nova;
QStringList params;
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
params << "--supported_engines";
nova.start("python", params, QIODevice::ReadOnly);
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
nova.waitForStarted();
nova.waitForFinished();
QByteArray result = nova.readAll();
result = result.replace("\r", "");
result = result.replace("\n", "");
QList<QByteArray> plugins_list = result.split(',');
return plugins_list.contains(plugin_name.toUtf8());
@@ -282,13 +280,11 @@ void engineSelectDlg::loadSupportedSearchEngines(bool first) {
QStringList params;
// Ask nova core for the supported search engines
QProcess nova;
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
params << "--supported_engines";
nova.start("python", params, QIODevice::ReadOnly);
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
nova.waitForStarted();
nova.waitForFinished();
QByteArray result = nova.readAll();
result = result.replace("\r", "");
result = result.replace("\n", "");
qDebug("read: %s", result.data());
QByteArray e;
@@ -299,13 +295,11 @@ void engineSelectDlg::loadSupportedSearchEngines(bool first) {
installed_engines[en] = old_engines.value(en, true);
}
params.clear();
params << misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py";
params << "--supported_engines_infos";
nova.start("python", params, QIODevice::ReadOnly);
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
nova.waitForStarted();
nova.waitForFinished();
result = nova.readAll();
result = result.replace("\r", "");
result = result.replace("\n", "");
qDebug("read: %s", result.data());
unsigned int i = 0;

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

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