diff --git a/Changelog b/Changelog index 46aa56830..1ecb3bb3a 100644 --- a/Changelog +++ b/Changelog @@ -33,6 +33,7 @@ - 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: Search plugin update is not making the GUI freeze anymore (moved to a thread) - COSMETIC: Redesigned torrent properties a little - COSMETIC: Redesigned options a little - COSMETIC: Display more logs messages concerning features diff --git a/INSTALL b/INSTALL index 801225343..1917a344d 100644 --- a/INSTALL +++ b/INSTALL @@ -24,7 +24,7 @@ Dependencies: - libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization -- libcurl +- libcommoncpp2 - python >= 2.3 (previous might work - not tested): needed by search engine. diff --git a/README b/README index b769616c6..7860e1632 100644 --- a/README +++ b/README @@ -1,9 +1,9 @@ -qBittorrent - A BitTorrent client in Qt4.2 +qBittorrent - A BitTorrent client in Qt4 ------------------------------------------ Description: ******************************** -qBittorrent is a bittorrent client programmed in C++ / Qt4.2 that use +qBittorrent is a bittorrent client programmed in C++ / Qt4 that use libtorrent (sometimes called rb_libtorrent) by Arvid Norberg. It aims to be a good alternative to all other bittorrent clients diff --git a/TODO b/TODO index e60839a1d..c917e564d 100644 --- a/TODO +++ b/TODO @@ -18,7 +18,6 @@ // Unsure - Azureus spoofing to prevent ban from trackers? - Web interface? -- Use downloader class to download search plugin updates - Allow to set upload limit for each torrent - Option to shutdown computer when downloads are finished - Add a torrent scheduler @@ -43,7 +42,7 @@ - Allow to hide columns (gtsoul) - Complete documentation and english translation * beta2 - - Fix configure file for libcommoncpp + - Handle downloadFromUrl errors (Display a messagebox to catch user's attention) - Wait for some bug fixes in libtorrent : - upload/download limit per torrent - ipfilter crash diff --git a/configure b/configure index 9a6b35a5f..ca03fa2ed 100755 --- a/configure +++ b/configure @@ -10,20 +10,19 @@ Usage: $0 [OPTION]... This script creates necessary configuration files to build/install. Main options: - --prefix=[path] Base path for build/install. Default: /usr/local - --bindir=[path] Directory for binaries. Default: PREFIX/bin - --datadir=[path] Directory for data. Default: PREFIX/share - --qtdir=[path] Directory where Qt is installed. - --verbose Show extra configure output. - --help This help text. + --prefix=[path] Base path for build/install. Default: /usr/local + --bindir=[path] Directory for binaries. Default: PREFIX/bin + --qtdir=[path] Directory where Qt is installed. + --verbose Show extra configure output. + --help This help text. Dependency options: --with-libtorrent-inc=[path] Path to libtorrent include files --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 EOT } @@ -130,11 +129,6 @@ while [ $# -gt 0 ]; do shift ;; - --datadir=*) - DATADIR=$optarg - shift - ;; - --qtdir=*) EX_QTDIR=$optarg shift @@ -160,13 +154,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 ;; @@ -181,7 +175,6 @@ done PREFIX=${PREFIX:-/usr/local} BINDIR=${BINDIR:-$PREFIX/bin} -DATADIR=${DATADIR:-$PREFIX/share} echo "Configuring qbittorrent ..." @@ -189,14 +182,13 @@ if [ "$QC_DEBUG" = "Y" ]; then echo echo PREFIX=$PREFIX echo BINDIR=$BINDIR -echo DATADIR=$DATADIR echo EX_QTDIR=$EX_QTDIR echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC -echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC -echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB +echo QC_WITH_LIBCOMMONCPP2_INC=$QC_WITH_LIBCOMMONCPP2_INC +echo QC_WITH_LIBCOMMONCPP2_LIB=$QC_WITH_LIBCOMMONCPP2_LIB echo fi @@ -417,65 +409,68 @@ public: return true; } }; -#line 1 "libcurl.qcm" +#line 1 "libcommoncpp2.qcm" /* -----BEGIN QCMOD----- -name: libcurl -arg: with-libcurl-inc=[path], Path to libcurl include files -arg: with-libcurl-lib=[path], Path to libcurl library files +name: libcommoncpp2 +arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files +arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files -----END QCMOD----- */ -class qc_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++"; } + QString shortname() const { return "libcommoncpp2"; } bool exec(){ - QString s; - s = conf->getenv("QC_WITH_LIBCURL_INC"); + QString s; + s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC"); if(!s.isEmpty()) { - if(!conf->checkHeader(s, "curl/curl.h")) { + if(!conf->checkHeader(s, "cc++/common.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")){ + if(conf->checkHeader(s, "cc++/common.h")){ found = true; break; } } if(!found) { return false; - } + } } conf->addIncludePath(s); - s = conf->getenv("QC_WITH_LIBCURL_LIB"); + s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB"); if(!s.isEmpty()) { - if(!conf->checkLibrary(s, "curl")) { - return false; - } - conf->addLib(QString("-L") + s); + if(!QFile::exists(s+QString("libccext2.so"))) + return false; + if(!QFile::exists(s+QString("libccgnu2.so"))) + return false; + conf->addLib(QString("-L") + s); }else{ QStringList sl; sl << "/usr/lib/"; sl << "/usr/local/lib/"; bool found = false; foreach(s, sl){ - if(conf->checkLibrary(s, "curl")){ - found = true; - break; + if(QFile::exists(s+QString("libccext2.so"))){ + if(QFile::exists(s+QString("libccgnu2.so"))){ + found = true; + break; + } } } if(!found) return false; conf->addLib(QString("-L") + s); } - conf->addLib("-lcurl"); + conf->addLib("-lccext2 -lccgnu2"); return true; } }; @@ -511,7 +506,7 @@ cat >$1/modules_new.cpp <required = true; o->disabled = false; - o = new qc_libcurl(conf); + o = new qc_libcommoncpp2(conf); o->required = true; o->disabled = false; o = new qc_python(conf); @@ -1441,14 +1436,13 @@ EOT export PREFIX export BINDIR -export DATADIR export EX_QTDIR export QC_WITH_LIBTORRENT_INC export QC_WITH_LIBTORRENT_LIB export QC_WITH_LIBTORRENT_STATIC_LIB export QC_WITH_LIBBOOST_INC -export QC_WITH_LIBCURL_INC -export QC_WITH_LIBCURL_LIB +export QC_WITH_LIBCOMMONCPP2_INC +export QC_WITH_LIBCOMMONCPP2_LIB export QC_DEBUG rm -rf .qconftemp ( diff --git a/qbittorrent.qc b/qbittorrent.qc index fa50072f1..c418b834a 100644 --- a/qbittorrent.qc +++ b/qbittorrent.qc @@ -11,7 +11,7 @@ - + diff --git a/qcm/libcommoncpp2.qcm b/qcm/libcommoncpp2.qcm new file mode 100644 index 000000000..23408efa2 --- /dev/null +++ b/qcm/libcommoncpp2.qcm @@ -0,0 +1,64 @@ +/* +-----BEGIN QCMOD----- +name: libcommoncpp2 +arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files +arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files +-----END QCMOD----- +*/ +class qc_libcommoncpp2 : public ConfObj +{ +public: + qc_libcommoncpp2(Conf *c) : ConfObj(c) {} + QString name() const { return "GNU Common C++"; } + QString shortname() const { return "libcommoncpp2"; } + bool exec(){ + QString s; + s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC"); + if(!s.isEmpty()) { + if(!conf->checkHeader(s, "cc++/common.h")) { + return false; + } + }else{ + QStringList sl; + sl << "/usr/include"; + sl << "/usr/local/include"; + bool found = false; + foreach(s, sl){ + if(conf->checkHeader(s, "cc++/common.h")){ + found = true; + break; + } + } + if(!found) { + return false; + } + } + conf->addIncludePath(s); + + s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB"); + if(!s.isEmpty()) { + if(!QFile::exists(s+QString("libccext2.so"))) + return false; + if(!QFile::exists(s+QString("libccgnu2.so"))) + return false; + conf->addLib(QString("-L") + s); + }else{ + QStringList sl; + sl << "/usr/lib/"; + sl << "/usr/local/lib/"; + bool found = false; + foreach(s, sl){ + if(QFile::exists(s+QString("libccext2.so"))){ + if(QFile::exists(s+QString("libccgnu2.so"))){ + found = true; + break; + } + } + } + if(!found) return false; + conf->addLib(QString("-L") + s); + } + conf->addLib("-lccext2 -lccgnu2"); + return true; + } +}; diff --git a/qcm/libcurl.qcm b/qcm/libcurl.qcm deleted file mode 100644 index f5577eed1..000000000 --- a/qcm/libcurl.qcm +++ /dev/null @@ -1,61 +0,0 @@ -/* ------BEGIN QCMOD----- -name: libcurl -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(!conf->checkLibrary(s, "curl")) { - return false; - } - conf->addLib(QString("-L") + s); - }else{ - QStringList sl; - sl << "/usr/lib/"; - sl << "/usr/local/lib/"; - bool found = false; - foreach(s, sl){ - if(conf->checkLibrary(s, "curl")){ - found = true; - break; - } - } - if(!found) return false; - conf->addLib(QString("-L") + s); - } - conf->addLib("-lcurl"); - return true; - } -}; diff --git a/src/misc.h b/src/misc.h index cf973a05e..3a2cc38ed 100644 --- a/src/misc.h +++ b/src/misc.h @@ -128,11 +128,6 @@ class misc : public QObject{ return true; } - // Function called by curl to write the data to the file - static int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream){ - return fwrite(buffer, size, nmemb, (FILE*)stream); - } - static QString findFileInDir(const QString& dir_path, const QString& fileName){ QDir dir(dir_path); if(dir.exists(fileName)){ diff --git a/src/rss.h b/src/rss.h index ef4d92806..df8dd508b 100644 --- a/src/rss.h +++ b/src/rss.h @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/src/searchEngine.cpp b/src/searchEngine.cpp index 705f6ad34..9d09284c5 100644 --- a/src/searchEngine.cpp +++ b/src/searchEngine.cpp @@ -27,12 +27,12 @@ #include #include #include -#include #include #include "SearchListDelegate.h" #include "searchEngine.h" #include "bittorrent.h" +#include "downloadThread.h" #define SEARCH_NAME 0 #define SEARCH_SIZE 1 @@ -46,6 +46,8 @@ SearchEngine::SearchEngine(bittorrent *BTSession, QSystemTrayIcon *myTrayIcon, b setupUi(this); this->BTSession = BTSession; this->myTrayIcon = myTrayIcon; + downloader = new downloadThread(this); + connect(downloader, SIGNAL(downloadFinished(const QString&, const QString&)), this, SLOT(novaUpdateDownloaded(const QString&, const QString&))); // Set Search results list model SearchListModel = new QStandardItemModel(0,5); SearchListModel->setHeaderData(SEARCH_NAME, Qt::Horizontal, tr("Name", "i.e: file name")); @@ -110,6 +112,7 @@ SearchEngine::~SearchEngine(){ delete searchCompleter; delete SearchListModel; delete SearchDelegate; + delete downloader; } // Set the color of a row in data model @@ -428,98 +431,45 @@ void SearchEngine::updateNova() const{ } } -// Download nova.py from qbittorrent.org -// Check if our nova.py is outdated and -// ask user for action. -void SearchEngine::on_update_nova_button_clicked(){ - CURL *curl; - QString filePath; - qDebug("Checking for search plugin updates on qbittorrent.org"); - // XXX: Trick to get a unique filename - QTemporaryFile *tmpfile = new QTemporaryFile; - if (tmpfile->open()) { - filePath = tmpfile->fileName(); - } - delete tmpfile; - FILE *file = fopen((const char*)filePath.toUtf8(), "w"); - if(!file){ - std::cerr << "Error: could not open temporary file...\n"; - } - // Initilization required by libcurl - curl = curl_easy_init(); - if(!curl){ - std::cerr << "Error: Failed to init curl...\n"; - fclose(file); - return; - } - // Set url to download - curl_easy_setopt(curl, CURLOPT_URL, "http://www.dchris.eu/nova/nova.zip"); - // Define our callback to get called when there's data to be written - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, misc::my_fwrite); - // Set destination file - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); - // Some SSL mambo jambo - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - // Perform Download - curl_easy_perform(curl); /* ignores error */ - // Cleanup - curl_easy_cleanup(curl); - // Close tmp file - fclose(file); - qDebug("Version on qbittorrent.org: %.2f", getNovaVersion(filePath)); +void SearchEngine::novaUpdateDownloaded(const QString&, const QString& filePath){ float version_on_server = getNovaVersion(filePath); - if(version_on_server == 0.0){ - //First server is down, try the mirror - QFile::remove(filePath); - FILE *file = fopen((const char*)filePath.toUtf8(), "w"); - if(!file){ - std::cerr << "Error: could not open temporary file...\n"; - } - curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_URL, "http://hydr0g3n.free.fr/nova/nova.py"); - // Define our callback to get called when there's data to be written - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, misc::my_fwrite); - // Set destination file - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); - // Some SSL mambo jambo - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - // Perform Download - curl_easy_perform(curl); /* ignores error */ - // Cleanup - curl_easy_cleanup(curl); - // Close tmp file - fclose(file); - version_on_server = getNovaVersion(filePath); - } + qDebug("Version on qbittorrent.org: %.2f", version_on_server); if(version_on_server > getNovaVersion(misc::qBittorrentPath()+"nova.py")){ if(QMessageBox::question(this, - tr("Search plugin update -- qBittorrent"), - tr("Search plugin can be updated, do you want to update it?\n\nChangelog:\n")+getNovaChangelog(filePath), - tr("&Yes"), tr("&No"), - QString(), 0, 1)){ - return; - }else{ - qDebug("Updating search plugin from qbittorrent.org"); - QFile::remove(misc::qBittorrentPath()+"nova.py"); - QFile::copy(filePath, misc::qBittorrentPath()+"nova.py"); - QFile::Permissions perm=QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser | QFile::ReadGroup | QFile::ReadGroup; - QFile(misc::qBittorrentPath()+"nova.py").setPermissions(perm); - } + tr("Search plugin update -- qBittorrent"), + tr("Search plugin can be updated, do you want to update it?\n\nChangelog:\n")+getNovaChangelog(filePath), + tr("&Yes"), tr("&No"), + QString(), 0, 1)){ + return; + }else{ + qDebug("Updating search plugin from qbittorrent.org"); + QFile::remove(misc::qBittorrentPath()+"nova.py"); + QFile::copy(filePath, misc::qBittorrentPath()+"nova.py"); + QFile::Permissions perm=QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser | QFile::ReadGroup | QFile::ReadGroup; + QFile(misc::qBittorrentPath()+"nova.py").setPermissions(perm); + } }else{ if(version_on_server == 0.0){ QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable.")); }else{ QMessageBox::information(this, tr("Search plugin update -- qBittorrent"), - tr("Your search plugin is already up to date.")); + tr("Your search plugin is already up to date.")); } } // Delete tmp file QFile::remove(filePath); } +// Download nova.py from qbittorrent.org +// Check if our nova.py is outdated and +// ask user for action. +void SearchEngine::on_update_nova_button_clicked(){ + qDebug("Checking for search plugin updates on qbittorrent.org"); + downloader->downloadUrl("http://www.dchris.eu/nova/nova.zip"); + //TODO: make use of fallback url: "http://hydr0g3n.free.fr/nova/nova.py" +} + // Slot called when search is Finished // Search can be finished for 3 reasons : // Error | Stopped by user | Finished normally diff --git a/src/searchEngine.h b/src/searchEngine.h index a2f9dd592..db1beb241 100644 --- a/src/searchEngine.h +++ b/src/searchEngine.h @@ -31,6 +31,7 @@ class QStandardItemModel; class SearchListDelegate; class bittorrent; class QSystemTrayIcon; +class downloadThread; class SearchEngine : public QWidget, public Ui::search_engine{ Q_OBJECT @@ -50,6 +51,7 @@ class SearchEngine : public QWidget, public Ui::search_engine{ bittorrent *BTSession; QSystemTrayIcon *myTrayIcon; bool systrayIntegration; + downloadThread *downloader; public: SearchEngine(bittorrent *BTSession, QSystemTrayIcon *myTrayIcon, bool systrayIntegration); @@ -80,6 +82,7 @@ class SearchEngine : public QWidget, public Ui::search_engine{ void sortSearchList(int index); void sortSearchListInt(int index, Qt::SortOrder sortOrder); void sortSearchListString(int index, Qt::SortOrder sortOrder); + void novaUpdateDownloaded(const QString& url, const QString& path); }; #endif diff --git a/src/src.pro b/src/src.pro index 94652f6c4..e77f92b4d 100644 --- a/src/src.pro +++ b/src/src.pro @@ -2,9 +2,6 @@ LANG_PATH = lang ICONS_PATH = Icons -LIBS += -lccext2 -LIBS += -lccgnu2 - #Set the following variable to 1 to enable debug DEBUG_MODE = 1 @@ -30,7 +27,7 @@ contains(DEBUG_MODE, 0){ QMAKE_CXXFLAGS_RELEASE += -fwrapv QMAKE_CXXFLAGS_DEBUG += -fwrapv -#LIBS += -lcurl -lupnp + CONFIG += link_pkgconfig PKGCONFIG += libtorrent QT += network xml @@ -78,7 +75,7 @@ contains(DEBUG_MODE, 0){ # Windows win32 { DEFINES += NO_UPNP - LIBS += -lcurl -ltorrent + LIBS += -ltorrent -lccext2 -lccgnu2 } RESOURCES = icons.qrc \