Browse Source

Rewrote folder scanning code (Now uses a filesystem watcher)

adaptive-webui-19844
Christophe Dumez 16 years ago
parent
commit
14646d0f9e
  1. 2
      Changelog
  2. 16
      src/GUI.cpp
  3. 1
      src/GUI.h
  4. 75
      src/bittorrent.cpp
  5. 11
      src/bittorrent.h
  6. 31
      src/options.ui
  7. 13
      src/options_imp.cpp
  8. 1
      src/options_imp.h
  9. 1
      src/search_engine/engines/mininova.py

2
Changelog

@ -12,10 +12,12 @@
- FEATURE: Got rid of libmagick++ dependency - FEATURE: Got rid of libmagick++ dependency
- FEATURE: Updated Web interface to MochaUI v0.9.5 - FEATURE: Updated Web interface to MochaUI v0.9.5
- FEATURE: Added notification in WebUI when qBittorrent is not reachable - FEATURE: Added notification in WebUI when qBittorrent is not reachable
- FEATURE: Rewrote folder scanning code (Now uses a filesystem watcher)
- BUGFIX: Fixed several memory leaks - BUGFIX: Fixed several memory leaks
- BUGFIX: WebUI is now working with IE7 - BUGFIX: WebUI is now working with IE7
- BUGFIX: Fixed spacing problem in toolbar when toggling its visibility - BUGFIX: Fixed spacing problem in toolbar when toggling its visibility
- BUGFIX: Fixed some compilation and Qt4 warnings - BUGFIX: Fixed some compilation and Qt4 warnings
- BUGFIX: Do not use an addition dialog for torrents from folder scanning
* Sun Nov 9 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.1 * Sun Nov 9 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.1
- BUGFIX: Fixed possible crash when deleting a torrent permanently - BUGFIX: Fixed possible crash when deleting a torrent permanently

16
src/GUI.cpp

@ -122,7 +122,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&)), this, SLOT(fullDiskError(QTorrentHandle&))); connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&)), this, SLOT(fullDiskError(QTorrentHandle&)));
connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&))); connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&)));
connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&))); connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&)));
connect(BTSession, SIGNAL(scanDirFoundTorrents(const QStringList&)), this, SLOT(processScannedFiles(const QStringList&)));
connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString))); connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString)));
connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString))); connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
connect(BTSession, SIGNAL(deletedTorrent(QString)), this, SLOT(deleteTorrent(QString))); connect(BTSession, SIGNAL(deletedTorrent(QString)), this, SLOT(deleteTorrent(QString)));
@ -869,20 +868,6 @@ void GUI::addTorrent(QString path) {
BTSession->addTorrent(path); BTSession->addTorrent(path);
} }
void GUI::processScannedFiles(const QStringList& params) {
QString param;
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
foreach(param, params) {
if(useTorrentAdditionDialog) {
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
dialog->showLoad(param, true);
}else{
BTSession->addTorrent(param, true);
}
}
}
void GUI::processDownloadedFiles(QString path, QString url) { void GUI::processDownloadedFiles(QString path, QString url) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
@ -927,7 +912,6 @@ void GUI::configureSession(bool deleteOptions) {
BTSession->disableDirectoryScanning(); BTSession->disableDirectoryScanning();
}else{ }else{
//Interval first //Interval first
BTSession->setTimerScanInterval(options->getFolderScanInterval());
BTSession->enableDirectoryScanning(options->getScanDir()); BTSession->enableDirectoryScanning(options->getScanDir());
} }
// Connection // Connection

1
src/GUI.h

@ -156,7 +156,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void processParams(const QStringList& params); void processParams(const QStringList& params);
void addTorrent(QString path); void addTorrent(QString path);
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker); void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
void processScannedFiles(const QStringList& params);
void processDownloadedFiles(QString path, QString url); void processDownloadedFiles(QString path, QString url);
void downloadFromURLList(const QStringList& urls); void downloadFromURLList(const QStringList& urls);
void deleteTorrent(QString hash); void deleteTorrent(QString hash);

75
src/bittorrent.cpp

@ -23,7 +23,9 @@
#include <QTime> #include <QTime>
#include <QString> #include <QString>
#include <QTimer> #include <QTimer>
#include <QFileSystemWatcher>
#include <QSettings> #include <QSettings>
#include <QMutex>
#include "bittorrent.h" #include "bittorrent.h"
#include "misc.h" #include "misc.h"
@ -43,7 +45,7 @@
#define MAX_TRACKER_ERRORS 2 #define MAX_TRACKER_ERRORS 2
// Main constructor // Main constructor
bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), folderScanInterval(5), queueingEnabled(false) { bittorrent::bittorrent() : DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), queueingEnabled(false) {
// To avoid some exceptions // To avoid some exceptions
fs::path::default_name_check(fs::no_check); fs::path::default_name_check(fs::no_check);
// Creating bittorrent session // Creating bittorrent session
@ -73,6 +75,7 @@ bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
BigRatioTimer = 0; BigRatioTimer = 0;
filterParser = 0; filterParser = 0;
FSWatcher = 0;
qDebug("* BTSession constructed"); qDebug("* BTSession constructed");
} }
@ -437,7 +440,7 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bo
QTorrentHandle h; QTorrentHandle h;
bool fastResume=false; bool fastResume=false;
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup"); QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
QString file, dest_file, scan_dir; QString file, dest_file;
// Checking if BT_backup Dir exists // Checking if BT_backup Dir exists
// create it if it is not // create it if it is not
@ -469,11 +472,10 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bo
} }
addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red")); addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red"));
if(fromScanDir) { if(fromScanDir) {
// Remove .corrupt file in case it already exists // Remove file
QFile::remove(file+".corrupt"); QFile::remove(file);
//Rename file extension so that it won't display error message more than once
QFile::rename(file,file+".corrupt");
} }
return;
} }
qDebug(" -> Hash: %s", misc::toString(t->info_hash()).c_str()); qDebug(" -> Hash: %s", misc::toString(t->info_hash()).c_str());
qDebug(" -> Name: %s", t->name().c_str()); qDebug(" -> Name: %s", t->name().c_str());
@ -979,56 +981,49 @@ bool bittorrent::isFilePreviewPossible(QString hash) const{
// Scan the first level of the directory for torrent files // Scan the first level of the directory for torrent files
// and add them to download list // and add them to download list
void bittorrent::scanDirectory() { void bittorrent::scanDirectory(QString scan_dir) {
FSMutex->lock();
qDebug("Scanning directory: %s", scan_dir.toUtf8().data());
QString file; QString file;
if(!scan_dir.isNull()) { QDir dir(scan_dir);
QStringList to_add; QStringList filters;
QDir dir(scan_dir); filters << "*.torrent";
QStringList filters; QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
filters << "*.torrent"; foreach(file, files) {
QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
foreach(file, files) {
QString fullPath = dir.path()+QDir::separator()+file; QString fullPath = dir.path()+QDir::separator()+file;
QFile::rename(fullPath, fullPath+QString::fromUtf8(".old")); QFile torrent(fullPath);
to_add << fullPath+QString::fromUtf8(".old"); if(torrent.size() != 0) {
} qDebug("Adding for scan_dir: %s", fullPath.toUtf8().data());
emit scanDirFoundTorrents(to_add); addTorrent(fullPath, true);
} else {
qDebug("Ignoring empty file: %s", fullPath.toUtf8().data());
}
} }
FSMutex->unlock();
} }
void bittorrent::setDefaultSavePath(QString savepath) { void bittorrent::setDefaultSavePath(QString savepath) {
defaultSavePath = savepath; defaultSavePath = savepath;
} }
void bittorrent::setTimerScanInterval(int secs) {
if(folderScanInterval != secs) {
folderScanInterval = secs;
if(!scan_dir.isNull()) {
timerScan->start(folderScanInterval*1000);
}
}
}
// Enable directory scanning // Enable directory scanning
void bittorrent::enableDirectoryScanning(QString _scan_dir) { void bittorrent::enableDirectoryScanning(QString scan_dir) {
if(!_scan_dir.isEmpty()) { if(!scan_dir.isEmpty()) {
scan_dir = _scan_dir; Q_ASSERT(FSWatcher == 0);
timerScan = new QTimer(this); FSMutex = new QMutex();
connect(timerScan, SIGNAL(timeout()), this, SLOT(scanDirectory())); FSWatcher = new QFileSystemWatcher(QStringList(scan_dir), this);
timerScan->start(folderScanInterval*1000); connect(FSWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(scanDirectory(QString)));
// Initial scan
scanDirectory(scan_dir);
} }
} }
// Disable directory scanning // Disable directory scanning
void bittorrent::disableDirectoryScanning() { void bittorrent::disableDirectoryScanning() {
if(!scan_dir.isNull()) { if(FSWatcher) {
scan_dir = QString::null; delete FSWatcher;
if(timerScan->isActive()) { delete FSMutex;
timerScan->stop();
}
} }
if(timerScan)
delete timerScan;
} }
// Set the ports range in which is chosen the port the bittorrent // Set the ports range in which is chosen the port the bittorrent

11
src/bittorrent.h

@ -35,6 +35,8 @@ using namespace libtorrent;
class downloadThread; class downloadThread;
class QTimer; class QTimer;
class QFileSystemWatcher;
class QMutex;
class FilterParserThread; class FilterParserThread;
class bittorrent : public QObject { class bittorrent : public QObject {
@ -42,8 +44,8 @@ class bittorrent : public QObject {
private: private:
session *s; session *s;
QString scan_dir; QPointer<QFileSystemWatcher> FSWatcher;
QPointer<QTimer> timerScan; QMutex* FSMutex;
QPointer<QTimer> timerAlerts; QPointer<QTimer> timerAlerts;
QPointer<QTimer> BigRatioTimer; QPointer<QTimer> BigRatioTimer;
bool DHTEnabled; bool DHTEnabled;
@ -64,7 +66,6 @@ class bittorrent : public QObject {
bool LSDEnabled; bool LSDEnabled;
QPointer<FilterParserThread> filterParser; QPointer<FilterParserThread> filterParser;
QString filterPath; QString filterPath;
int folderScanInterval; // in seconds
bool queueingEnabled; bool queueingEnabled;
QStringList url_skippingDlg; QStringList url_skippingDlg;
@ -157,12 +158,11 @@ class bittorrent : public QObject {
void enableNATPMP(bool b); void enableNATPMP(bool b);
void enableLSD(bool b); void enableLSD(bool b);
bool enableDHT(bool b); bool enableDHT(bool b);
void setTimerScanInterval(int secs);
void addConsoleMessage(QString msg, QColor color=QApplication::palette().color(QPalette::WindowText)); void addConsoleMessage(QString msg, QColor color=QApplication::palette().color(QPalette::WindowText));
void addPeerBanMessage(QString msg, bool from_ipfilter); void addPeerBanMessage(QString msg, bool from_ipfilter);
protected slots: protected slots:
void scanDirectory(); void scanDirectory(QString);
void readAlerts(); void readAlerts();
void processDownloadedFile(QString, QString); void processDownloadedFile(QString, QString);
bool loadTrackerFile(QString hash); bool loadTrackerFile(QString hash);
@ -178,7 +178,6 @@ class bittorrent : public QObject {
void fullDiskError(QTorrentHandle& h); void fullDiskError(QTorrentHandle& h);
void trackerError(QString hash, QString time, QString msg); void trackerError(QString hash, QString time, QString msg);
void trackerAuthenticationRequired(QTorrentHandle& h); void trackerAuthenticationRequired(QTorrentHandle& h);
void scanDirFoundTorrents(const QStringList& pathList);
void newDownloadedTorrent(QString path, QString url); void newDownloadedTorrent(QString path, QString url);
void updateFileSize(QString hash); void updateFileSize(QString hash);
void downloadFromUrlFailure(QString url, QString reason); void downloadFromUrlFailure(QString url, QString reason);

31
src/options.ui

@ -497,37 +497,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="FolderScanLbl" >
<property name="text" >
<string>Folder scan interval:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="FolderScanSpin" >
<property name="minimum" >
<number>1</number>
</property>
<property name="maximum" >
<number>9999</number>
</property>
<property name="value" >
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="FolderScanLbl2" >
<property name="text" >
<string>seconds</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

13
src/options_imp.cpp

@ -174,7 +174,6 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){
connect(checkStartPaused, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); connect(checkStartPaused, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton()));
connect(checkScanDir, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); connect(checkScanDir, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton()));
connect(textScanDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton())); connect(textScanDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(FolderScanSpin, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton()));
// Connection tab // Connection tab
connect(spinPortMin, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton())); connect(spinPortMin, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton()));
connect(spinPortMax, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton())); connect(spinPortMax, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton()));
@ -302,7 +301,6 @@ void options_imp::saveOptions(){
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()); settings.setValue(QString::fromUtf8("ScanDir"), getScanDir());
settings.setValue(QString::fromUtf8("ScanDirInterval"), getFolderScanInterval());
settings.setValue(QString::fromUtf8("DblClOnTorDl"), getActionOnDblClOnTorrentDl()); settings.setValue(QString::fromUtf8("DblClOnTorDl"), getActionOnDblClOnTorrentDl());
settings.setValue(QString::fromUtf8("DblClOnTorFn"), getActionOnDblClOnTorrentFn()); settings.setValue(QString::fromUtf8("DblClOnTorFn"), getActionOnDblClOnTorrentFn());
// End Downloads preferences // End Downloads preferences
@ -513,7 +511,6 @@ void options_imp::loadOptions(){
// enable // enable
checkScanDir->setChecked(true); checkScanDir->setChecked(true);
textScanDir->setText(strValue); textScanDir->setText(strValue);
FolderScanSpin->setValue(settings.value(QString::fromUtf8("ScanDirInterval"), 5).toInt());
enableDirScan(2); enableDirScan(2);
} }
actionTorrentDlOnDblClBox->setCurrentIndex(settings.value(QString::fromUtf8("DblClOnTorDl"), 0).toInt()); actionTorrentDlOnDblClBox->setCurrentIndex(settings.value(QString::fromUtf8("DblClOnTorDl"), 0).toInt());
@ -1112,23 +1109,13 @@ void options_imp::enableDirScan(int checkBoxValue){
//enable //enable
textScanDir->setEnabled(true); textScanDir->setEnabled(true);
browseScanDirButton->setEnabled(true); browseScanDirButton->setEnabled(true);
FolderScanSpin->setEnabled(true);
FolderScanLbl->setEnabled(true);
FolderScanLbl2->setEnabled(true);
}else{ }else{
//disable //disable
textScanDir->setEnabled(false); textScanDir->setEnabled(false);
browseScanDirButton->setEnabled(false); browseScanDirButton->setEnabled(false);
FolderScanSpin->setEnabled(false);
FolderScanLbl->setEnabled(false);
FolderScanLbl2->setEnabled(false);
} }
} }
int options_imp::getFolderScanInterval() const {
return FolderScanSpin->value();
}
bool options_imp::speedInTitleBar() const { bool options_imp::speedInTitleBar() const {
return checkSpeedInTitle->isChecked(); return checkSpeedInTitle->isChecked();
} }

1
src/options_imp.h

@ -74,7 +74,6 @@ class options_imp : public QDialog, private Ui::Dialog {
bool addTorrentsInPause() const; bool addTorrentsInPause() const;
bool isDirScanEnabled() const; bool isDirScanEnabled() const;
QString getScanDir() const; QString getScanDir() const;
int getFolderScanInterval() const;
int getActionOnDblClOnTorrentDl() const; int getActionOnDblClOnTorrentDl() const;
int getActionOnDblClOnTorrentFn() const; int getActionOnDblClOnTorrentFn() const;
// Connection options // Connection options

1
src/search_engine/engines/mininova.py

@ -36,7 +36,6 @@ class mininova(object):
table_items = 'added cat name size seeds leech'.split() table_items = 'added cat name size seeds leech'.split()
def search(self, what): def search(self, what):
order = 'seeds' # must be one in self.table_items
def get_link(lnk): def get_link(lnk):
lnks = lnk.getElementsByTagName('a') lnks = lnk.getElementsByTagName('a')

Loading…
Cancel
Save