Browse Source

FEATURE: Support for multiple scan folders

* Patch by Christian Kandeler (Thanks!)
adaptive-webui-19844
Christophe Dumez 15 years ago
parent
commit
7710c88797
  1. 1
      Changelog
  2. 90
      src/bittorrent.cpp
  3. 8
      src/bittorrent.h
  4. 10
      src/eventmanager.cpp
  5. 95
      src/filesystemwatcher.h
  6. 92
      src/options_imp.cpp
  7. 8
      src/options_imp.h
  8. 21
      src/preferences.h
  9. 2
      src/rss_imp.cpp
  10. 191
      src/scannedfoldersmodel.cpp
  11. 82
      src/scannedfoldersmodel.h
  12. 67
      src/src.pro
  13. 202
      src/ui/options.ui

1
Changelog

@ -12,6 +12,7 @@
- FEATURE: Trackers can be added from Web UI - FEATURE: Trackers can be added from Web UI
- FEATURE: Global transfer information are displayed in the new Web UI status bar - FEATURE: Global transfer information are displayed in the new Web UI status bar
- FEATURE: Allow to change the priority of several files at once - FEATURE: Allow to change the priority of several files at once
- FEATURE: Support for multiple scan folders (Patch by Christian Kandeler)
- COSMETIC: Improved style management - COSMETIC: Improved style management
* Mon Jan 18 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.0 * Mon Jan 18 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.0

90
src/bittorrent.cpp

@ -41,6 +41,7 @@
#include "downloadthread.h" #include "downloadthread.h"
#include "filterparserthread.h" #include "filterparserthread.h"
#include "preferences.h" #include "preferences.h"
#include "scannedfoldersmodel.h"
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
#include "geoip.h" #include "geoip.h"
#endif #endif
@ -68,7 +69,13 @@ enum ProxyType {HTTP=1, SOCKS5=2, HTTP_PW=3, SOCKS5_PW=4, SOCKS4=5};
enum VersionType { NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL }; enum VersionType { NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL };
// Main constructor // 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), torrentExport(false), exiting(false) { Bittorrent::Bittorrent()
: m_scanFolders(ScanFoldersModel::instance(this)),
preAllocateAll(false), addInPause(false), ratio_limit(-1),
UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false),
DHTEnabled(false), current_dht_port(0), queueingEnabled(false),
torrentExport(false), exiting(false)
{
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
geoipDBLoaded = false; geoipDBLoaded = false;
resolve_countries = false; resolve_countries = false;
@ -136,6 +143,7 @@ Bittorrent::Bittorrent() : preAllocateAll(false), addInPause(false), ratio_limit
#endif #endif
// Apply user settings to Bittorrent session // Apply user settings to Bittorrent session
configureSession(); configureSession();
connect(m_scanFolders, SIGNAL(torrentsAdded(QStringList&)), this, SLOT(addTorrentsFromScanFolder(QStringList&)));
qDebug("* BTSession constructed"); qDebug("* BTSession constructed");
} }
@ -165,8 +173,6 @@ Bittorrent::~Bittorrent() {
session_proxy sp = s->abort(); session_proxy sp = s->abort();
delete s; delete s;
} }
// Disable directory scanning
disableDirectoryScanning();
// Delete our objects // Delete our objects
delete timerAlerts; delete timerAlerts;
if(BigRatioTimer) if(BigRatioTimer)
@ -174,8 +180,6 @@ Bittorrent::~Bittorrent() {
if(filterParser) if(filterParser)
delete filterParser; delete filterParser;
delete downloader; delete downloader;
if(FSWatcher)
delete FSWatcher;
if(bd_scheduler) if(bd_scheduler)
delete bd_scheduler; delete bd_scheduler;
// HTTP Server // HTTP Server
@ -272,13 +276,14 @@ void Bittorrent::configureSession() {
#endif #endif
preAllocateAllFiles(Preferences::preAllocateAllFiles()); preAllocateAllFiles(Preferences::preAllocateAllFiles());
startTorrentsInPause(Preferences::addTorrentsInPause()); startTorrentsInPause(Preferences::addTorrentsInPause());
// * Scan dir // * Scan dirs
QString scan_dir = Preferences::getScanDir(); const QStringList &scan_dirs = Preferences::getScanDirs();
if(scan_dir.isEmpty()) { foreach (const QString &dir, scan_dirs) {
disableDirectoryScanning(); m_scanFolders->addPath(dir);
}else{ }
//Interval first const QVariantList &downloadInDirList = Preferences::getDownloadInScanDirs();
enableDirectoryScanning(scan_dir); for (int i = 0; i < downloadInDirList.count(); ++i) {
m_scanFolders->setDownloadAtPath(i, downloadInDirList.at(i).toBool());
} }
// * Export Dir // * Export Dir
bool newTorrentExport = Preferences::isTorrentExportEnabled(); bool newTorrentExport = Preferences::isTorrentExportEnabled();
@ -1039,7 +1044,7 @@ QTorrentHandle Bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
// Enforcing the save path defined before URL download (from RSS for example) // Enforcing the save path defined before URL download (from RSS for example)
savePath = savepath_fromurl.take(QUrl::fromEncoded(from_url.toLocal8Bit())); savePath = savepath_fromurl.take(QUrl::fromEncoded(from_url.toLocal8Bit()));
} else { } else {
savePath = getSavePath(hash); savePath = getSavePath(hash, fromScanDir, path);
} }
if(!defaultTempPath.isEmpty() && resumed && !TorrentPersistentData::isSeed(hash)) { if(!defaultTempPath.isEmpty() && resumed && !TorrentPersistentData::isSeed(hash)) {
qDebug("addTorrent::Temp folder is enabled."); qDebug("addTorrent::Temp folder is enabled.");
@ -1495,14 +1500,13 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
} }
void Bittorrent::addTorrentsFromScanFolder(QStringList &pathList) { void Bittorrent::addTorrentsFromScanFolder(QStringList &pathList) {
QString dir_path = FSWatcher->directories().first();
foreach(const QString &file, pathList) { foreach(const QString &file, pathList) {
QString fullPath = dir_path+QDir::separator()+file; qDebug("File %s added", qPrintable(file));
try { try {
torrent_info t(fullPath.toLocal8Bit().data()); torrent_info t(file.toLocal8Bit().data());
addTorrent(fullPath, true); addTorrent(file, true);
} catch(std::exception&) { } catch(std::exception&) {
qDebug("Ignoring incomplete torrent file: %s", fullPath.toLocal8Bit().data()); qDebug("Ignoring incomplete torrent file: %s", file.toLocal8Bit().data());
} }
} }
} }
@ -1647,39 +1651,6 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
} }
#endif #endif
// Enable directory scanning
void Bittorrent::enableDirectoryScanning(QString scan_dir) {
if(!scan_dir.isEmpty()) {
QDir newDir(scan_dir);
if(!newDir.exists()) {
qDebug("Scan dir %s does not exist, create it", scan_dir.toUtf8().data());
newDir.mkpath(scan_dir);
}
if(FSWatcher == 0) {
// Set up folder watching
FSWatcher = new FileSystemWatcher(this);
connect(FSWatcher, SIGNAL(torrentsAdded(QStringList&)), this, SLOT(addTorrentsFromScanFolder(QStringList&)));
FSWatcher->addPath(scan_dir);
} else {
QString old_scan_dir = "";
if(!FSWatcher->directories().empty())
old_scan_dir = FSWatcher->directories().first();
if(QDir(old_scan_dir) != QDir(scan_dir)) {
if(!old_scan_dir.isEmpty())
FSWatcher->removePath(old_scan_dir);
FSWatcher->addPath(scan_dir);
}
}
}
}
// Disable directory scanning
void Bittorrent::disableDirectoryScanning() {
if(FSWatcher) {
delete FSWatcher;
}
}
// Set the ports range in which is chosen the port the Bittorrent // Set the ports range in which is chosen the port the Bittorrent
// session will listen to // session will listen to
void Bittorrent::setListeningPort(int port) { void Bittorrent::setListeningPort(int port) {
@ -2133,12 +2104,13 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
return s->status(); return s->status();
} }
QString Bittorrent::getSavePath(QString hash) { QString Bittorrent::getSavePath(QString hash, bool fromScanDir, QString filePath) {
QString savePath; QString savePath;
if(TorrentTempData::hasTempData(hash)) { if(TorrentTempData::hasTempData(hash)) {
savePath = TorrentTempData::getSavePath(hash); savePath = TorrentTempData::getSavePath(hash);
if(savePath.isEmpty()) if(savePath.isEmpty()) {
savePath = defaultSavePath; savePath = defaultSavePath;
}
if(appendLabelToSavePath) { if(appendLabelToSavePath) {
qDebug("appendLabelToSavePath is true"); qDebug("appendLabelToSavePath is true");
QString label = TorrentTempData::getLabel(hash); QString label = TorrentTempData::getLabel(hash);
@ -2152,9 +2124,13 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
qDebug("getSavePath, got save_path from temp data: %s", savePath.toLocal8Bit().data()); qDebug("getSavePath, got save_path from temp data: %s", savePath.toLocal8Bit().data());
} else { } else {
savePath = TorrentPersistentData::getSavePath(hash); savePath = TorrentPersistentData::getSavePath(hash);
if(savePath.isEmpty()) if(savePath.isEmpty()) {
savePath = defaultSavePath; if(fromScanDir && m_scanFolders->downloadInTorrentFolder(filePath))
if(appendLabelToSavePath) { savePath = QFileInfo(filePath).dir().path();
else
savePath = defaultSavePath;
}
if(!fromScanDir && appendLabelToSavePath) {
QString label = TorrentPersistentData::getLabel(hash); QString label = TorrentPersistentData::getLabel(hash);
if(!label.isEmpty()) { if(!label.isEmpty()) {
QDir save_dir(savePath); QDir save_dir(savePath);

8
src/bittorrent.h

@ -52,10 +52,10 @@ using namespace libtorrent;
class downloadThread; class downloadThread;
class QTimer; class QTimer;
class FileSystemWatcher;
class FilterParserThread; class FilterParserThread;
class HttpServer; class HttpServer;
class BandwidthScheduler; class BandwidthScheduler;
class ScanFoldersModel;
class TrackerInfos { class TrackerInfos {
public: public:
@ -102,7 +102,7 @@ private:
// HTTP // HTTP
QPointer<downloadThread> downloader; QPointer<downloadThread> downloader;
// File System // File System
QPointer<FileSystemWatcher> FSWatcher; ScanFoldersModel *m_scanFolders;
// Console / Log // Console / Log
QStringList consoleMessages; QStringList consoleMessages;
QStringList peerBanMessages; QStringList peerBanMessages;
@ -142,7 +142,7 @@ private:
bool exiting; bool exiting;
protected: protected:
QString getSavePath(QString hash); QString getSavePath(QString hash, bool fromScanDir = false, QString filePath = QString());
bool initWebUi(QString username, QString password, int port); bool initWebUi(QString username, QString password, int port);
public: public:
@ -195,8 +195,6 @@ public slots:
void saveDHTEntry(); void saveDHTEntry();
void preAllocateAllFiles(bool b); void preAllocateAllFiles(bool b);
void saveFastResumeData(); void saveFastResumeData();
void enableDirectoryScanning(QString scan_dir);
void disableDirectoryScanning();
void enableIPFilter(QString filter); void enableIPFilter(QString filter);
void disableIPFilter(); void disableIPFilter();
void setQueueingEnabled(bool enable); void setQueueingEnabled(bool enable);

10
src/eventmanager.cpp

@ -129,8 +129,10 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
Preferences::setTempPathEnabled(m["temp_path_enabled"].toBool()); Preferences::setTempPathEnabled(m["temp_path_enabled"].toBool());
if(m.contains("temp_path")) if(m.contains("temp_path"))
Preferences::setTempPath(m["temp_path"].toString()); Preferences::setTempPath(m["temp_path"].toString());
if(m.contains("scan_dir")) if(m.contains("scan_dirs"))
Preferences::setScanDir(m["scan_dir"].toString()); Preferences::setScanDirs(m["scan_dirs"].toStringList());
if(m.contains("download_in_scan_dirs"))
Preferences::setDownloadInScanDirs(m["download_in_scan_dirs"].toList());
if(m.contains("export_dir")) if(m.contains("export_dir"))
Preferences::setExportDir(m["export_dir"].toString()); Preferences::setExportDir(m["export_dir"].toString());
if(m.contains("preallocate_all")) if(m.contains("preallocate_all"))
@ -229,8 +231,8 @@ QVariantMap EventManager::getGlobalPreferences() const {
data["save_path"] = Preferences::getSavePath(); data["save_path"] = Preferences::getSavePath();
data["temp_path_enabled"] = Preferences::isTempPathEnabled(); data["temp_path_enabled"] = Preferences::isTempPathEnabled();
data["temp_path"] = Preferences::getTempPath(); data["temp_path"] = Preferences::getTempPath();
data["scan_dir_enabled"] = Preferences::isDirScanEnabled(); data["scan_dirs"] = Preferences::getScanDirs();
data["scan_dir"] = Preferences::getScanDir(); data["download_in_scan_dirs"] = Preferences::getDownloadInScanDirs();
data["export_dir_enabled"] = Preferences::isTorrentExportEnabled(); data["export_dir_enabled"] = Preferences::isTorrentExportEnabled();
data["export_dir"] = Preferences::getExportDir(); data["export_dir"] = Preferences::getExportDir();
data["preallocate_all"] = Preferences::preAllocateAllFiles(); data["preallocate_all"] = Preferences::preAllocateAllFiles();

95
src/filesystemwatcher.h

@ -34,12 +34,14 @@
class FileSystemWatcher: public QFileSystemWatcher { class FileSystemWatcher: public QFileSystemWatcher {
Q_OBJECT Q_OBJECT
#ifndef Q_WS_WIN
private: private:
QDir watched_folder; #ifndef Q_WS_WIN
QList<QDir> watched_folders;
QPointer<QTimer> watch_timer; QPointer<QTimer> watch_timer;
#endif
QStringList filters; QStringList filters;
#ifndef Q_WS_WIN
protected: protected:
bool isNetworkFileSystem(QString path) { bool isNetworkFileSystem(QString path) {
QString file = path; QString file = path;
@ -98,12 +100,12 @@ protected:
public: public:
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) { FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
filters << "*.torrent"; filters << "*.torrent";
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanFolder())); connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
} }
FileSystemWatcher(QString path, QObject *parent): QFileSystemWatcher(parent) { FileSystemWatcher(QString path, QObject *parent): QFileSystemWatcher(parent) {
filters << "*.torrent"; filters << "*.torrent";
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanFolder())); connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
addPath(path); addPath(path);
} }
@ -115,33 +117,40 @@ public:
} }
QStringList directories() const { QStringList directories() const {
QStringList dirs;
#ifndef Q_WS_WIN #ifndef Q_WS_WIN
if(watch_timer) if(watch_timer) {
return QStringList(watched_folder.path()); foreach (const QDir &dir, watched_folders)
dirs << dir.canonicalPath();
}
#endif #endif
return QFileSystemWatcher::directories(); dirs << QFileSystemWatcher::directories();
return dirs;
} }
void addPath(const QString & path) { void addPath(const QString & path) {
#ifndef Q_WS_WIN #ifndef Q_WS_WIN
watched_folder = QDir(path); QDir dir(path);
if(!watched_folder.exists()) return; if (!dir.exists())
return;
// Check if the path points to a network file system or not // Check if the path points to a network file system or not
if(isNetworkFileSystem(path)) { if(isNetworkFileSystem(path)) {
// Network mode // Network mode
Q_ASSERT(!watch_timer); qDebug("Network folder detected: %s", qPrintable(path));
qDebug("Network folder detected: %s", path.toLocal8Bit().data());
qDebug("Using file polling mode instead of inotify..."); qDebug("Using file polling mode instead of inotify...");
watched_folders << dir;
// Set up the watch timer // Set up the watch timer
watch_timer = new QTimer(this); if (!watch_timer) {
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanFolder())); watch_timer = new QTimer(this);
watch_timer->start(5000); // 5 sec connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanNetworkFolders()));
watch_timer->start(5000); // 5 sec
}
} else { } else {
#endif #endif
// Normal mode // Normal mode
qDebug("FS Watching is watching %s in normal mode", path.toLocal8Bit().data()); qDebug("FS Watching is watching %s in normal mode", path.toLocal8Bit().data());
QFileSystemWatcher::addPath(path); QFileSystemWatcher::addPath(path);
scanFolder(); scanLocalFolder(path);
#ifndef Q_WS_WIN #ifndef Q_WS_WIN
} }
#endif #endif
@ -149,38 +158,58 @@ public:
void removePath(const QString & path) { void removePath(const QString & path) {
#ifndef Q_WS_WIN #ifndef Q_WS_WIN
if(watch_timer) { QDir dir(path);
// Network mode for (int i = 0; i < watched_folders.count(); ++i) {
if(QDir(path) == watched_folder) { if (QDir(watched_folders.at(i)) == dir) {
delete watch_timer; watched_folders.removeAt(i);
if (watched_folders.isEmpty())
delete watch_timer;
return;
} }
} else {
#endif
// Normal mode
QFileSystemWatcher::removePath(path);
#ifndef Q_WS_WIN
} }
#endif #endif
// Normal mode
QFileSystemWatcher::removePath(path);
} }
protected slots: protected slots:
// XXX: Does not detect file size changes to improve performance. void scanLocalFolder(QString path) {
void scanFolder() { qDebug("scanLocalFolder(%s) called", qPrintable(path));
qDebug("Scan folder was called");
QStringList torrents; QStringList torrents;
if(watch_timer) { // Local folders scan
torrents = watched_folder.entryList(filters, QDir::Files, QDir::Unsorted); addTorrentsFromDir(QDir(path), torrents);
} else { // Report detected torrent files
torrents = QDir(QFileSystemWatcher::directories().first()).entryList(filters, QDir::Files, QDir::Unsorted); if(!torrents.empty()) {
qDebug("FSWatcher: Polling manually folder %s", QFileSystemWatcher::directories().first().toLocal8Bit().data()); qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
emit torrentsAdded(torrents);
}
}
void scanNetworkFolders() {
qDebug("scanNetworkFolders() called");
QStringList torrents;
// Network folders scan
foreach (const QDir &dir, watched_folders) {
qDebug("FSWatcher: Polling manually folder %s", qPrintable(dir.path()));
addTorrentsFromDir(dir, torrents);
} }
if(!torrents.empty()) // Report detected torrent files
if(!torrents.empty()) {
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
emit torrentsAdded(torrents); emit torrentsAdded(torrents);
}
} }
signals: signals:
void torrentsAdded(QStringList &pathList); void torrentsAdded(QStringList &pathList);
private:
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
const QStringList &files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
foreach(const QString &file, files)
torrents << dir.canonicalPath() + '/' + file;
}
}; };
#endif // FILESYSTEMWATCHER_H #endif // FILESYSTEMWATCHER_H

92
src/options_imp.cpp

@ -47,6 +47,7 @@
#include "preferences.h" #include "preferences.h"
#include "misc.h" #include "misc.h"
#include "advancedsettings.h" #include "advancedsettings.h"
#include "scannedfoldersmodel.h"
// Constructor // Constructor
options_imp::options_imp(QWidget *parent):QDialog(parent){ options_imp::options_imp(QWidget *parent):QDialog(parent){
@ -62,6 +63,12 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){
break; break;
} }
} }
scanFoldersView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
scanFoldersView->setModel(ScanFoldersModel::instance());
connect(ScanFoldersModel::instance(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(enableApplyButton()));
connect(scanFoldersView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(handleScanFolderViewSelectionChanged()));
connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(applySettings(QAbstractButton*))); connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(applySettings(QAbstractButton*)));
comboStyle->addItems(QStyleFactory::keys()); comboStyle->addItems(QStyleFactory::keys());
// Languages supported // Languages supported
@ -139,7 +146,6 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){
connect(checkNoSystray, SIGNAL(toggled(bool)), this, SLOT(setSystrayOptionsState(bool))); connect(checkNoSystray, SIGNAL(toggled(bool)), this, SLOT(setSystrayOptionsState(bool)));
// Downloads tab // Downloads tab
connect(checkTempFolder, SIGNAL(toggled(bool)), this, SLOT(enableTempPathInput(bool))); connect(checkTempFolder, SIGNAL(toggled(bool)), this, SLOT(enableTempPathInput(bool)));
connect(checkScanDir, SIGNAL(toggled(bool)), this, SLOT(enableDirScan(bool)));
connect(checkExportDir, SIGNAL(toggled(bool)), this, SLOT(enableTorrentExport(bool))); connect(checkExportDir, SIGNAL(toggled(bool)), this, SLOT(enableTorrentExport(bool)));
// Connection tab // Connection tab
connect(checkUploadLimit, SIGNAL(toggled(bool)), this, SLOT(enableUploadLimit(bool))); connect(checkUploadLimit, SIGNAL(toggled(bool)), this, SLOT(enableUploadLimit(bool)));
@ -187,8 +193,6 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){
connect(checkPreallocateAll, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(checkPreallocateAll, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(checkAdditionDialog, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(checkAdditionDialog, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(checkStartPaused, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(checkStartPaused, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(checkScanDir, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(textScanDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(checkExportDir, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(checkExportDir, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(textExportDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton())); connect(textExportDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(actionTorrentDlOnDblClBox, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton())); connect(actionTorrentDlOnDblClBox, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
@ -280,6 +284,8 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){
// Main destructor // Main destructor
options_imp::~options_imp(){ options_imp::~options_imp(){
qDebug("-> destructing Options"); qDebug("-> destructing Options");
foreach (const QString &path, addedScanDirs)
ScanFoldersModel::instance()->removePath(path);
delete scrollArea_advanced->layout(); delete scrollArea_advanced->layout();
delete advancedSettings; delete advancedSettings;
} }
@ -366,7 +372,8 @@ void options_imp::saveOptions(){
settings.setValue(QString::fromUtf8("PreAllocation"), preAllocateAllFiles()); settings.setValue(QString::fromUtf8("PreAllocation"), preAllocateAllFiles());
settings.setValue(QString::fromUtf8("AdditionDialog"), useAdditionDialog()); settings.setValue(QString::fromUtf8("AdditionDialog"), useAdditionDialog());
settings.setValue(QString::fromUtf8("StartInPause"), addTorrentsInPause()); settings.setValue(QString::fromUtf8("StartInPause"), addTorrentsInPause());
settings.setValue(QString::fromUtf8("ScanDir"), getScanDir()); ScanFoldersModel::instance()->makePersistent(settings);
addedScanDirs.clear();
Preferences::setExportDir(getExportDir()); Preferences::setExportDir(getExportDir());
settings.setValue(QString::fromUtf8("DblClOnTorDl"), getActionOnDblClOnTorrentDl()); settings.setValue(QString::fromUtf8("DblClOnTorDl"), getActionOnDblClOnTorrentDl());
settings.setValue(QString::fromUtf8("DblClOnTorFn"), getActionOnDblClOnTorrentFn()); settings.setValue(QString::fromUtf8("DblClOnTorFn"), getActionOnDblClOnTorrentFn());
@ -589,17 +596,6 @@ void options_imp::loadOptions(){
checkPreallocateAll->setChecked(Preferences::preAllocateAllFiles()); checkPreallocateAll->setChecked(Preferences::preAllocateAllFiles());
checkAdditionDialog->setChecked(Preferences::useAdditionDialog()); checkAdditionDialog->setChecked(Preferences::useAdditionDialog());
checkStartPaused->setChecked(Preferences::addTorrentsInPause()); checkStartPaused->setChecked(Preferences::addTorrentsInPause());
strValue = Preferences::getScanDir();
if(strValue.isEmpty()) {
// Disable
checkScanDir->setChecked(false);
enableDirScan(checkScanDir->isChecked());
} else {
// enable
checkScanDir->setChecked(true);
textScanDir->setText(strValue);
enableDirScan(checkScanDir->isChecked());
}
strValue = Preferences::getExportDir(); strValue = Preferences::getExportDir();
if(strValue.isEmpty()) { if(strValue.isEmpty()) {
@ -923,10 +919,6 @@ bool options_imp::confirmOnExit() const{
return checkConfirmExit->isChecked(); return checkConfirmExit->isChecked();
} }
bool options_imp::isDirScanEnabled() const {
return checkScanDir->isChecked();
}
bool options_imp::isQueueingSystemEnabled() const { bool options_imp::isQueueingSystemEnabled() const {
return checkEnableQueueing->isChecked(); return checkEnableQueueing->isChecked();
} }
@ -1241,11 +1233,6 @@ void options_imp::enableHTTPProxyAuth(bool checked){
textProxyPassword_http->setEnabled(checked); textProxyPassword_http->setEnabled(checked);
} }
void options_imp::enableDirScan(bool checked){
textScanDir->setEnabled(checked);
browseScanDirButton->setEnabled(checked);
}
void options_imp::enableTorrentExport(bool checked) { void options_imp::enableTorrentExport(bool checked) {
textExportDir->setEnabled(checked); textExportDir->setEnabled(checked);
browseExportDirButton->setEnabled(checked); browseExportDirButton->setEnabled(checked);
@ -1340,15 +1327,6 @@ void options_imp::setLocale(QString locale){
} }
} }
// Return scan dir set in options
QString options_imp::getScanDir() const {
if(checkScanDir->isChecked()){
return misc::expandPath(textScanDir->text());
}else{
return QString::null;
}
}
QString options_imp::getExportDir() const { QString options_imp::getExportDir() const {
if(checkExportDir->isChecked()){ if(checkExportDir->isChecked()){
return misc::expandPath(textExportDir->text()); return misc::expandPath(textExportDir->text());
@ -1371,21 +1349,45 @@ int options_imp::getActionOnDblClOnTorrentFn() const {
return actionTorrentFnOnDblClBox->currentIndex(); return actionTorrentFnOnDblClBox->currentIndex();
} }
// Display dialog to choose scan dir void options_imp::on_addScanFolderButton_clicked() {
void options_imp::on_browseScanDirButton_clicked() { const QString dir = QFileDialog::getExistingDirectory(this, tr("Add directory to scan"));
QString scan_path = misc::expandPath(textScanDir->text()); if (!dir.isEmpty()) {
QDir scanDir(scan_path); const ScanFoldersModel::PathStatus status = ScanFoldersModel::instance()->addPath(dir);
QString dir; QString error;
if(!scan_path.isEmpty() && scanDir.exists()) { switch (status) {
dir = QFileDialog::getExistingDirectory(this, tr("Choose scan directory"), scanDir.absolutePath()); case ScanFoldersModel::AlreadyInList:
} else { error = tr("Folder is already being watched.").arg(dir);
dir = QFileDialog::getExistingDirectory(this, tr("Choose scan directory"), QDir::homePath()); break;
} case ScanFoldersModel::DoesNotExist:
if(!dir.isNull()){ error = tr("Folder does not exist.");
textScanDir->setText(dir); break;
case ScanFoldersModel::CannotRead:
error = tr("Folder is not readable.");
break;
default:
addedScanDirs << dir;
enableApplyButton();
}
if (!error.isEmpty()) {
QMessageBox::warning(this, tr("Failure"), tr("Failed to add Scan Folder '%1': %2").arg(dir).arg(error));
}
} }
} }
void options_imp::on_removeScanFolderButton_clicked() {
const QModelIndexList &selected
= scanFoldersView->selectionModel()->selectedIndexes();
if (selected.isEmpty())
return;
Q_ASSERT(selected.count() == ScanFoldersModel::instance()->columnCount());
ScanFoldersModel::instance()->removePath(selected.first().row());
}
void options_imp::handleScanFolderViewSelectionChanged() {
removeScanFolderButton->setEnabled(!scanFoldersView->selectionModel()->selectedIndexes().isEmpty());
}
void options_imp::on_browseExportDirButton_clicked() { void options_imp::on_browseExportDirButton_clicked() {
QString export_path = misc::expandPath(textExportDir->text()); QString export_path = misc::expandPath(textExportDir->text());
QDir exportDir(export_path); QDir exportDir(export_path);

8
src/options_imp.h

@ -52,6 +52,7 @@ private:
QStringList locales; QStringList locales;
QAbstractButton *applyButton; QAbstractButton *applyButton;
AdvancedSettings *advancedSettings; AdvancedSettings *advancedSettings;
QList<QString> addedScanDirs;
public: public:
// Contructor / Destructor // Contructor / Destructor
@ -82,8 +83,6 @@ protected:
bool preAllocateAllFiles() const; bool preAllocateAllFiles() const;
bool useAdditionDialog() const; bool useAdditionDialog() const;
bool addTorrentsInPause() const; bool addTorrentsInPause() const;
bool isDirScanEnabled() const;
QString getScanDir() const;
QString getExportDir() const; QString getExportDir() const;
int getActionOnDblClOnTorrentDl() const; int getActionOnDblClOnTorrentDl() const;
int getActionOnDblClOnTorrentFn() const; int getActionOnDblClOnTorrentFn() const;
@ -136,7 +135,6 @@ protected slots:
void enableUploadLimit(bool checked); void enableUploadLimit(bool checked);
void enableDownloadLimit(bool checked); void enableDownloadLimit(bool checked);
void enableTempPathInput(bool checked); void enableTempPathInput(bool checked);
void enableDirScan(bool checked);
void enableTorrentExport(bool checked); void enableTorrentExport(bool checked);
void enablePeerProxy(int comboIndex); void enablePeerProxy(int comboIndex);
void enablePeerProxyAuth(bool checked); void enablePeerProxyAuth(bool checked);
@ -159,7 +157,6 @@ protected slots:
void closeEvent(QCloseEvent *e); void closeEvent(QCloseEvent *e);
void on_buttonBox_rejected(); void on_buttonBox_rejected();
void applySettings(QAbstractButton* button); void applySettings(QAbstractButton* button);
void on_browseScanDirButton_clicked();
void on_browseExportDirButton_clicked(); void on_browseExportDirButton_clicked();
void on_browseFilterButton_clicked(); void on_browseFilterButton_clicked();
void on_browseSaveDirButton_clicked(); void on_browseSaveDirButton_clicked();
@ -173,6 +170,9 @@ protected slots:
void loadWindowState(); void loadWindowState();
void saveWindowState() const; void saveWindowState() const;
void on_randomButton_clicked(); void on_randomButton_clicked();
void on_addScanFolderButton_clicked();
void on_removeScanFolderButton_clicked();
void handleScanFolderViewSelectionChanged();
public slots: public slots:
void setLocale(QString locale); void setLocale(QString locale);

21
src/preferences.h

@ -191,22 +191,25 @@ public:
return settings.value(QString::fromUtf8("Preferences/Downloads/StartInPause"), false).toBool(); return settings.value(QString::fromUtf8("Preferences/Downloads/StartInPause"), false).toBool();
} }
static bool isDirScanEnabled() { static QStringList getScanDirs() {
QSettings settings("qBittorrent", "qBittorrent"); QSettings settings("qBittorrent", "qBittorrent");
return !settings.value(QString::fromUtf8("Preferences/Downloads/ScanDir"), QString()).toString().isEmpty(); return settings.value(QString::fromUtf8("Preferences/Downloads/ScanDirs"), QStringList()).toStringList();
} }
static QString getScanDir() { // This must be called somewhere with data from the model
static void setScanDirs(const QStringList &dirs) {
QSettings settings("qBittorrent", "qBittorrent"); QSettings settings("qBittorrent", "qBittorrent");
return settings.value(QString::fromUtf8("Preferences/Downloads/ScanDir"), QString()).toString(); settings.setValue(QString::fromUtf8("Preferences/Downloads/ScanDirs"), dirs);
} }
static void setScanDir(QString path) { static QVariantList getDownloadInScanDirs() {
path = path.trimmed(); QSettings settings("qBittorrent", "qBittorrent");
if(path.isEmpty()) return settings.value(QString::fromUtf8("Preferences/Downloads/DownloadInScanDirs"), QVariantList()).toList();
path = QString(); }
static void setDownloadInScanDirs(const QVariantList &list) {
QSettings settings("qBittorrent", "qBittorrent"); QSettings settings("qBittorrent", "qBittorrent");
settings.setValue(QString::fromUtf8("Preferences/Downloads/ScanDir"), path); settings.setValue(QString::fromUtf8("Preferences/Downloads/DownloadInScanDirs"), list);
} }
static bool isTorrentExportEnabled() { static bool isTorrentExportEnabled() {

2
src/rss_imp.cpp

@ -432,7 +432,7 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
QList<RssItem*> news; QList<RssItem*> news;
if(rss_item == rssmanager) if(rss_item == rssmanager)
news = RssManager::sortNewsList(rss_item->getUnreadNewsList()); news = RssManager::sortNewsList(rss_item->getUnreadNewsList());
else else if(rss_item)
news = RssManager::sortNewsList(rss_item->getNewsList()); news = RssManager::sortNewsList(rss_item->getNewsList());
// Clear the list first // Clear the list first
textBrowser->clear(); textBrowser->clear();

191
src/scannedfoldersmodel.cpp

@ -0,0 +1,191 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christian Kandeler, Christophe Dumez
*
* 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
*/
#include "scannedfoldersmodel.h"
#include "filesystemwatcher.h"
#include <QDir>
#include <QFileInfo>
#include <QSettings>
#include <QString>
#include <QTemporaryFile>
namespace {
const int PathColumn = 0;
const int DownloadAtTorrentColumn = 1;
}
class ScanFoldersModel::PathData {
public:
PathData(const QString &path) : path(path), downloadAtPath(false) {}
const QString path;
bool downloadAtPath;
};
ScanFoldersModel *ScanFoldersModel::instance(QObject *parent) {
Q_ASSERT(!parent != !m_instance);
if (!m_instance)
m_instance = new ScanFoldersModel(parent);
return m_instance;
}
ScanFoldersModel::ScanFoldersModel(QObject *parent) :
QAbstractTableModel(parent), m_fsWatcher(0)
{ }
ScanFoldersModel::~ScanFoldersModel() { }
int ScanFoldersModel::rowCount(const QModelIndex &parent) const {
return parent.isValid() ? 0 : m_pathList.count();
}
int ScanFoldersModel::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return 2;
}
QVariant ScanFoldersModel::data(const QModelIndex &index, int role) const {
if (!index.isValid() || index.row() >= rowCount())
return QVariant();
const QSharedPointer<PathData> &pathData = m_pathList.at(index.row());
if (index.column() == PathColumn && role == Qt::DisplayRole)
return pathData->path;
if (index.column() == DownloadAtTorrentColumn && role == Qt::CheckStateRole)
return pathData->downloadAtPath ? Qt::Checked : Qt::Unchecked;
return QVariant();
}
QVariant ScanFoldersModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0 || section >= columnCount())
return QVariant();
if (section == PathColumn)
return tr("Watched Folder");
return tr("Download here");
}
Qt::ItemFlags ScanFoldersModel::flags(const QModelIndex &index) const {
if (!index.isValid() || index.row() >= rowCount() || index.column() != DownloadAtTorrentColumn)
return QAbstractTableModel::flags(index);
return QAbstractTableModel::flags(index) | Qt::ItemIsUserCheckable;
}
bool ScanFoldersModel::setData(const QModelIndex &index, const QVariant &value, int role) {
if (!index.isValid() || index.row() >= rowCount() || index.column() > DownloadAtTorrentColumn || role != Qt::CheckStateRole)
return false;
Q_ASSERT(index.column() == DownloadAtTorrentColumn);
m_pathList[index.row()]->downloadAtPath = (value.toInt() == Qt::Checked);
emit dataChanged(index, index);
return true;
}
ScanFoldersModel::PathStatus ScanFoldersModel::addPath(const QString &path) {
QDir dir(path);
if (!dir.exists())
return DoesNotExist;
if (!dir.isReadable())
return CannotRead;
const QString &canonicalPath = dir.canonicalPath();
if (findPathData(canonicalPath) != -1)
return AlreadyInList;
if (!m_fsWatcher) {
m_fsWatcher = new FileSystemWatcher(this);
connect(m_fsWatcher, SIGNAL(torrentsAdded(QStringList&)), this, SIGNAL(torrentsAdded(QStringList&)));
}
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_pathList << QSharedPointer<PathData>(new PathData(canonicalPath));
endInsertRows();
m_fsWatcher->addPath(canonicalPath);
return Ok;
}
void ScanFoldersModel::removePath(int row) {
Q_ASSERT(row >= 0 && row < rowCount());
beginRemoveRows(QModelIndex(), row, row);
m_fsWatcher->removePath(m_pathList.at(row)->path);
m_pathList.removeAt(row);
endRemoveRows();
}
bool ScanFoldersModel::removePath(const QString &path) {
const int row = findPathData(path);
if (row == -1)
return false;
removePath(row);
return true;
}
ScanFoldersModel::PathStatus ScanFoldersModel::setDownloadAtPath(int row, bool downloadAtPath) {
Q_ASSERT(row >= 0 && row < rowCount());
bool &oldValue = m_pathList[row]->downloadAtPath;
if (oldValue != downloadAtPath) {
if (downloadAtPath) {
QTemporaryFile testFile(m_pathList[row]->path + "/tmpFile");
if (!testFile.open())
return CannotWrite;
}
oldValue = downloadAtPath;
const QModelIndex &changedIndex = index(row, DownloadAtTorrentColumn);
emit dataChanged(changedIndex, changedIndex);
}
return Ok;
}
bool ScanFoldersModel::downloadInTorrentFolder(const QString &filePath) const {
const int row = findPathData(QFileInfo(filePath).dir().path());
Q_ASSERT(row != -1);
return m_pathList.at(row)->downloadAtPath;
}
int ScanFoldersModel::findPathData(const QString &path) const {
for (int i = 0; i < m_pathList.count(); ++i) {
const QSharedPointer<PathData> &pathData = m_pathList.at(i);
if (pathData->path == path)
return i;
}
return -1;
}
void ScanFoldersModel::makePersistent(QSettings &settings) {
QStringList paths;
QList<QVariant> downloadInFolderInfo;
foreach (const QSharedPointer<PathData> &pathData, m_pathList) {
paths << pathData->path;
downloadInFolderInfo << pathData->downloadAtPath;
}
settings.setValue(QString::fromUtf8("ScanDirs"), paths);
settings.setValue(QString::fromUtf8("DownloadInScanDirs"), downloadInFolderInfo);
}
ScanFoldersModel *ScanFoldersModel::m_instance = 0;

82
src/scannedfoldersmodel.h

@ -0,0 +1,82 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christian Kandeler, Christophe Dumez
*
* 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 SCANNEDFOLDERSMODEL_H
#define SCANNEDFOLDERSMODEL_H
#include <QAbstractTableModel>
#include <QList>
#include <QSharedPointer>
#include <QStringList>
class FileSystemWatcher;
class QSettings;
class ScanFoldersModel : public QAbstractTableModel {
Q_OBJECT
Q_DISABLE_COPY(ScanFoldersModel)
public:
enum PathStatus { Ok, DoesNotExist, CannotRead, CannotWrite, AlreadyInList };
static ScanFoldersModel *instance(QObject *parent = 0);
~ScanFoldersModel();
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
// TODO: removePaths(); singular version becomes private helper functions;
// also: remove functions should take modelindexes
PathStatus addPath(const QString &path);
void removePath(int row);
bool removePath(const QString &path);
PathStatus setDownloadAtPath(int row, bool downloadAtPath);
bool downloadInTorrentFolder(const QString &filePath) const;
void makePersistent(QSettings &settings);
signals:
// The absolute paths of new torrent files in the scanned directories.
void torrentsAdded(QStringList &pathList);
private:
explicit ScanFoldersModel(QObject *parent);
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
static ScanFoldersModel *m_instance;
class PathData;
int findPathData(const QString &path) const;
QList<QSharedPointer<PathData> > m_pathList;
FileSystemWatcher *m_fsWatcher;
};
#endif // SCANNEDFOLDERSMODEL_H

67
src/src.pro

@ -15,6 +15,7 @@ DEFINES += VERSION=\\\"v2.2.0beta4\\\"
DEFINES += VERSION_MAJOR=2 DEFINES += VERSION_MAJOR=2
DEFINES += VERSION_MINOR=2 DEFINES += VERSION_MINOR=2
DEFINES += VERSION_BUGFIX=0 DEFINES += VERSION_BUGFIX=0
# NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL # NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL
DEFINES += VERSION_TYPE=BETA DEFINES += VERSION_TYPE=BETA
@ -38,17 +39,14 @@ contains(DEBUG_MODE, 0) {
include(../conf.pri) include(../conf.pri)
# Target # Target
#target.path = $$BINDIR # target.path = $$BINDIR
target.path = $$PREFIX/bin/ target.path = $$PREFIX/bin/
INSTALLS += target INSTALLS += target
} }
# Man page # Man page
contains(DEFINES, DISABLE_GUI) { contains(DEFINES, DISABLE_GUI):man.files = ../doc/qbittorrent-nox.1
man.files = ../doc/qbittorrent-nox.1 else:man.files = ../doc/qbittorrent.1
} else {
man.files = ../doc/qbittorrent.1
}
man.path = $$PREFIX/share/man/man1/ man.path = $$PREFIX/share/man/man1/
INSTALLS += man INSTALLS += man
@ -94,11 +92,10 @@ contains(DEFINES, DISABLE_GUI) {
} }
contains(DEFINES, DISABLE_GUI) { contains(DEFINES, DISABLE_GUI) {
QT=core QT = core
TARGET = qbittorrent-nox TARGET = qbittorrent-nox
} else {
TARGET = qbittorrent
} }
else:TARGET = qbittorrent
# QMAKE_CXXFLAGS_RELEASE += -fwrapv # QMAKE_CXXFLAGS_RELEASE += -fwrapv
# QMAKE_CXXFLAGS_DEBUG += -fwrapv # QMAKE_CXXFLAGS_DEBUG += -fwrapv
@ -107,9 +104,8 @@ CONFIG += link_pkgconfig
PKGCONFIG += "libtorrent-rasterbar" PKGCONFIG += "libtorrent-rasterbar"
QT += network QT += network
!contains(DEFINES, DISABLE_GUI) { !contains(DEFINES, DISABLE_GUI):QT += xml
QT += xml
}
DEFINES += QT_NO_CAST_TO_ASCII DEFINES += QT_NO_CAST_TO_ASCII
# Windows # Windows
@ -127,31 +123,25 @@ win32:LIBS += -lssl32 \
DEFINES += WITH_GEOIP_EMBEDDED DEFINES += WITH_GEOIP_EMBEDDED
message("On Windows, GeoIP database must be embedded.") message("On Windows, GeoIP database must be embedded.")
} }
macx { macx {
DEFINES += WITH_GEOIP_EMBEDDED DEFINES += WITH_GEOIP_EMBEDDED
message("On Mac OS X, GeoIP database must be embedded.") message("On Mac OS X, GeoIP database must be embedded.")
} }
unix:!macx:contains(DEFINES, WITH_GEOIP_EMBEDDED):message("You chose to embed GeoIP database in qBittorrent executable.")
unix:!macx {
contains(DEFINES, WITH_GEOIP_EMBEDDED) {
message("You chose to embed GeoIP database in qBittorrent executable.")
}
}
# Add GeoIP resource file if the GeoIP database # Add GeoIP resource file if the GeoIP database
# should be embedded in qBittorrent executable # should be embedded in qBittorrent executable
contains(DEFINES, WITH_GEOIP_EMBEDDED) { contains(DEFINES, WITH_GEOIP_EMBEDDED) {
exists("geoip/GeoIP.dat") { exists("geoip/GeoIP.dat") {
message("GeoIP.dat was found in src/geoip/.") message("GeoIP.dat was found in src/geoip/.")
RESOURCES += geoip.qrc RESOURCES += geoip.qrc
} else { }
DEFINES -= WITH_GEOIP_EMBEDDED else {
error("GeoIP.dat was not found in src/geoip/ folder, please follow instructions in src/geoip/README.") DEFINES -= WITH_GEOIP_EMBEDDED
} error("GeoIP.dat was not found in src/geoip/ folder, please follow instructions in src/geoip/README.")
} else { }
message("GeoIP database will not be embedded in qBittorrent executable.")
} }
else:message("GeoIP database will not be embedded in qBittorrent executable.")
} }
# Resource files # Resource files
@ -206,12 +196,11 @@ HEADERS += misc.h \
torrentpersistentdata.h \ torrentpersistentdata.h \
filesystemwatcher.h \ filesystemwatcher.h \
preferences.h \ preferences.h \
bandwidthscheduler.h bandwidthscheduler.h \
scannedfoldersmodel.h
contains(DEFINES, DISABLE_GUI) { contains(DEFINES, DISABLE_GUI):HEADERS += headlessloader.h
HEADERS += headlessloader.h else:HEADERS += GUI.h \
} else {
HEADERS += GUI.h \
feedList.h \ feedList.h \
supportedengines.h \ supportedengines.h \
transferlistwidget.h \ transferlistwidget.h \
@ -252,10 +241,8 @@ contains(DEFINES, DISABLE_GUI) {
trackerlogin.h \ trackerlogin.h \
pieceavailabilitybar.h \ pieceavailabilitybar.h \
advancedsettings.h advancedsettings.h
}
!contains(DEFINES, DISABLE_GUI) { !contains(DEFINES, DISABLE_GUI):FORMS += ui/mainwindow.ui \
FORMS += ui/mainwindow.ui \
ui/options.ui \ ui/options.ui \
ui/about.ui \ ui/about.ui \
ui/createtorrent.ui \ ui/createtorrent.ui \
@ -274,7 +261,6 @@ contains(DEFINES, DISABLE_GUI) {
ui/propertieswidget.ui \ ui/propertieswidget.ui \
ui/peer.ui \ ui/peer.ui \
ui/confirmdeletiondlg.ui ui/confirmdeletiondlg.ui
}
SOURCES += main.cpp \ SOURCES += main.cpp \
bittorrent.cpp \ bittorrent.cpp \
@ -284,10 +270,10 @@ SOURCES += main.cpp \
httpconnection.cpp \ httpconnection.cpp \
httprequestparser.cpp \ httprequestparser.cpp \
httpresponsegenerator.cpp \ httpresponsegenerator.cpp \
eventmanager.cpp eventmanager.cpp \
scannedfoldersmodel.cpp
!contains(DEFINES, DISABLE_GUI) { !contains(DEFINES, DISABLE_GUI):SOURCES += GUI.cpp \
SOURCES += GUI.cpp \
options_imp.cpp \ options_imp.cpp \
createtorrent_imp.cpp \ createtorrent_imp.cpp \
searchengine.cpp \ searchengine.cpp \
@ -299,6 +285,5 @@ SOURCES += main.cpp \
transferlistwidget.cpp \ transferlistwidget.cpp \
propertieswidget.cpp \ propertieswidget.cpp \
peerlistwidget.cpp peerlistwidget.cpp
}
DESTDIR = . DESTDIR = .

202
src/ui/options.ui

@ -565,10 +565,10 @@ QGroupBox {
<widget class="QWidget" name="scrollAreaWidgetContents_2"> <widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>-30</x>
<y>-76</y> <y>0</y>
<width>644</width> <width>632</width>
<height>548</height> <height>684</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_17"> <layout class="QVBoxLayout" name="verticalLayout_17">
@ -583,7 +583,7 @@ QGroupBox {
<property name="title"> <property name="title">
<string>File system</string> <string>File system</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_12"> <layout class="QVBoxLayout" name="verticalLayout_25">
<item> <item>
<widget class="QGroupBox" name="groupBox_3"> <widget class="QGroupBox" name="groupBox_3">
<property name="styleSheet"> <property name="styleSheet">
@ -696,57 +696,120 @@ QGroupBox {
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="checkScanDir"> <widget class="QGroupBox" name="groupBox_2">
<property name="text"> <property name="title">
<string>Automatically load .torrent files from:</string> <string>Check Folders for .torrent Files:</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_38">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QTableView" name="scanFoldersView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>150</height>
</size>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>80</number>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>80</number>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_37">
<item>
<widget class="QPushButton" name="addScanFolderButton">
<property name="text">
<string>Add folder ...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeScanFolderButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove folder</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="textScanDir">
<property name="enabled">
<bool>false</bool>
</property>
<property name="styleSheet">
<string>QLineEdit {
margin-left: 23px;
}</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="browseScanDirButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>27</height>
</size>
</property>
<property name="icon">
<iconset resource="../icons.qrc">
<normaloff>:/Icons/oxygen/browse.png</normaloff>:/Icons/oxygen/browse.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QCheckBox" name="checkExportDir"> <widget class="QCheckBox" name="checkExportDir">
<property name="text"> <property name="text">
@ -1060,8 +1123,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>447</width>
<height>482</height> <height>288</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_28"> <layout class="QVBoxLayout" name="verticalLayout_28">
@ -1305,8 +1368,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>364</width>
<height>490</height> <height>332</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_33"> <layout class="QVBoxLayout" name="verticalLayout_33">
@ -1710,8 +1773,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>459</width>
<height>490</height> <height>415</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_20"> <layout class="QVBoxLayout" name="verticalLayout_20">
@ -2127,8 +2190,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>475</width>
<height>490</height> <height>312</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_16"> <layout class="QVBoxLayout" name="verticalLayout_16">
@ -2561,8 +2624,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>287</width>
<height>490</height> <height>124</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_21"> <layout class="QVBoxLayout" name="verticalLayout_21">
@ -2658,8 +2721,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>213</width>
<height>490</height> <height>221</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_23"> <layout class="QVBoxLayout" name="verticalLayout_23">
@ -2825,8 +2888,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>445</width>
<height>490</height> <height>192</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_24"> <layout class="QVBoxLayout" name="verticalLayout_24">
@ -3000,8 +3063,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>96</width>
<height>490</height> <height>26</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_36"/> <layout class="QVBoxLayout" name="verticalLayout_36"/>
@ -3062,7 +3125,6 @@ QGroupBox {
<tabstop>checkPreallocateAll</tabstop> <tabstop>checkPreallocateAll</tabstop>
<tabstop>checkAdditionDialog</tabstop> <tabstop>checkAdditionDialog</tabstop>
<tabstop>checkStartPaused</tabstop> <tabstop>checkStartPaused</tabstop>
<tabstop>browseScanDirButton</tabstop>
<tabstop>spinPort</tabstop> <tabstop>spinPort</tabstop>
<tabstop>checkUPnP</tabstop> <tabstop>checkUPnP</tabstop>
<tabstop>checkNATPMP</tabstop> <tabstop>checkNATPMP</tabstop>

Loading…
Cancel
Save