Browse Source

- Merged headless branch

adaptive-webui-19844
Christophe Dumez 15 years ago
parent
commit
cbe4bbac6a
  1. 1
      AUTHORS
  2. 21
      configure
  3. 4
      qcm/geoip-database.qcm
  4. 4
      qcm/libnotify.qcm
  5. 4
      qcm/qt4.qcm
  6. 32
      src/bittorrent.cpp
  7. 15
      src/bittorrent.h
  8. 2
      src/eventmanager.cpp
  9. 23
      src/filterparserthread.h
  10. 138
      src/headlessloader.h
  11. 73
      src/main.cpp
  12. 86
      src/misc.h
  13. 5
      src/preferences.h
  14. 4
      src/qtorrenthandle.cpp
  15. 4
      src/qtorrenthandle.h
  16. 164
      src/src.pro

1
AUTHORS

@ -6,6 +6,7 @@ Contributors: @@ -6,6 +6,7 @@ Contributors:
* Ishan Arora <ishan@qbittorrent.org>
* Arnaud Demaizière <arnaud@qbittorrent.org>
* Grigis Gaëtan <cipher16@gmail.com>
* Frédéric Lassabe <frederic.lassabe@utbm.fr>
Code from other projects:
* files src/ico.cpp src/ico.h

21
configure vendored

@ -18,6 +18,8 @@ Main options: @@ -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 @@ -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 @@ -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 <<EOT @@ -290,6 +298,7 @@ cat >$1/modules.cpp <<EOT
/*
-----BEGIN QCMOD-----
name: Qt >= 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: @@ -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: @@ -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: @@ -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 @@ -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

4
qcm/geoip-database.qcm

@ -12,6 +12,10 @@ public: @@ -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

4
qcm/libnotify.qcm

@ -11,6 +11,10 @@ public: @@ -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;

4
qcm/qt4.qcm

@ -1,6 +1,7 @@ @@ -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: @@ -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");
}

32
src/bittorrent.cpp

@ -41,7 +41,9 @@ @@ -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 <libtorrent/extensions/ut_metadata.hpp>
@ -65,8 +67,11 @@ enum ProxyType {HTTP=1, SOCKS5=2, HTTP_PW=3, SOCKS5_PW=4, SOCKS4=5}; @@ -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() { @@ -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() { @@ -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) { @@ -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) { @@ -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 @@ -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 { @@ -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("<font color='grey'>")+ QDateTime::currentDateTime().toString(QString::fromUtf8("dd/MM/yyyy hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + msg + QString::fromUtf8("</i></font>"));
#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() { @@ -1782,12 +1798,12 @@ void Bittorrent::readAlerts() {
}
}
else if (portmap_error_alert* p = dynamic_cast<portmap_error_alert*>(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<portmap_alert*>(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<peer_blocked_alert*>(a.get())) {
@ -1895,7 +1911,11 @@ QString Bittorrent::getSavePath(QString hash) { @@ -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);

15
src/bittorrent.h

@ -34,8 +34,12 @@ @@ -34,8 +34,12 @@
#include <QMap>
#include <QUrl>
#include <QStringList>
#include <QApplication>
#include <QPalette>
#ifdef DISABLE_GUI
#include <QCoreApplication>
#else
#include <QApplication>
#include <QPalette>
#endif
#include <QPointer>
#include <libtorrent/session.hpp>
@ -117,8 +121,10 @@ private: @@ -117,8 +121,10 @@ private:
QString defaultSavePath;
QString defaultTempPath;
// GeoIP
#ifndef DISABLE_GUI
bool resolve_countries;
bool geoipDBLoaded;
#endif
// ETA Computation
QPointer<QTimer> timerETA;
QHash<QString, QList<int> > ETA_samples;
@ -219,7 +225,11 @@ public slots: @@ -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: @@ -248,6 +258,7 @@ signals:
void torrentFinishedChecking(QTorrentHandle& h);
void metadataReceived(QTorrentHandle &h);
void savePathChanged(QTorrentHandle &h);
void newConsoleMessage(QString msg);
};
#endif

2
src/eventmanager.cpp

@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
#include "bittorrent.h"
#include "misc.h"
#include "preferences.h"
#include "proplistdelegate.h"
//#include "proplistdelegate.h"
#include "torrentpersistentdata.h"
#include <QDebug>

23
src/filterparserthread.h

@ -34,7 +34,8 @@ @@ -34,7 +34,8 @@
#include <QThread>
#include <QFile>
#include <QDataStream>
#include <QMessageBox>
#include <QRegExp>
#include <QStringList>
#include <libtorrent/session.hpp>
#include <libtorrent/ip_filter.hpp>
@ -103,7 +104,7 @@ class FilterParserThread : public QThread { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -342,7 +343,7 @@ class FilterParserThread : public QThread {
for(unsigned int i=0; i<namecount; i++) {
string name;
if(!getlineInStream(stream, name, '\0')) {
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;
}
if(abort) return;
@ -350,7 +351,7 @@ class FilterParserThread : public QThread { @@ -350,7 +351,7 @@ class FilterParserThread : public QThread {
// Reading the ranges
unsigned int rangecount;
if(!stream.readRawData((char*)&rangecount, sizeof(rangecount))) {
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;
}
rangecount=ntohl(rangecount);
@ -363,7 +364,7 @@ class FilterParserThread : public QThread { @@ -363,7 +364,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
@ -376,7 +377,7 @@ class FilterParserThread : public QThread { @@ -376,7 +377,7 @@ class FilterParserThread : public QThread {
if(abort) return;
}
} else {
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;
}
file.close();

138
src/headlessloader.h

@ -0,0 +1,138 @@ @@ -0,0 +1,138 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez, Frédéric Lassabe
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#ifndef HEADLESSLOADER_H
#define HEADLESSLOADER_H
#include <QObject>
#include <QCoreApplication>
#include <QLocalServer>
#include <QLocalSocket>
#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<QLocalSocket*>(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

73
src/main.cpp

@ -28,25 +28,34 @@ @@ -28,25 +28,34 @@
* Contact : chris@qbittorrent.org
*/
#include <QApplication>
#include <QLocale>
#include <QTranslator>
#include <QFile>
#include <QSplashScreen>
#ifndef DISABLE_GUI
#include <QApplication>
#include <QSplashScreen>
#include <QPlastiqueStyle>
#include "qgnomelook.h"
#include <QMotifStyle>
#include <QCDEStyle>
#ifdef Q_WS_WIN
#include <QWindowsXPStyle>
#endif
#ifdef Q_WS_MAC
#include <QMacStyle>
#endif
#include "GUI.h"
#include "ico.h"
#else
#include <QCoreApplication>
#include "headlessloader.h"
#endif
#include <QSettings>
#include <QLocalSocket>
#include <unistd.h>
#include <sys/types.h>
#include <QPlastiqueStyle>
#include "qgnomelook.h"
#include <QMotifStyle>
#include <QCDEStyle>
#ifdef Q_WS_WIN
#include <QWindowsXPStyle>
#endif
#ifdef Q_WS_MAC
#include <QMacStyle>
#endif
#ifndef Q_WS_WIN
#include <signal.h>
#include <execinfo.h>
@ -54,12 +63,14 @@ @@ -54,12 +63,14 @@
#endif
#include <stdlib.h>
#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) { @@ -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){ @@ -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[]){ @@ -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; i<argc; ++i) {
#ifndef DISABLE_GUI
if(QString::fromUtf8(argv[i]) == QString::fromUtf8("--no-splash")) {
no_splash = true;
} else {
#endif
if(QString::fromUtf8(argv[i]).startsWith("--webui-port=")) {
QStringList parts = QString::fromUtf8(argv[i]).split("=");
if(parts.size() == 2) {
@ -149,12 +169,17 @@ int main(int argc, char *argv[]){ @@ -149,12 +169,17 @@ int main(int argc, char *argv[]){
}
}
}
#ifndef DISABLE_GUI
}
#endif
}
}
#ifndef DISABLE_GUI
if(settings.value(QString::fromUtf8("Preferences/General/NoSplashScreen"), false).toBool()) {
no_splash = true;
}
#endif
// Set environment variable
if(putenv((char*)"QBITTORRENT="VERSION)) {
std::cerr << "Couldn't set environment variable...\n";
@ -187,7 +212,12 @@ int main(int argc, char *argv[]){ @@ -187,7 +212,12 @@ int main(int argc, char *argv[]){
localSocket.close();
return 0;
}
#ifdef DISABLE_GUI
app = new QCoreApplication(argc, argv);
#else
app = new QApplication(argc, argv);
#endif
#ifndef DISABLE_GUI
useStyle(app, settings.value("Preferences/General/Style", 0).toInt());
app->setStyleSheet("QStatusBar::item { border-width: 0; }");
QSplashScreen *splash = 0;
@ -195,6 +225,7 @@ int main(int argc, char *argv[]){ @@ -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[]){ @@ -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.");

86
src/misc.h

@ -43,10 +43,24 @@ @@ -43,10 +43,24 @@
#include <QThread>
#include <ctime>
#include <QDateTime>
#include <QDesktopServices>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#ifdef DISABLE_GUI
#include <QCoreApplication>
#else
#include <QApplication>
#endif
#ifdef Q_WS_WIN
#include <shlobj.h>
#endif
#ifdef Q_WS_MAC
#include <Files.h>
#include <Folders.h>
#endif
#ifndef Q_WS_WIN
#ifdef Q_WS_MAC
#include <sys/param.h>
@ -168,8 +182,72 @@ public: @@ -168,8 +182,72 @@ public:
}
}
#ifdef Q_WS_MAC
static QString getFullPath(const FSRef &ref)
{
QByteArray ba(2048, 0);
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(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: @@ -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: @@ -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());

5
src/preferences.h

@ -676,6 +676,11 @@ public: @@ -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();

4
src/qtorrenthandle.cpp

@ -417,10 +417,12 @@ bool QTorrentHandle::is_sequential_download() const { @@ -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 { @@ -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());

4
src/qtorrenthandle.h

@ -121,7 +121,9 @@ class QTorrentHandle { @@ -121,7 +121,9 @@ class QTorrentHandle {
#endif
QString creation_date() const;
void get_peer_info(std::vector<peer_info>&) const;
#ifndef DISABLE_GUI
bool resolve_countries() const;
#endif
bool priv() const;
bool first_last_piece_first() const;
@ -152,7 +154,9 @@ class QTorrentHandle { @@ -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;

164
src/src.pro

@ -172,28 +172,10 @@ TRANSLATIONS = $$LANG_PATH/qbittorrent_fr.ts \ @@ -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 \ @@ -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 = .

Loading…
Cancel
Save