mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-15 01:33:07 -07:00
FEATURE: Support for multiple scan folders
* Patch by Christian Kandeler (Thanks!)
This commit is contained in:
parent
4d5001d18d
commit
7710c88797
13 changed files with 601 additions and 270 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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")));
|
||||||
}
|
|
||||||
if(!torrents.empty())
|
|
||||||
emit torrentsAdded(torrents);
|
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);
|
||||||
|
}
|
||||||
|
// Report detected torrent files
|
||||||
|
if(!torrents.empty()) {
|
||||||
|
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||||
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
|
||||||
if(path.isEmpty())
|
|
||||||
path = QString();
|
|
||||||
QSettings settings("qBittorrent", "qBittorrent");
|
QSettings settings("qBittorrent", "qBittorrent");
|
||||||
settings.setValue(QString::fromUtf8("Preferences/Downloads/ScanDir"), path);
|
return settings.value(QString::fromUtf8("Preferences/Downloads/DownloadInScanDirs"), QVariantList()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setDownloadInScanDirs(const QVariantList &list) {
|
||||||
|
QSettings settings("qBittorrent", "qBittorrent");
|
||||||
|
settings.setValue(QString::fromUtf8("Preferences/Downloads/DownloadInScanDirs"), list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isTorrentExportEnabled() {
|
static bool isTorrentExportEnabled() {
|
||||||
|
|
|
@ -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
Normal file
191
src/scannedfoldersmodel.cpp
Normal file
|
@ -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
Normal file
82
src/scannedfoldersmodel.h
Normal file
|
@ -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
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 = .
|
||||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue