diff --git a/AUTHORS b/AUTHORS index 1beb3550d..df11b15b7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,6 +6,7 @@ Contributors: * Ishan Arora * Arnaud Demaizière * Grigis Gaëtan +* Frédéric Lassabe Code from other projects: * files src/ico.cpp src/ico.h diff --git a/configure b/configure index 698423dff..8b0a95f1c 100755 --- a/configure +++ b/configure @@ -18,6 +18,8 @@ Main options: --help This help text. Dependency options: + --disable-gui Disable qBittorrent Graphical user + interface for headless running --with-libboost-inc=[path] Path to libboost include files --disable-libnotify Disable use of libnotify --disable-geoip-database Disable use of geoip-database @@ -140,6 +142,11 @@ while [ $# -gt 0 ]; do shift ;; + --disable-gui) + QC_DISABLE_GUI="Y" + shift + ;; + --with-libboost-inc=*) QC_WITH_LIBBOOST_INC=$optarg shift @@ -181,6 +188,7 @@ echo PREFIX=$PREFIX echo BINDIR=$BINDIR echo DATADIR=$DATADIR echo EX_QTDIR=$EX_QTDIR +echo QC_DISABLE_GUI=$QC_DISABLE_GUI echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC echo QC_DISABLE_libnotify=$QC_DISABLE_libnotify echo QC_DISABLE_geoip_database=$QC_DISABLE_geoip_database @@ -290,6 +298,7 @@ cat >$1/modules.cpp <= 4.4 +arg: disable-gui, Disable qBittorrent Graphical user interface for headless running -----END QCMOD----- */ class qc_qt4 : public ConfObj @@ -300,6 +309,9 @@ public: QString shortname() const { return "Qt 4.4"; } bool exec() { + if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) { + conf->addDefine("DISABLE_GUI"); + } if(QT_VERSION >= 0x040500) { conf->addDefine("QT_4_5"); } @@ -410,6 +422,10 @@ public: QString name() const { return "libnotify >= 0.4.2 (optional)"; } QString shortname() const { return "libnotify"; } bool exec(){ + if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) { + printf("\nNot Required"); + return true; + } QStringList incs; QString req_ver = "0.4.2"; QString version, libs, other; @@ -453,6 +469,10 @@ public: QString name() const { return "GeoIP Database (optional)"; } QString shortname() const { return "GeoIP Database"; } bool exec() { + if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) { + printf("\nNot Required"); + return true; + } #ifdef Q_WS_X11 if(!conf->getenv("QC_WITH_GEOIP_DATABASE_EMBEDDED").isEmpty()) { #endif @@ -1431,6 +1451,7 @@ export PREFIX export BINDIR export DATADIR export EX_QTDIR +export QC_DISABLE_GUI export QC_WITH_LIBBOOST_INC export QC_DISABLE_libnotify export QC_DISABLE_geoip_database diff --git a/qcm/geoip-database.qcm b/qcm/geoip-database.qcm index f5fb0854d..9c21afdba 100644 --- a/qcm/geoip-database.qcm +++ b/qcm/geoip-database.qcm @@ -12,6 +12,10 @@ public: QString name() const { return "GeoIP Database (optional)"; } QString shortname() const { return "GeoIP Database"; } bool exec() { + if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) { + printf("\nNot Required"); + return true; + } #ifdef Q_WS_X11 if(!conf->getenv("QC_WITH_GEOIP_DATABASE_EMBEDDED").isEmpty()) { #endif diff --git a/qcm/libnotify.qcm b/qcm/libnotify.qcm index cc55aa4b2..415c80133 100644 --- a/qcm/libnotify.qcm +++ b/qcm/libnotify.qcm @@ -11,6 +11,10 @@ public: QString name() const { return "libnotify >= 0.4.2 (optional)"; } QString shortname() const { return "libnotify"; } bool exec(){ + if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) { + printf("\nNot Required"); + return true; + } QStringList incs; QString req_ver = "0.4.2"; QString version, libs, other; diff --git a/qcm/qt4.qcm b/qcm/qt4.qcm index 5866ebe5a..59b564275 100644 --- a/qcm/qt4.qcm +++ b/qcm/qt4.qcm @@ -1,6 +1,7 @@ /* -----BEGIN QCMOD----- name: Qt >= 4.4 +arg: disable-gui, Disable qBittorrent Graphical user interface for headless running -----END QCMOD----- */ class qc_qt4 : public ConfObj @@ -11,6 +12,9 @@ public: QString shortname() const { return "Qt 4.4"; } bool exec() { + if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) { + conf->addDefine("DISABLE_GUI"); + } if(QT_VERSION >= 0x040500) { conf->addDefine("QT_4_5"); } diff --git a/src/bittorrent.cpp b/src/bittorrent.cpp index d93e7d010..1e8f8c264 100644 --- a/src/bittorrent.cpp +++ b/src/bittorrent.cpp @@ -41,7 +41,9 @@ #include "downloadthread.h" #include "filterparserthread.h" #include "preferences.h" -#include "geoip.h" +#ifndef DISABLE_GUI + #include "geoip.h" +#endif #include "torrentpersistentdata.h" #include "httpserver.h" #include @@ -65,8 +67,11 @@ enum ProxyType {HTTP=1, SOCKS5=2, HTTP_PW=3, SOCKS5_PW=4, SOCKS4=5}; enum VersionType { NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL }; // Main constructor -Bittorrent::Bittorrent() : preAllocateAll(false), addInPause(false), ratio_limit(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), DHTEnabled(false), current_dht_port(0), queueingEnabled(false), geoipDBLoaded(false), exiting(false) { +Bittorrent::Bittorrent() : preAllocateAll(false), addInPause(false), ratio_limit(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), DHTEnabled(false), current_dht_port(0), queueingEnabled(false), exiting(false) { +#ifndef DISABLE_GUI + geoipDBLoaded = false; resolve_countries = false; +#endif // To avoid some exceptions fs::path::default_name_check(fs::no_check); // For backward compatibility @@ -299,6 +304,7 @@ void Bittorrent::configureSession() { // Enabled setUploadRateLimit(up_limit*1024); } +#ifndef DISABLE_GUI // Resolve countries qDebug("Loading country resolution settings"); bool new_resolv_countries = Preferences::resolvePeerCountries(); @@ -319,6 +325,7 @@ void Bittorrent::configureSession() { h.resolve_countries(resolve_countries); } } +#endif // * UPnP if(Preferences::isUPnPEnabled()) { enableUPnP(true); @@ -553,7 +560,7 @@ bool Bittorrent::initWebUi(QString username, QString password, int port) { if (success) addConsoleMessage(tr("The Web UI is listening on port %1").arg(port)); else - addConsoleMessage(tr("Web User Interface Error - Unable to bind Web UI to port %1").arg(port), QColor("red")); + addConsoleMessage(tr("Web User Interface Error - Unable to bind Web UI to port %1").arg(port), "red"); } return success; } @@ -788,8 +795,10 @@ QTorrentHandle Bittorrent::addMagnetUri(QString magnet_uri, bool resumed) { h.set_max_connections(Preferences::getMaxConnecsPerTorrent()); // Uploads limit per torrent h.set_max_uploads(Preferences::getMaxUploadsPerTorrent()); +#ifndef DISABLE_GUI // Resolve countries h.resolve_countries(resolve_countries); +#endif // Load filtered files if(!resumed) { // Sequential download @@ -955,9 +964,11 @@ QTorrentHandle Bittorrent::addTorrent(QString path, bool fromScanDir, QString fr h.set_max_connections(Preferences::getMaxConnecsPerTorrent()); // Uploads limit per torrent h.set_max_uploads(Preferences::getMaxUploadsPerTorrent()); +#ifndef DISABLE_GUI // Resolve countries qDebug("AddTorrent: Resolve_countries: %d", (int)resolve_countries); h.resolve_countries(resolve_countries); +#endif if(!resumed) { // Sequential download if(TorrentTempData::hasTempData(hash)) { @@ -1254,11 +1265,16 @@ QStringList Bittorrent::getPeerBanMessages() const { return peerBanMessages; } +#ifdef DISABLE_GUI +void Bittorrent::addConsoleMessage(QString msg, QString) { +#else void Bittorrent::addConsoleMessage(QString msg, QColor color) { if(consoleMessages.size() > 100) { consoleMessages.removeFirst(); } consoleMessages.append(QString::fromUtf8("")+ QDateTime::currentDateTime().toString(QString::fromUtf8("dd/MM/yyyy hh:mm:ss")) + QString::fromUtf8(" - ") + msg + QString::fromUtf8("")); +#endif + emit newConsoleMessage(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss") + " - " + msg); } void Bittorrent::addPeerBanMessage(QString ip, bool from_ipfilter) { @@ -1782,12 +1798,12 @@ void Bittorrent::readAlerts() { } } else if (portmap_error_alert* p = dynamic_cast(a.get())) { - addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(QString(p->message().c_str())), QColor("red")); + addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(QString(p->message().c_str())), "red"); //emit UPnPError(QString(p->msg().c_str())); } else if (portmap_alert* p = dynamic_cast(a.get())) { qDebug("UPnP Success, msg: %s", p->message().c_str()); - addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(QString(p->message().c_str())), QColor("blue")); + addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(QString(p->message().c_str())), "blue"); //emit UPnPSuccess(QString(p->msg().c_str())); } else if (peer_blocked_alert* p = dynamic_cast(a.get())) { @@ -1895,7 +1911,11 @@ QString Bittorrent::getSavePath(QString hash) { // download the torrent file to a tmp location, then // add it to download list void Bittorrent::downloadFromUrl(QString url) { - addConsoleMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(url), QPalette::WindowText); + addConsoleMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(url) +#ifndef DISABLE_GUI + , QPalette::WindowText +#endif + ); //emit aboutToDownloadFromUrl(url); // Launch downloader thread downloader->downloadUrl(url); diff --git a/src/bittorrent.h b/src/bittorrent.h index 7a7aa33ff..d2f877e94 100644 --- a/src/bittorrent.h +++ b/src/bittorrent.h @@ -34,8 +34,12 @@ #include #include #include -#include -#include +#ifdef DISABLE_GUI + #include +#else + #include + #include +#endif #include #include @@ -117,8 +121,10 @@ private: QString defaultSavePath; QString defaultTempPath; // GeoIP +#ifndef DISABLE_GUI bool resolve_countries; bool geoipDBLoaded; +#endif // ETA Computation QPointer timerETA; QHash > ETA_samples; @@ -219,7 +225,11 @@ public slots: void enableNATPMP(bool b); void enableLSD(bool b); bool enableDHT(bool b); +#ifdef DISABLE_GUI + void addConsoleMessage(QString msg, QString color=QString::null); +#else void addConsoleMessage(QString msg, QColor color=QApplication::palette().color(QPalette::WindowText)); +#endif void addPeerBanMessage(QString msg, bool from_ipfilter); void processDownloadedFile(QString, QString); void addMagnetSkipAddDlg(QString uri); @@ -248,6 +258,7 @@ signals: void torrentFinishedChecking(QTorrentHandle& h); void metadataReceived(QTorrentHandle &h); void savePathChanged(QTorrentHandle &h); + void newConsoleMessage(QString msg); }; #endif diff --git a/src/eventmanager.cpp b/src/eventmanager.cpp index f4172d1ef..8ea52e1b2 100644 --- a/src/eventmanager.cpp +++ b/src/eventmanager.cpp @@ -33,7 +33,7 @@ #include "bittorrent.h" #include "misc.h" #include "preferences.h" -#include "proplistdelegate.h" +//#include "proplistdelegate.h" #include "torrentpersistentdata.h" #include diff --git a/src/filterparserthread.h b/src/filterparserthread.h index 3e514ffe9..e146d5197 100644 --- a/src/filterparserthread.h +++ b/src/filterparserthread.h @@ -34,7 +34,8 @@ #include #include #include -#include +#include +#include #include #include @@ -103,7 +104,7 @@ class FilterParserThread : public QThread { QFile file(filePath); if (file.exists()){ if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ - QMessageBox::critical(0, tr("I/O Error", "Input/Output Error"), tr("Couldn't open %1 in read mode.").arg(filePath)); + std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; return; } unsigned int nbLine = 0; @@ -224,7 +225,7 @@ class FilterParserThread : public QThread { QStringList IP; if (file.exists()){ if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ - QMessageBox::critical(0, tr("I/O Error", "Input/Output Error"), tr("Couldn't open %1 in read mode.").arg(filePath)); + std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; return; } unsigned int nbLine = 0; @@ -292,7 +293,7 @@ class FilterParserThread : public QThread { QFile file(filePath); if (file.exists()){ if(!file.open(QIODevice::ReadOnly)){ - QMessageBox::critical(0, tr("I/O Error", "Input/Output Error"), tr("Couldn't open %1 in read mode.").arg(filePath)); + std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; return; } QDataStream stream(&file); @@ -304,7 +305,7 @@ class FilterParserThread : public QThread { memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) || !stream.readRawData((char*)&version, sizeof(version)) ) { - QMessageBox::critical(0, tr("I/O Error", "Input/Output Error"), tr("%1 is not a valid PeerGuardian P2B file.").arg(filePath)); + std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; return; } @@ -318,7 +319,7 @@ class FilterParserThread : public QThread { !stream.readRawData((char*)&start, sizeof(start)) || !stream.readRawData((char*)&end, sizeof(end)) ) { - QMessageBox::critical(0, tr("I/O Error", "Input/Output Error"), tr("%1 is not a valid PeerGuardian P2B file.").arg(filePath)); + std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; return; } // Network byte order to Host byte order @@ -334,7 +335,7 @@ class FilterParserThread : public QThread { qDebug ("p2b version 3"); unsigned int namecount; if(!stream.readRawData((char*)&namecount, sizeof(namecount))) { - QMessageBox::critical(0, tr("I/O Error", "Input/Output Error"), tr("%1 is not a valid PeerGuardian P2B file.").arg(filePath)); + std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; return; } namecount=ntohl(namecount); @@ -342,7 +343,7 @@ class FilterParserThread : public QThread { for(unsigned int i=0; i +#include +#include +#include +#include "preferences.h" +#include "bittorrent.h" + +class HeadlessLoader: QObject { + Q_OBJECT + + private: + QLocalServer *localServer; + Bittorrent *BTSession; + + public: + HeadlessLoader(QStringList torrentCmdLine) { + // Enable Web UI + Preferences::setWebUiEnabled(true); + // Instanciate Bittorrent Object + BTSession = new Bittorrent(); + connect(BTSession, SIGNAL(newConsoleMessage(QString)), this, SLOT(displayConsoleMessage(QString))); + // Resume unfinished torrents + BTSession->startUpTorrents(); + // Process command line parameters + processParams(torrentCmdLine); + // Use a tcp server to allow only one instance of qBittorrent + localServer = new QLocalServer(); + QString uid = QString::number(getuid()); +#ifdef Q_WS_X11 + if(QFile::exists(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid)) { + // Socket was not closed cleanly + std::cerr << "Warning: Local domain socket was not closed cleanly, deleting file...\n"; + QFile::remove(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid); + } +#endif + if (!localServer->listen("qBittorrent-"+uid)) { + std::cerr << "Couldn't create socket, single instance mode won't work...\n"; + } + connect(localServer, SIGNAL(newConnection()), this, SLOT(acceptConnection())); + // Display some information to the user + std::cout << std::endl << "******** " << tr("Information").toStdString() << " ********" << std::endl; + std::cout << tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(Preferences::getWebUiPort())).toStdString() << std::endl; + std::cout << tr("The Web UI administrator user name is: %1").arg(Preferences::getWebUiUsername()).toStdString() << std::endl; + if(Preferences::getWebUiPassword() == "f6fdffe48c908deb0f4c3bd36c032e72") { + std::cout << tr("The Web UI administrator password is still the default one: %1").arg("adminadmin").toStdString() << std::endl; + std::cout << tr("This is a security risk, please consider changing your password from program preferences").toStdString() << std::endl; + } + } + + ~HeadlessLoader() { + delete BTSession; + } + + public slots: + // Call this function to exit qBittorrent headless loader + // and return to prompt (object will be deleted by main) + void exit() { + qApp->quit(); + } + + void displayConsoleMessage(QString msg) { + std::cout << msg.toLocal8Bit().data() << std::endl; + } + + // As program parameters, we can get paths or urls. + // This function parse the parameters and call + // the right addTorrent function, considering + // the parameter type. + void processParams(const QStringList& params) { + foreach(QString param, params) { + param = param.trimmed(); + if(param.startsWith("--")) continue; + if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) { + BTSession->downloadFromUrl(param); + }else{ + if(param.startsWith("magnet:", Qt::CaseInsensitive)) { + BTSession->addMagnetUri(param); + } else { + BTSession->addTorrent(param); + } + } + } + } + + void acceptConnection() { + QLocalSocket *clientConnection = localServer->nextPendingConnection(); + connect(clientConnection, SIGNAL(disconnected()), this, SLOT(readParamsOnSocket())); + qDebug("accepted connection from another instance"); + } + + void readParamsOnSocket() { + QLocalSocket *clientConnection = static_cast(sender()); + if(clientConnection) { + QByteArray params = clientConnection->readAll(); + if(!params.isEmpty()) { + processParams(QString::fromUtf8(params.data()).split(QString::fromUtf8("\n"))); + qDebug("Received parameters from another instance"); + } + clientConnection->deleteLater(); + } + } + +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index e3f262515..c84295ad3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,25 +28,34 @@ * Contact : chris@qbittorrent.org */ -#include #include #include #include -#include + +#ifndef DISABLE_GUI + #include + #include + #include + #include "qgnomelook.h" + #include + #include + #ifdef Q_WS_WIN + #include + #endif + #ifdef Q_WS_MAC + #include + #endif + #include "GUI.h" + #include "ico.h" +#else + #include + #include "headlessloader.h" +#endif + #include #include #include #include -#include -#include "qgnomelook.h" -#include -#include -#ifdef Q_WS_WIN -#include -#endif -#ifdef Q_WS_MAC -#include -#endif #ifndef Q_WS_WIN #include #include @@ -54,12 +63,14 @@ #endif #include -#include "GUI.h" #include "misc.h" #include "preferences.h" -#include "ico.h" -QApplication *app; +#ifdef DISABLE_GUI + QCoreApplication *app; +#else + QApplication *app; +#endif #ifndef Q_WS_WIN void sigtermHandler(int) { @@ -82,6 +93,7 @@ void sigabrtHandler(int) { } #endif +#ifndef DISABLE_GUI void useStyle(QApplication *app, int style){ switch(style) { case 1: @@ -114,13 +126,16 @@ void useStyle(QApplication *app, int style){ } } } +#endif // Main int main(int argc, char *argv[]){ QFile file; QString locale; QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); +#ifndef DISABLE_GUI bool no_splash = false; +#endif if(argc > 1){ if(QString::fromUtf8(argv[1]) == QString::fromUtf8("--version")){ std::cout << "qBittorrent " << VERSION << '\n'; @@ -129,16 +144,21 @@ int main(int argc, char *argv[]){ if(QString::fromUtf8(argv[1]) == QString::fromUtf8("--help")){ std::cout << "Usage: \n"; std::cout << '\t' << argv[0] << " --version : displays program version\n"; +#ifndef DISABLE_GUI std::cout << '\t' << argv[0] << " --no-splash : disable splash screen\n"; +#endif std::cout << '\t' << argv[0] << " --help : displays this help message\n"; std::cout << '\t' << argv[0] << " --webui-port=x : changes the webui port (default: 8080)\n"; std::cout << '\t' << argv[0] << " [files or urls] : starts program and download given parameters (optional)\n"; return 0; } + for(int i=1; isetStyleSheet("QStatusBar::item { border-width: 0; }"); QSplashScreen *splash = 0; @@ -195,6 +225,7 @@ int main(int argc, char *argv[]){ splash = new QSplashScreen(QPixmap(QString::fromUtf8(":/Icons/skin/splash.png"))); splash->show(); } +#endif // Open options file to read locale locale = settings.value(QString::fromUtf8("Preferences/General/Locale"), QString()).toString(); QTranslator translator; @@ -209,24 +240,36 @@ int main(int argc, char *argv[]){ } app->installTranslator(&translator); app->setApplicationName(QString::fromUtf8("qBittorrent")); +#ifndef DISABLE_GUI app->setQuitOnLastWindowClosed(false); +#endif #ifndef Q_WS_WIN signal(SIGABRT, sigabrtHandler); signal(SIGTERM, sigtermHandler); + signal(SIGINT, sigtermHandler); signal(SIGSEGV, sigsegvHandler); #endif // Read torrents given on command line QStringList torrentCmdLine = app->arguments(); // Remove first argument (program name) torrentCmdLine.removeFirst(); +#ifndef DISABLE_GUI GUI *window = new GUI(0, torrentCmdLine); if(!no_splash) { splash->finish(window); delete splash; } +#else + // Load Headless class + HeadlessLoader *loader = new HeadlessLoader(torrentCmdLine); +#endif int ret = app->exec(); +#ifndef DISABLE_GUI delete window; qDebug("GUI was deleted!"); +#else + delete loader; +#endif qDebug("Deleting app..."); delete app; qDebug("App was deleted! All good."); diff --git a/src/misc.h b/src/misc.h index 8cb785edb..15b141829 100644 --- a/src/misc.h +++ b/src/misc.h @@ -43,10 +43,24 @@ #include #include #include -#include #include #include +#ifdef DISABLE_GUI + #include +#else + #include +#endif + +#ifdef Q_WS_WIN +#include +#endif + +#ifdef Q_WS_MAC +#include +#include +#endif + #ifndef Q_WS_WIN #ifdef Q_WS_MAC #include @@ -168,8 +182,72 @@ public: } } +#ifdef Q_WS_MAC +static QString getFullPath(const FSRef &ref) +{ + QByteArray ba(2048, 0); + if (FSRefMakePath(&ref, reinterpret_cast(ba.data()), ba.size()) == noErr) + return QString::fromUtf8(ba).normalized(QString::NormalizationForm_C); + return QString(); +} +#endif + +static QString QDesktopServicesDataLocation() { +#ifdef Q_WS_WIN +#if defined Q_WS_WINCE + if (SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE)) +#else + if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE)) +#endif + result = QString::fromWCharArray(path); + if (!QCoreApplication::applicationName().isEmpty()) + result = result + QLatin1String("\\") + qApp->applicationName(); +#else +#ifdef Q_WS_MAC + // http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html + FSRef ref; + OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref); + if (err) + return QString(); + QString path = getFullPath(ref); + path += QLatin1Char('/') + qApp->applicationName(); + return path; +#else + QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME")); + if (xdgDataHome.isEmpty()) + xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); + xdgDataHome += QLatin1String("/data/") + + qApp->applicationName(); + return xdgDataHome; +#endif +#endif +} + +static QString QDesktopServicesCacheLocation() { +#ifdef Q_WS_WIN + return QDesktopServicesDataLocation() + QLatin1String("\\cache"); +#else +#ifdef Q_WS_MAC + // http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html + FSRef ref; + OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref); + if (err) + return QString(); + QString path = getFullPath(ref); + path += QLatin1Char('/') + qApp->applicationName(); + return path; +#else + QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME")); + if (xdgCacheHome.isEmpty()) + xdgCacheHome = QDir::homePath() + QLatin1String("/.cache"); + xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName(); + return xdgCacheHome; +#endif +#endif +} + static QString searchEngineLocation() { - QString location = QDir::cleanPath(QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QString location = QDir::cleanPath(QDesktopServicesDataLocation() + QDir::separator() + "search_engine"); QDir locationDir(location); if(!locationDir.exists()) @@ -178,7 +256,7 @@ public: } static QString BTBackupLocation() { - QString location = QDir::cleanPath(QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QString location = QDir::cleanPath(QDesktopServicesDataLocation() + QDir::separator() + "BT_backup"); QDir locationDir(location); if(!locationDir.exists()) @@ -187,7 +265,7 @@ public: } static QString cacheLocation() { - QString location = QDir::cleanPath(QDesktopServices::storageLocation(QDesktopServices::CacheLocation)); + QString location = QDir::cleanPath(QDesktopServicesCacheLocation()); QDir locationDir(location); if(!locationDir.exists()) locationDir.mkpath(locationDir.absolutePath()); diff --git a/src/preferences.h b/src/preferences.h index 39534f2ef..76fb43e73 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -676,6 +676,11 @@ public: return settings.value("Preferences/WebUI/Enabled", false).toBool(); } + static void setWebUiEnabled(bool enabled) { + QSettings settings("qBittorrent", "qBittorrent"); + settings.setValue("Preferences/WebUI/Enabled", enabled); + } + static quint16 getWebUiPort() { QSettings settings("qBittorrent", "qBittorrent"); return settings.value("Preferences/WebUI/Port", 8080).toInt(); diff --git a/src/qtorrenthandle.cpp b/src/qtorrenthandle.cpp index dac74e39b..004f9004f 100644 --- a/src/qtorrenthandle.cpp +++ b/src/qtorrenthandle.cpp @@ -417,10 +417,12 @@ bool QTorrentHandle::is_sequential_download() const { return h.is_sequential_download(); } +#ifndef DISABLE_GUI bool QTorrentHandle::resolve_countries() const { Q_ASSERT(h.is_valid()); return h.resolve_countries(); } +#endif bool QTorrentHandle::priv() const { Q_ASSERT(h.is_valid()); @@ -547,10 +549,12 @@ void QTorrentHandle::super_seeding(bool on) const { } #endif +#ifndef DISABLE_GUI void QTorrentHandle::resolve_countries(bool r) { Q_ASSERT(h.is_valid()); h.resolve_countries(r); } +#endif void QTorrentHandle::connect_peer(libtorrent::asio::ip::tcp::endpoint const& adr, int source) const { Q_ASSERT(h.is_valid()); diff --git a/src/qtorrenthandle.h b/src/qtorrenthandle.h index 930537b61..02b52741a 100644 --- a/src/qtorrenthandle.h +++ b/src/qtorrenthandle.h @@ -121,7 +121,9 @@ class QTorrentHandle { #endif QString creation_date() const; void get_peer_info(std::vector&) const; +#ifndef DISABLE_GUI bool resolve_countries() const; +#endif bool priv() const; bool first_last_piece_first() const; @@ -152,7 +154,9 @@ class QTorrentHandle { #ifdef LIBTORRENT_0_15 void super_seeding(bool on) const; #endif +#ifndef DISABLE_GUI void resolve_countries(bool r); +#endif void connect_peer(libtorrent::asio::ip::tcp::endpoint const& adr, int source = 0) const; void set_peer_upload_limit(libtorrent::asio::ip::tcp::endpoint ip, int limit) const; void set_peer_download_limit(libtorrent::asio::ip::tcp::endpoint ip, int limit) const; diff --git a/src/src.pro b/src/src.pro index 803ddebfa..c1bd2d901 100644 --- a/src/src.pro +++ b/src/src.pro @@ -172,28 +172,10 @@ TRANSLATIONS = $$LANG_PATH/qbittorrent_fr.ts \ $$LANG_PATH/qbittorrent_sr.ts # Source code -HEADERS += GUI.h \ - misc.h \ - options_imp.h \ - about_imp.h \ - createtorrent_imp.h \ - searchlistdelegate.h \ - proplistdelegate.h \ - previewselect.h \ - previewlistdelegate.h \ - trackerlogin.h \ +HEADERS += misc.h \ downloadthread.h \ - downloadfromurldlg.h \ - torrentadditiondlg.h \ bittorrent.h \ - searchEngine.h \ - rss.h \ - rss_imp.h \ - speedlimitdlg.h \ qtorrenthandle.h \ - engineselectdlg.h \ - pluginsource.h \ - qgnomelook.h \ httpserver.h \ httpconnection.h \ httprequestparser.h \ @@ -201,70 +183,102 @@ HEADERS += GUI.h \ json.h \ eventmanager.h \ filterparserthread.h \ - trackersadditiondlg.h \ - searchtab.h \ - console_imp.h \ - ico.h \ stacktrace.h \ torrentpersistentdata.h \ - feeddownloader.h \ - feedList.h \ - supportedengines.h \ - transferlistwidget.h \ - transferlistdelegate.h \ - transferlistfilterswidget.h \ - propertieswidget.h \ - torrentfilesmodel.h \ filesystemwatcher.h \ - peerlistwidget.h \ - peerlistdelegate.h \ - reverseresolution.h \ - preferences.h \ - geoip.h \ - peeraddition.h \ - deletionconfirmationdlg.h \ - statusbar.h \ - trackerlist.h \ - downloadedpiecesbar.h \ - pieceavailabilitybar.h -FORMS += ui/mainwindow.ui \ - ui/options.ui \ - ui/about.ui \ - ui/createtorrent.ui \ - ui/preview.ui \ - ui/login.ui \ - ui/downloadfromurldlg.ui \ - ui/torrentadditiondlg.ui \ - ui/search.ui \ - ui/rss.ui \ - ui/bandwidth_limit.ui \ - ui/engineselect.ui \ - ui/pluginsource.ui \ - ui/trackersadditiondlg.ui \ - ui/console.ui \ - ui/feeddownloader.ui \ - ui/propertieswidget.ui \ - ui/peer.ui \ - ui/confirmdeletiondlg.ui -SOURCES += GUI.cpp \ - main.cpp \ - options_imp.cpp \ - createtorrent_imp.cpp \ + preferences.h + +contains(DEFINES, DISABLE_GUI) { + HEADERS += headlessloader.h +} else { + HEADERS += GUI.h \ + feedList.h \ + supportedengines.h \ + transferlistwidget.h \ + transferlistdelegate.h \ + transferlistfilterswidget.h \ + propertieswidget.h \ + torrentfilesmodel.h \ + geoip.h \ + peeraddition.h \ + deletionconfirmationdlg.h \ + statusbar.h \ + trackerlist.h \ + downloadedpiecesbar.h \ + peerlistwidget.h \ + peerlistdelegate.h \ + reverseresolution.h \ + feeddownloader.h \ + trackersadditiondlg.h \ + searchtab.h \ + console_imp.h \ + ico.h \ + engineselectdlg.h \ + pluginsource.h \ + qgnomelook.h \ + searchEngine.h \ + rss.h \ + rss_imp.h \ + speedlimitdlg.h \ + options_imp.h \ + about_imp.h \ + createtorrent_imp.h \ + searchlistdelegate.h \ + proplistdelegate.h \ + previewselect.h \ + previewlistdelegate.h \ + downloadfromurldlg.h \ + torrentadditiondlg.h \ + trackerlogin.h \ + pieceavailabilitybar.h +} + +!contains(DEFINES, DISABLE_GUI) { + message(adding forms) + FORMS += ui/mainwindow.ui \ + ui/options.ui \ + ui/about.ui \ + ui/createtorrent.ui \ + ui/preview.ui \ + ui/login.ui \ + ui/downloadfromurldlg.ui \ + ui/torrentadditiondlg.ui \ + ui/search.ui \ + ui/rss.ui \ + ui/bandwidth_limit.ui \ + ui/engineselect.ui \ + ui/pluginsource.ui \ + ui/trackersadditiondlg.ui \ + ui/console.ui \ + ui/feeddownloader.ui \ + ui/propertieswidget.ui \ + ui/peer.ui \ + ui/confirmdeletiondlg.ui +} + +SOURCES += main.cpp \ bittorrent.cpp \ - searchengine.cpp \ - rss_imp.cpp \ qtorrenthandle.cpp \ - engineselectdlg.cpp \ downloadthread.cpp \ httpserver.cpp \ httpconnection.cpp \ httprequestparser.cpp \ httpresponsegenerator.cpp \ - eventmanager.cpp \ - searchtab.cpp \ - ico.cpp \ - rss.cpp \ - transferlistwidget.cpp \ - propertieswidget.cpp \ - peerlistwidget.cpp + eventmanager.cpp + +!contains(DEFINES, DISABLE_GUI) { + SOURCES += GUI.cpp \ + options_imp.cpp \ + createtorrent_imp.cpp \ + searchengine.cpp \ + rss_imp.cpp \ + engineselectdlg.cpp \ + searchtab.cpp \ + ico.cpp \ + rss.cpp \ + transferlistwidget.cpp \ + propertieswidget.cpp \ + peerlistwidget.cpp +} + DESTDIR = .