Compare commits
39 Commits
release-2.
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6452a6ec93 | ||
|
|
f845acb207 | ||
|
|
f42eec5ad9 | ||
|
|
ec1a06d7c8 | ||
|
|
e9b6a726e3 | ||
|
|
a3f54fc3b9 | ||
|
|
10f58b4eed | ||
|
|
52fef5ac38 | ||
|
|
4d0cdea1c9 | ||
|
|
86ca755dfe | ||
|
|
659664509a | ||
|
|
412f947db5 | ||
|
|
ad47565b93 | ||
|
|
89175ea827 | ||
|
|
8dc34463e3 | ||
|
|
cab38857d1 | ||
|
|
14db21c241 | ||
|
|
975ab9ad64 | ||
|
|
b810278452 | ||
|
|
86ac0a430e | ||
|
|
78a0f34645 | ||
|
|
3ae09658c9 | ||
|
|
7d9caad31e | ||
|
|
c9c627dec2 | ||
|
|
5b104cdd9b | ||
|
|
8f667dce5c | ||
|
|
89412e5050 | ||
|
|
63c121ecc7 | ||
|
|
33b60779d6 | ||
|
|
26b2367833 | ||
|
|
9b40a036a7 | ||
|
|
d4cc0e9e4a | ||
|
|
ca802a6233 | ||
|
|
35394c4966 | ||
|
|
077dd11af6 | ||
|
|
a5c9c8d670 | ||
|
|
1ef0bcbc06 | ||
|
|
e15eab9b6a | ||
|
|
8f1c56babd |
5
AUTHORS
@@ -6,7 +6,6 @@ Contributors:
|
|||||||
* Ishan Arora <ishan@qbittorrent.org>
|
* Ishan Arora <ishan@qbittorrent.org>
|
||||||
* Arnaud Demaizière <arnaud@qbittorrent.org>
|
* Arnaud Demaizière <arnaud@qbittorrent.org>
|
||||||
* Grigis Gaëtan <cipher16@gmail.com>
|
* Grigis Gaëtan <cipher16@gmail.com>
|
||||||
* Christian Kandeler <zambesi@users.sourceforge.net>
|
|
||||||
|
|
||||||
Code from other projects:
|
Code from other projects:
|
||||||
* files src/ico.cpp src/ico.h
|
* files src/ico.cpp src/ico.h
|
||||||
@@ -61,7 +60,7 @@ Translations authors:
|
|||||||
* files: src/lang/*.ts
|
* files: src/lang/*.ts
|
||||||
copyright:
|
copyright:
|
||||||
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
|
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
|
||||||
- Bulgarian: Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)
|
- Bulgarian: Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)
|
||||||
- Catalan: Francisco Luque Contreras (frannoe@ya.com)
|
- Catalan: Francisco Luque Contreras (frannoe@ya.com)
|
||||||
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
|
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
|
||||||
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
|
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
|
||||||
@@ -87,5 +86,5 @@ Translations authors:
|
|||||||
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
|
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
|
||||||
- Swedish: Daniel Nylander (po@danielnylander.se)
|
- Swedish: Daniel Nylander (po@danielnylander.se)
|
||||||
- Turkish: Hasan Yilmaz (iletisim@hedefturkce.com)
|
- Turkish: Hasan Yilmaz (iletisim@hedefturkce.com)
|
||||||
- Ukrainian: Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)
|
- Ukrainian: Andrey Shpachenko (masterfix@users.sourceforge.net)
|
||||||
license: GPLv2
|
license: GPLv2
|
||||||
|
|||||||
57
Changelog
@@ -1,36 +1,29 @@
|
|||||||
* Sat Mar 20 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.1
|
* Sun Jan 24 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.2
|
||||||
- FEATURE: Display pieces that are being downloaded
|
- FEATURE: Added back file prioritizing in a torrent
|
||||||
- FEATURE: Added back folder watching in Web UI
|
- BUGFIX: Fix issue causing torrents not to be displayed in the list
|
||||||
- FEATURE: Added back file prioritizing in Web UI
|
- BUGFIX: Make sure invalid torrent are removed from the transfer list
|
||||||
- BUGFIX: Fix compilation with Qt 4.4
|
- BUGFIX: Fix overwrite check when renaming a folder in a torrent
|
||||||
- BUGFIX: Fix Web UI compatibility with Safari
|
- BUGFIX: Force a recheck after renaming files to avoid overwriting
|
||||||
- BUGFIX: Fix progress display with cleanlook style
|
- BUGFIX: Improve "Open destination folder" behavior
|
||||||
- BUGFIX: Fix file filtering in complex torrents
|
- BUGFIX: Fix race condition in RSS that could cause a crash on startup
|
||||||
- BUGFIX: Ask for user confirmation for recursive torrent download
|
- BUGFIX: Improved user friendlyness of size units
|
||||||
- BUGFIX: Fix "add file" dialog in torrent creation tool
|
- BUGFIX: Optimized transfer list repainting
|
||||||
- BUGFIX: Fix "Ctrl+A" in Web UI
|
- COSMETIC: Improved transfer speed display in peers list
|
||||||
|
|
||||||
* Sun Mar 14 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.0
|
* Wed Jan 20 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.1
|
||||||
- FEATURE: User can set alternative speed limits for fast toggling
|
- BUGFIX: Fix compilation with Qt4.4
|
||||||
- FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period)
|
- BUGFIX: Save torrent metadata so that it does not have to be re-downloaded on restart (Magnet links)
|
||||||
- FEATURE: Added "Added/Completed On" columns to transfer list
|
- BUGFIX: Fix folder renaming in a torrent (would rename children under certain conditions)
|
||||||
- FEATURE: Added "Upload/Download limit" columns to transfer list
|
- BUGFIX: Nox version no longer requires libQtXml
|
||||||
- FEATURE: Torrent files can be exported to a given directory
|
- BUGFIX: Configure file now checks for pkg-config executable which is required
|
||||||
- FEATURE: Outgoing ports range can be customized (for QoS)
|
- BUGFIX: Torrents added from magnet links were not remembered on restart
|
||||||
- FEATURE: User can choose to apply transfer limits on LAN too
|
- BUGFIX: "Add in pause" setting can be ignored from torrent addition dialog
|
||||||
- FEATURE: User can choose to include the protocol overhead in transfer limits
|
- BUGFIX: Fix renaming of files with unicode characters in their name
|
||||||
- FEATURE: Torrents can be automatically rechecked on completion
|
- BUGFIX: Fix typo in legal notice (startup)
|
||||||
- FEATURE: If 2 torrents have the same hash, add new trackers/URL seeds to the existing torrent
|
- BUGFIX: Can listen on ports < 1024 (must be root)
|
||||||
- FEATURE: Trackers can be added from Web UI
|
- BUGFIX: Paused torrents can now be rechecked
|
||||||
- FEATURE: Global transfer information are displayed in the new Web UI status bar
|
- BUGFIX: Fix "open torrent destination" feature when path contains spaces
|
||||||
- FEATURE: Allow to change the priority of several files at once
|
- I18N: Updated translations (Hungarian, Chinese, Russian)
|
||||||
- FEATURE: Support for multiple scan folders (Patch by Christian Kandeler)
|
|
||||||
- BUGFIX: Only one log window can be opened at a time
|
|
||||||
- BUGFIX: Optimized RSS module memory usage
|
|
||||||
- BUGFIX: Consider HTTP downloads >1MB as invalid .torrent files and abort
|
|
||||||
- BUGFIX: Fix Web UI authentication with some browsers
|
|
||||||
- BUGFIX: Set Web UI ban period to 1 hour
|
|
||||||
- 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
|
||||||
- FEATURE: Graphical User Interface can be disabled at compilation time (headless running)
|
- FEATURE: Graphical User Interface can be disabled at compilation time (headless running)
|
||||||
|
|||||||
14
configure
vendored
@@ -312,7 +312,11 @@ public:
|
|||||||
if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||||
conf->addDefine("DISABLE_GUI");
|
conf->addDefine("DISABLE_GUI");
|
||||||
}
|
}
|
||||||
|
if(QT_VERSION >= 0x040500) {
|
||||||
|
conf->addDefine("QT_4_5");
|
||||||
|
}
|
||||||
return(QT_VERSION >= 0x040400);
|
return(QT_VERSION >= 0x040400);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#line 1 "pkg-config.qcm"
|
#line 1 "pkg-config.qcm"
|
||||||
@@ -355,18 +359,12 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
for(int n = 0; n < incs.count(); ++n)
|
for(int n = 0; n < incs.count(); ++n)
|
||||||
conf->addIncludePath(incs[n]);
|
conf->addIncludePath(incs[n]);
|
||||||
//if(!libs.isEmpty())
|
if(!libs.isEmpty())
|
||||||
// conf->addLib(libs);
|
conf->addLib(libs);
|
||||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
||||||
printf("\nWarning: libtorrent-rasterbar v%s was detected. Some feature will be disabled because they require v%s.\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
|
printf("\nWarning: libtorrent-rasterbar v%s was detected. Some feature will be disabled because they require v%s.\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
|
||||||
else
|
else
|
||||||
conf->addDefine("LIBTORRENT_0_15");
|
conf->addDefine("LIBTORRENT_0_15");
|
||||||
// Get linking parameters
|
|
||||||
QStringList params;
|
|
||||||
QByteArray staticlibs;
|
|
||||||
params << "--static" << "--libs" << "libtorrent-rasterbar";
|
|
||||||
conf->doCommand("pkg-config", params, &staticlibs);
|
|
||||||
conf->addLib(staticlibs.trimmed());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,18 +20,12 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
for(int n = 0; n < incs.count(); ++n)
|
for(int n = 0; n < incs.count(); ++n)
|
||||||
conf->addIncludePath(incs[n]);
|
conf->addIncludePath(incs[n]);
|
||||||
//if(!libs.isEmpty())
|
if(!libs.isEmpty())
|
||||||
// conf->addLib(libs);
|
conf->addLib(libs);
|
||||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
||||||
printf("\nWarning: libtorrent-rasterbar v%s was detected. Some feature will be disabled because they require v%s.\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
|
printf("\nWarning: libtorrent-rasterbar v%s was detected. Some feature will be disabled because they require v%s.\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
|
||||||
else
|
else
|
||||||
conf->addDefine("LIBTORRENT_0_15");
|
conf->addDefine("LIBTORRENT_0_15");
|
||||||
// Get linking parameters
|
|
||||||
QStringList params;
|
|
||||||
QByteArray staticlibs;
|
|
||||||
params << "--static" << "--libs" << "libtorrent-rasterbar";
|
|
||||||
conf->doCommand("pkg-config", params, &staticlibs);
|
|
||||||
conf->addLib(staticlibs.trimmed());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ public:
|
|||||||
if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||||
conf->addDefine("DISABLE_GUI");
|
conf->addDefine("DISABLE_GUI");
|
||||||
}
|
}
|
||||||
|
if(QT_VERSION >= 0x040500) {
|
||||||
|
conf->addDefine("QT_4_5");
|
||||||
|
}
|
||||||
return(QT_VERSION >= 0x040400);
|
return(QT_VERSION >= 0x040400);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
136
src/GUI.cpp
105
src/GUI.h
@@ -55,28 +55,43 @@ class TransferListFiltersWidget;
|
|||||||
class QSplitter;
|
class QSplitter;
|
||||||
class PropertiesWidget;
|
class PropertiesWidget;
|
||||||
class StatusBar;
|
class StatusBar;
|
||||||
class consoleDlg;
|
|
||||||
class about;
|
|
||||||
class createtorrent;
|
|
||||||
class downloadFromURL;
|
|
||||||
|
|
||||||
class GUI : public QMainWindow, private Ui::MainWindow{
|
class GUI : public QMainWindow, private Ui::MainWindow{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
private:
|
||||||
// Construct / Destruct
|
// Bittorrent
|
||||||
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
|
Bittorrent *BTSession;
|
||||||
~GUI();
|
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; // Still needed?
|
||||||
// Methods
|
// GUI related
|
||||||
int getCurrentTabIndex() const;
|
QTimer *guiUpdater;
|
||||||
TransferListWidget* getTransferList() const { return transferList; }
|
QTabWidget *tabs;
|
||||||
|
StatusBar *status_bar;
|
||||||
public slots:
|
QPointer<options_imp> options;
|
||||||
void trackerAuthenticationRequired(QTorrentHandle& h);
|
QPointer<QSystemTrayIcon> systrayIcon;
|
||||||
void setTabText(int index, QString text) const;
|
QPointer<QTimer> systrayCreator;
|
||||||
void showNotificationBaloon(QString title, QString msg) const;
|
QMenu *myTrayIconMenu;
|
||||||
void downloadFromURLList(const QStringList& urls);
|
TransferListWidget *transferList;
|
||||||
void updateAltSpeedsBtn(bool alternative);
|
TransferListFiltersWidget *transferListFilters;
|
||||||
|
PropertiesWidget *properties;
|
||||||
|
bool displaySpeedInTitle;
|
||||||
|
bool force_exit;
|
||||||
|
// Keyboard shortcuts
|
||||||
|
QShortcut *switchSearchShortcut;
|
||||||
|
QShortcut *switchSearchShortcut2;
|
||||||
|
QShortcut *switchTransferShortcut;
|
||||||
|
QShortcut *switchRSSShortcut;
|
||||||
|
// Widgets
|
||||||
|
QAction *prioSeparator;
|
||||||
|
QAction *prioSeparator2;
|
||||||
|
QSplitter *hSplitter;
|
||||||
|
QSplitter *vSplitter;
|
||||||
|
// Search
|
||||||
|
SearchEngine *searchEngine;
|
||||||
|
// RSS
|
||||||
|
QPointer<RSSImp> rssWidget;
|
||||||
|
// Misc
|
||||||
|
QLocalServer *localServer;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
// GUI related slots
|
// GUI related slots
|
||||||
@@ -113,59 +128,35 @@ protected slots:
|
|||||||
void loadPreferences(bool configure_session=true);
|
void loadPreferences(bool configure_session=true);
|
||||||
void processParams(const QStringList& params);
|
void processParams(const QStringList& params);
|
||||||
void addTorrent(QString path);
|
void addTorrent(QString path);
|
||||||
void addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker);
|
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
|
||||||
void processDownloadedFiles(QString path, QString url);
|
void processDownloadedFiles(QString path, QString url);
|
||||||
void finishedTorrent(QTorrentHandle& h) const;
|
void finishedTorrent(QTorrentHandle& h) const;
|
||||||
void askRecursiveTorrentDownloadConfirmation(QTorrentHandle &h);
|
|
||||||
// Options slots
|
// Options slots
|
||||||
void on_actionOptions_triggered();
|
void on_actionOptions_triggered();
|
||||||
void optionsSaved();
|
void optionsSaved();
|
||||||
// HTTP slots
|
// HTTP slots
|
||||||
void on_actionDownload_from_URL_triggered();
|
void on_actionDownload_from_URL_triggered();
|
||||||
|
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void trackerAuthenticationRequired(QTorrentHandle& h);
|
||||||
|
void setTabText(int index, QString text) const;
|
||||||
|
void showNotificationBaloon(QString title, QString msg) const;
|
||||||
|
void downloadFromURLList(const QStringList& urls);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *);
|
void closeEvent(QCloseEvent *);
|
||||||
void showEvent(QShowEvent *);
|
void showEvent(QShowEvent *);
|
||||||
bool event(QEvent * event);
|
bool event(QEvent * event);
|
||||||
void displayRSSTab(bool enable);
|
void displayRSSTab(bool enable);
|
||||||
|
|
||||||
private:
|
public:
|
||||||
// Bittorrent
|
// Construct / Destruct
|
||||||
Bittorrent *BTSession;
|
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
|
||||||
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; // Still needed?
|
~GUI();
|
||||||
// GUI related
|
// Methods
|
||||||
QTimer *guiUpdater;
|
int getCurrentTabIndex() const;
|
||||||
QTabWidget *tabs;
|
TransferListWidget* getTransferList() const { return transferList; }
|
||||||
StatusBar *status_bar;
|
|
||||||
QPointer<options_imp> options;
|
|
||||||
QPointer<consoleDlg> console;
|
|
||||||
QPointer<about> aboutDlg;
|
|
||||||
QPointer<createtorrent> createTorrentDlg;
|
|
||||||
QPointer<downloadFromURL> downloadFromURLDialog;
|
|
||||||
QPointer<QSystemTrayIcon> systrayIcon;
|
|
||||||
QPointer<QTimer> systrayCreator;
|
|
||||||
QMenu *myTrayIconMenu;
|
|
||||||
TransferListWidget *transferList;
|
|
||||||
TransferListFiltersWidget *transferListFilters;
|
|
||||||
PropertiesWidget *properties;
|
|
||||||
bool displaySpeedInTitle;
|
|
||||||
bool force_exit;
|
|
||||||
// Keyboard shortcuts
|
|
||||||
QShortcut *switchSearchShortcut;
|
|
||||||
QShortcut *switchSearchShortcut2;
|
|
||||||
QShortcut *switchTransferShortcut;
|
|
||||||
QShortcut *switchRSSShortcut;
|
|
||||||
// Widgets
|
|
||||||
QAction *prioSeparator;
|
|
||||||
QAction *prioSeparator2;
|
|
||||||
QSplitter *hSplitter;
|
|
||||||
QSplitter *vSplitter;
|
|
||||||
// Search
|
|
||||||
SearchEngine *searchEngine;
|
|
||||||
// RSS
|
|
||||||
QPointer<RSSImp> rssWidget;
|
|
||||||
// Misc
|
|
||||||
QLocalServer *localServer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,6 +1,6 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Categories=Qt;Network;P2P;
|
Categories=Qt;Network;P2P;
|
||||||
Comment=V2.2.1
|
Comment=V2.1.2
|
||||||
Exec=qbittorrent %f
|
Exec=qbittorrent %f
|
||||||
GenericName=Bittorrent client
|
GenericName=Bittorrent client
|
||||||
GenericName[bg]=Торент клиент
|
GenericName[bg]=Торент клиент
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 910 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 680 B |
@@ -63,7 +63,7 @@ class about : public QDialog, private Ui::AboutDlg{
|
|||||||
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+QString::fromUtf8("<br>"));
|
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+QString::fromUtf8("<br>"));
|
||||||
te_translation->append(QString::fromUtf8(
|
te_translation->append(QString::fromUtf8(
|
||||||
"<i>- <u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
|
"<i>- <u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
|
||||||
- <u>Bulgarian:</u> Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)<br>\
|
- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||||
- <u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)<br>\
|
- <u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)<br>\
|
||||||
- <u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)<br>\
|
- <u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)<br>\
|
||||||
- <u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)<br>\
|
- <u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)<br>\
|
||||||
@@ -87,7 +87,7 @@ class about : public QDialog, private Ui::AboutDlg{
|
|||||||
- <u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)<br>\
|
- <u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)<br>\
|
||||||
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
|
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
|
||||||
- <u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)<br>\
|
- <u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)<br>\
|
||||||
- <u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)<br><br>"));
|
- <u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net)<br><br>"));
|
||||||
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
|
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
|
||||||
te_translation->scrollToAnchor(QString::fromUtf8("top"));
|
te_translation->scrollToAnchor(QString::fromUtf8("top"));
|
||||||
// License
|
// License
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
#ifndef ADVANCEDSETTINGS_H
|
|
||||||
#define ADVANCEDSETTINGS_H
|
|
||||||
|
|
||||||
#include <QTableWidget>
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QSpinBox>
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include "preferences.h"
|
|
||||||
|
|
||||||
enum AdvSettingsCols {PROPERTY, VALUE};
|
|
||||||
enum AdvSettingsRows {DISK_CACHE, OUTGOING_PORT_MIN, OUTGOING_PORT_MAX, IGNORE_LIMIT_LAN, COUNT_OVERHEAD, RECHECK_COMPLETED, LIST_REFRESH, RESOLVE_COUNTRIES, RESOLVE_HOSTS };
|
|
||||||
#define ROW_COUNT 9
|
|
||||||
|
|
||||||
class AdvancedSettings: public QTableWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSpinBox *spin_cache, *outgoing_ports_min, *outgoing_ports_max, *spin_list_refresh;
|
|
||||||
QCheckBox *cb_ignore_limits_lan, *cb_count_overhead, *cb_recheck_completed, *cb_resolve_countries, *cb_resolve_hosts;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AdvancedSettings(QWidget *parent=0): QTableWidget(parent) {
|
|
||||||
// Set visual appearance
|
|
||||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
||||||
setAlternatingRowColors(true);
|
|
||||||
setColumnCount(2);
|
|
||||||
QStringList header;
|
|
||||||
header << tr("Property") << tr("Value");
|
|
||||||
setHorizontalHeaderLabels(header);
|
|
||||||
setColumnWidth(0, width()/2);
|
|
||||||
horizontalHeader()->setStretchLastSection(true);
|
|
||||||
verticalHeader()->setVisible(false);
|
|
||||||
setRowCount(ROW_COUNT);
|
|
||||||
// Load settings
|
|
||||||
loadAdvancedSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
~AdvancedSettings() {
|
|
||||||
delete spin_cache;
|
|
||||||
delete outgoing_ports_min;
|
|
||||||
delete outgoing_ports_max;
|
|
||||||
delete cb_ignore_limits_lan;
|
|
||||||
delete cb_count_overhead;
|
|
||||||
delete cb_recheck_completed;
|
|
||||||
delete spin_list_refresh;
|
|
||||||
delete cb_resolve_countries;
|
|
||||||
delete cb_resolve_hosts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void saveAdvancedSettings() {
|
|
||||||
// Disk write cache
|
|
||||||
Preferences::setDiskCacheSize(spin_cache->value());
|
|
||||||
// Outgoing ports
|
|
||||||
Preferences::setOutgoingPortsMin(outgoing_ports_min->value());
|
|
||||||
Preferences::setOutgoingPortsMax(outgoing_ports_max->value());
|
|
||||||
// Ignore limits on LAN
|
|
||||||
Preferences::ignoreLimitsOnLAN(cb_ignore_limits_lan->isChecked());
|
|
||||||
// Include protocol overhead in transfer limits
|
|
||||||
Preferences::includeOverheadInLimits(cb_count_overhead->isChecked());
|
|
||||||
// Recheck torrents on completion
|
|
||||||
Preferences::recheckTorrentsOnCompletion(cb_recheck_completed->isChecked());
|
|
||||||
// Transfer list refresh interval
|
|
||||||
Preferences::setRefreshInterval(spin_list_refresh->value());
|
|
||||||
// Peer resolution
|
|
||||||
Preferences::resolvePeerCountries(cb_resolve_countries->isChecked());
|
|
||||||
Preferences::resolvePeerHostNames(cb_resolve_hosts->isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void loadAdvancedSettings() {
|
|
||||||
// Disk write cache
|
|
||||||
setItem(DISK_CACHE, PROPERTY, new QTableWidgetItem(tr("Disk write cache size")));
|
|
||||||
spin_cache = new QSpinBox();
|
|
||||||
connect(spin_cache, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
|
|
||||||
spin_cache->setMinimum(1);
|
|
||||||
spin_cache->setMaximum(200);
|
|
||||||
spin_cache->setValue(Preferences::diskCacheSize());
|
|
||||||
spin_cache->setSuffix(tr(" MiB"));
|
|
||||||
setCellWidget(DISK_CACHE, VALUE, spin_cache);
|
|
||||||
// Outgoing port Min
|
|
||||||
setItem(OUTGOING_PORT_MIN, PROPERTY, new QTableWidgetItem(tr("Outgoing ports (Min) [0: Disabled]")));
|
|
||||||
outgoing_ports_min = new QSpinBox();
|
|
||||||
connect(outgoing_ports_min, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
|
|
||||||
outgoing_ports_min->setMinimum(0);
|
|
||||||
outgoing_ports_min->setMaximum(65535);
|
|
||||||
outgoing_ports_min->setValue(Preferences::outgoingPortsMin());
|
|
||||||
setCellWidget(OUTGOING_PORT_MIN, VALUE, outgoing_ports_min);
|
|
||||||
// Outgoing port Min
|
|
||||||
setItem(OUTGOING_PORT_MAX, PROPERTY, new QTableWidgetItem(tr("Outgoing ports (Max) [0: Disabled]")));
|
|
||||||
outgoing_ports_max = new QSpinBox();
|
|
||||||
connect(outgoing_ports_max, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
|
|
||||||
outgoing_ports_max->setMinimum(0);
|
|
||||||
outgoing_ports_max->setMaximum(65535);
|
|
||||||
outgoing_ports_max->setValue(Preferences::outgoingPortsMax());
|
|
||||||
setCellWidget(OUTGOING_PORT_MAX, VALUE, outgoing_ports_max);
|
|
||||||
// Ignore transfer limits on local network
|
|
||||||
setItem(IGNORE_LIMIT_LAN, PROPERTY, new QTableWidgetItem(tr("Ignore transfer limits on local network")));
|
|
||||||
cb_ignore_limits_lan = new QCheckBox();
|
|
||||||
connect(cb_ignore_limits_lan, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
|
||||||
cb_ignore_limits_lan->setChecked(Preferences::ignoreLimitsOnLAN());
|
|
||||||
setCellWidget(IGNORE_LIMIT_LAN, VALUE, cb_ignore_limits_lan);
|
|
||||||
// Consider protocol overhead in transfer limits
|
|
||||||
setItem(COUNT_OVERHEAD, PROPERTY, new QTableWidgetItem(tr("Include TCP/IP overhead in transfer limits")));
|
|
||||||
cb_count_overhead = new QCheckBox();
|
|
||||||
connect(cb_count_overhead, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
|
||||||
cb_count_overhead->setChecked(Preferences::includeOverheadInLimits());
|
|
||||||
setCellWidget(COUNT_OVERHEAD, VALUE, cb_count_overhead);
|
|
||||||
// Recheck completed torrents
|
|
||||||
setItem(RECHECK_COMPLETED, PROPERTY, new QTableWidgetItem(tr("Recheck torrents on completion")));
|
|
||||||
cb_recheck_completed = new QCheckBox();
|
|
||||||
connect(cb_recheck_completed, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
|
||||||
cb_recheck_completed->setChecked(Preferences::recheckTorrentsOnCompletion());
|
|
||||||
setCellWidget(RECHECK_COMPLETED, VALUE, cb_recheck_completed);
|
|
||||||
// Transfer list refresh interval
|
|
||||||
setItem(LIST_REFRESH, PROPERTY, new QTableWidgetItem(tr("Transfer list refresh interval")));
|
|
||||||
spin_list_refresh = new QSpinBox();
|
|
||||||
connect(spin_list_refresh, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
|
|
||||||
spin_list_refresh->setMinimum(30);
|
|
||||||
spin_list_refresh->setMaximum(99999);
|
|
||||||
spin_list_refresh->setValue(Preferences::getRefreshInterval());
|
|
||||||
spin_list_refresh->setSuffix(tr(" ms", " milliseconds"));
|
|
||||||
setCellWidget(LIST_REFRESH, VALUE, spin_list_refresh);
|
|
||||||
// Resolve Peer countries
|
|
||||||
setItem(RESOLVE_COUNTRIES, PROPERTY, new QTableWidgetItem(tr("Resolve peer countries (GeoIP)")));
|
|
||||||
cb_resolve_countries = new QCheckBox();
|
|
||||||
connect(cb_resolve_countries, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
|
||||||
cb_resolve_countries->setChecked(Preferences::resolvePeerCountries());
|
|
||||||
setCellWidget(RESOLVE_COUNTRIES, VALUE, cb_resolve_countries);
|
|
||||||
// Resolve peer hosts
|
|
||||||
setItem(RESOLVE_HOSTS, PROPERTY, new QTableWidgetItem(tr("Resolve peer host names")));
|
|
||||||
cb_resolve_hosts = new QCheckBox();
|
|
||||||
connect(cb_resolve_hosts, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
|
||||||
cb_resolve_hosts->setChecked(Preferences::resolvePeerHostNames());
|
|
||||||
setCellWidget(RESOLVE_HOSTS, VALUE, cb_resolve_hosts);
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitSettingsChanged() {
|
|
||||||
emit settingsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void settingsChanged();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ADVANCEDSETTINGS_H
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
#ifndef BANDWIDTHSCHEDULER_H
|
|
||||||
#define BANDWIDTHSCHEDULER_H
|
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QTime>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include "preferences.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class BandwidthScheduler: public QTimer {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool in_alternative_mode;
|
|
||||||
|
|
||||||
public:
|
|
||||||
BandwidthScheduler(QObject *parent): QTimer(parent), in_alternative_mode(false) {
|
|
||||||
Q_ASSERT(Preferences::isSchedulerEnabled());
|
|
||||||
// Signal shot, we call start() again manually
|
|
||||||
setSingleShot(true);
|
|
||||||
// Connect Signals/Slots
|
|
||||||
connect(this, SIGNAL(timeout()), this, SLOT(switchMode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void start() {
|
|
||||||
Q_ASSERT(Preferences::isSchedulerEnabled());
|
|
||||||
|
|
||||||
QTime startAltSpeeds = Preferences::getSchedulerStartTime();
|
|
||||||
QTime endAltSpeeds = Preferences::getSchedulerEndTime();
|
|
||||||
if(startAltSpeeds == endAltSpeeds) {
|
|
||||||
std::cerr << "Error: bandwidth scheduler have the same start time and end time." << std::endl;
|
|
||||||
std::cerr << "The bandwidth scheduler will be disabled" << std::endl;
|
|
||||||
stop();
|
|
||||||
emit switchToAlternativeMode(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine what the closest QTime is
|
|
||||||
QTime now = QTime::currentTime();
|
|
||||||
uint time_to_start = secsTo(now, startAltSpeeds);
|
|
||||||
uint time_to_end = secsTo(now, endAltSpeeds);
|
|
||||||
if(time_to_end < time_to_start) {
|
|
||||||
// We should be in alternative mode
|
|
||||||
in_alternative_mode = true;
|
|
||||||
// Start counting
|
|
||||||
QTimer::start(time_to_end*1000);
|
|
||||||
} else {
|
|
||||||
// We should be in normal mode
|
|
||||||
in_alternative_mode = false;
|
|
||||||
// Start counting
|
|
||||||
QTimer::start(time_to_start*1000);
|
|
||||||
}
|
|
||||||
// Send signal to notify BTSession
|
|
||||||
emit switchToAlternativeMode(in_alternative_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void switchMode() {
|
|
||||||
// Get the day this mode was started (either today or yesterday)
|
|
||||||
QDate current_date = QDateTime::currentDateTime().toLocalTime().date();
|
|
||||||
int day = current_date.dayOfWeek();
|
|
||||||
if(in_alternative_mode) {
|
|
||||||
// It is possible that starttime was yesterday
|
|
||||||
if(QTime::currentTime().secsTo(Preferences::getSchedulerStartTime()) > 0) {
|
|
||||||
current_date.addDays(-1); // Go to yesterday
|
|
||||||
day = current_date.day();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if the day is in scheduler days
|
|
||||||
// Notify BTSession only if necessary
|
|
||||||
switch(Preferences::getSchedulerDays()) {
|
|
||||||
case EVERY_DAY:
|
|
||||||
emit switchToAlternativeMode(!in_alternative_mode);
|
|
||||||
break;
|
|
||||||
case WEEK_ENDS:
|
|
||||||
if(day == Qt::Saturday || day == Qt::Sunday)
|
|
||||||
emit switchToAlternativeMode(!in_alternative_mode);
|
|
||||||
break;
|
|
||||||
case WEEK_DAYS:
|
|
||||||
if(day != Qt::Saturday && day != Qt::Sunday)
|
|
||||||
emit switchToAlternativeMode(!in_alternative_mode);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Convert our enum index to Qt enum index
|
|
||||||
int scheduler_day = ((int)Preferences::getSchedulerDays()) - 2;
|
|
||||||
if(day == scheduler_day)
|
|
||||||
emit switchToAlternativeMode(!in_alternative_mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Call start again
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void switchToAlternativeMode(bool alternative);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Qt function can return negative values and we
|
|
||||||
// don't want that
|
|
||||||
uint secsTo(QTime now, QTime t) {
|
|
||||||
int diff = now.secsTo(t);
|
|
||||||
if(diff < 0) {
|
|
||||||
// 86400 seconds in a day
|
|
||||||
diff += 86400;
|
|
||||||
}
|
|
||||||
Q_ASSERT(diff >= 0);
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BANDWIDTHSCHEDULER_H
|
|
||||||
131
src/bittorrent.h
@@ -52,10 +52,9 @@ using namespace libtorrent;
|
|||||||
|
|
||||||
class downloadThread;
|
class downloadThread;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
class FileSystemWatcher;
|
||||||
class FilterParserThread;
|
class FilterParserThread;
|
||||||
class HttpServer;
|
class HttpServer;
|
||||||
class BandwidthScheduler;
|
|
||||||
class ScanFoldersModel;
|
|
||||||
|
|
||||||
class TrackerInfos {
|
class TrackerInfos {
|
||||||
public:
|
public:
|
||||||
@@ -89,6 +88,60 @@ public:
|
|||||||
class Bittorrent : public QObject {
|
class Bittorrent : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Bittorrent
|
||||||
|
session *s;
|
||||||
|
QPointer<QTimer> timerAlerts;
|
||||||
|
QMap<QUrl, QString> savepath_fromurl;
|
||||||
|
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
|
||||||
|
QStringList torrentsToPausedAfterChecking;
|
||||||
|
// Ratio
|
||||||
|
QPointer<QTimer> BigRatioTimer;
|
||||||
|
// HTTP
|
||||||
|
QPointer<downloadThread> downloader;
|
||||||
|
// File System
|
||||||
|
QPointer<FileSystemWatcher> FSWatcher;
|
||||||
|
// Console / Log
|
||||||
|
QStringList consoleMessages;
|
||||||
|
QStringList peerBanMessages;
|
||||||
|
// Settings
|
||||||
|
bool preAllocateAll;
|
||||||
|
bool addInPause;
|
||||||
|
float ratio_limit;
|
||||||
|
bool UPnPEnabled;
|
||||||
|
bool NATPMPEnabled;
|
||||||
|
bool LSDEnabled;
|
||||||
|
bool DHTEnabled;
|
||||||
|
int current_dht_port;
|
||||||
|
bool PeXEnabled;
|
||||||
|
bool queueingEnabled;
|
||||||
|
bool appendLabelToSavePath;
|
||||||
|
#ifdef LIBTORRENT_0_15
|
||||||
|
bool appendqBExtension;
|
||||||
|
#endif
|
||||||
|
QString defaultSavePath;
|
||||||
|
QString defaultTempPath;
|
||||||
|
// GeoIP
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
bool resolve_countries;
|
||||||
|
bool geoipDBLoaded;
|
||||||
|
#endif
|
||||||
|
// ETA Computation
|
||||||
|
QPointer<QTimer> timerETA;
|
||||||
|
QHash<QString, QList<int> > ETA_samples;
|
||||||
|
// IP filtering
|
||||||
|
QPointer<FilterParserThread> filterParser;
|
||||||
|
QString filterPath;
|
||||||
|
// Web UI
|
||||||
|
QPointer<HttpServer> httpServer;
|
||||||
|
QList<QUrl> url_skippingDlg;
|
||||||
|
// Fast exit (async)
|
||||||
|
bool exiting;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString getSavePath(QString hash);
|
||||||
|
bool initWebUi(QString username, QString password, int port);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor / Destructor
|
// Constructor / Destructor
|
||||||
Bittorrent();
|
Bittorrent();
|
||||||
@@ -115,11 +168,13 @@ public:
|
|||||||
qlonglong getETA(QString hash);
|
qlonglong getETA(QString hash);
|
||||||
bool useTemporaryFolder() const;
|
bool useTemporaryFolder() const;
|
||||||
QString getDefaultSavePath() const;
|
QString getDefaultSavePath() const;
|
||||||
ScanFoldersModel* getScanFoldersModel() const;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
|
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
|
||||||
QTorrentHandle addMagnetUri(QString magnet_uri, bool resumed=false);
|
QTorrentHandle addMagnetUri(QString magnet_uri, bool resumed=false);
|
||||||
|
void importOldTorrents();
|
||||||
|
void applyFormerAttributeFiles(QTorrentHandle h);
|
||||||
|
void importOldTempData(QString torrent_path);
|
||||||
void loadSessionState();
|
void loadSessionState();
|
||||||
void saveSessionState();
|
void saveSessionState();
|
||||||
void downloadFromUrl(QString url);
|
void downloadFromUrl(QString url);
|
||||||
@@ -127,7 +182,6 @@ public slots:
|
|||||||
void startUpTorrents();
|
void startUpTorrents();
|
||||||
session_proxy asyncDeletion();
|
session_proxy asyncDeletion();
|
||||||
void recheckTorrent(QString hash);
|
void recheckTorrent(QString hash);
|
||||||
void useAlternativeSpeedsLimit(bool alternative);
|
|
||||||
/* Needed by Web UI */
|
/* Needed by Web UI */
|
||||||
void pauseAllTorrents();
|
void pauseAllTorrents();
|
||||||
void pauseTorrent(QString hash);
|
void pauseTorrent(QString hash);
|
||||||
@@ -137,6 +191,8 @@ 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);
|
||||||
@@ -152,9 +208,9 @@ public slots:
|
|||||||
void setGlobalRatio(float ratio);
|
void setGlobalRatio(float ratio);
|
||||||
void setDeleteRatio(float ratio);
|
void setDeleteRatio(float ratio);
|
||||||
void setDHTPort(int dht_port);
|
void setDHTPort(int dht_port);
|
||||||
void setPeerProxySettings(const proxy_settings &proxySettings);
|
void setPeerProxySettings(proxy_settings proxySettings);
|
||||||
void setHTTPProxySettings(const proxy_settings &proxySettings);
|
void setHTTPProxySettings(proxy_settings proxySettings);
|
||||||
void setSessionSettings(const session_settings &sessionSettings);
|
void setSessionSettings(session_settings sessionSettings);
|
||||||
void startTorrentsInPause(bool b);
|
void startTorrentsInPause(bool b);
|
||||||
void setDefaultTempPath(QString temppath);
|
void setDefaultTempPath(QString temppath);
|
||||||
void setAppendLabelToSavePath(bool append);
|
void setAppendLabelToSavePath(bool append);
|
||||||
@@ -182,18 +238,12 @@ public slots:
|
|||||||
void downloadFromURLList(const QStringList& urls);
|
void downloadFromURLList(const QStringList& urls);
|
||||||
void configureSession();
|
void configureSession();
|
||||||
void banIP(QString ip);
|
void banIP(QString ip);
|
||||||
void recursiveTorrentDownload(const QTorrentHandle &h);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QString getSavePath(QString hash, bool fromScanDir = false, QString filePath = QString());
|
|
||||||
bool initWebUi(QString username, QString password, int port);
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void addTorrentsFromScanFolder(QStringList&);
|
void addTorrentsFromScanFolder(QStringList&);
|
||||||
void readAlerts();
|
void readAlerts();
|
||||||
void deleteBigRatios();
|
void deleteBigRatios();
|
||||||
void takeETASamples();
|
void takeETASamples();
|
||||||
void exportTorrentFiles(QString path);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void addedTorrent(QTorrentHandle& h);
|
void addedTorrent(QTorrentHandle& h);
|
||||||
@@ -211,61 +261,6 @@ signals:
|
|||||||
void metadataReceived(QTorrentHandle &h);
|
void metadataReceived(QTorrentHandle &h);
|
||||||
void savePathChanged(QTorrentHandle &h);
|
void savePathChanged(QTorrentHandle &h);
|
||||||
void newConsoleMessage(QString msg);
|
void newConsoleMessage(QString msg);
|
||||||
void alternativeSpeedsModeChanged(bool alternative);
|
|
||||||
void recursiveTorrentDownloadPossible(QTorrentHandle &h);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Bittorrent
|
|
||||||
session *s;
|
|
||||||
QPointer<QTimer> timerAlerts;
|
|
||||||
QPointer<BandwidthScheduler> bd_scheduler;
|
|
||||||
QMap<QUrl, QString> savepath_fromurl;
|
|
||||||
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
|
|
||||||
QStringList torrentsToPausedAfterChecking;
|
|
||||||
// Ratio
|
|
||||||
QPointer<QTimer> BigRatioTimer;
|
|
||||||
// HTTP
|
|
||||||
QPointer<downloadThread> downloader;
|
|
||||||
// File System
|
|
||||||
ScanFoldersModel *m_scanFolders;
|
|
||||||
// Console / Log
|
|
||||||
QStringList consoleMessages;
|
|
||||||
QStringList peerBanMessages;
|
|
||||||
// Settings
|
|
||||||
bool preAllocateAll;
|
|
||||||
bool addInPause;
|
|
||||||
float ratio_limit;
|
|
||||||
bool UPnPEnabled;
|
|
||||||
bool NATPMPEnabled;
|
|
||||||
bool LSDEnabled;
|
|
||||||
bool DHTEnabled;
|
|
||||||
int current_dht_port;
|
|
||||||
bool PeXEnabled;
|
|
||||||
bool queueingEnabled;
|
|
||||||
bool appendLabelToSavePath;
|
|
||||||
bool torrentExport;
|
|
||||||
#ifdef LIBTORRENT_0_15
|
|
||||||
bool appendqBExtension;
|
|
||||||
#endif
|
|
||||||
QString defaultSavePath;
|
|
||||||
QString defaultTempPath;
|
|
||||||
// ETA Computation
|
|
||||||
QPointer<QTimer> timerETA;
|
|
||||||
QHash<QString, QList<int> > ETA_samples;
|
|
||||||
// IP filtering
|
|
||||||
QPointer<FilterParserThread> filterParser;
|
|
||||||
QString filterPath;
|
|
||||||
// Web UI
|
|
||||||
QPointer<HttpServer> httpServer;
|
|
||||||
QList<QUrl> url_skippingDlg;
|
|
||||||
// Fast exit (async)
|
|
||||||
bool exiting;
|
|
||||||
// GeoIP
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
bool geoipDBLoaded;
|
|
||||||
bool resolve_countries;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ class consoleDlg : public QDialog, private Ui_ConsoleDlg{
|
|||||||
consoleDlg(QWidget *parent, Bittorrent* _BTSession) : QDialog(parent) {
|
consoleDlg(QWidget *parent, Bittorrent* _BTSession) : QDialog(parent) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
setModal(true);
|
|
||||||
BTSession = _BTSession;
|
BTSession = _BTSession;
|
||||||
textConsole->setHtml(BTSession->getConsoleMessages().join("<br>"));
|
textConsole->setHtml(BTSession->getConsoleMessages().join("<br>"));
|
||||||
textBannedPeers->setHtml(BTSession->getPeerBanMessages().join("<br>"));
|
textBannedPeers->setHtml(BTSession->getPeerBanMessages().join("<br>"));
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ bool file_filter(boost::filesystem::path const& filename)
|
|||||||
createtorrent::createtorrent(QWidget *parent): QDialog(parent){
|
createtorrent::createtorrent(QWidget *parent): QDialog(parent){
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
setModal(true);
|
|
||||||
creatorThread = new torrentCreatorThread(this);
|
creatorThread = new torrentCreatorThread(this);
|
||||||
connect(creatorThread, SIGNAL(creationSuccess(QString, const char*)), this, SLOT(handleCreationSuccess(QString, const char*)));
|
connect(creatorThread, SIGNAL(creationSuccess(QString, const char*)), this, SLOT(handleCreationSuccess(QString, const char*)));
|
||||||
connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
|
connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
|
||||||
@@ -85,7 +84,7 @@ void createtorrent::on_addFolder_button_clicked(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void createtorrent::on_addFile_button_clicked(){
|
void createtorrent::on_addFile_button_clicked(){
|
||||||
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath());
|
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath(), QString(), 0, QFileDialog::ShowDirsOnly);
|
||||||
if(!file.isEmpty())
|
if(!file.isEmpty())
|
||||||
textInputPath->setText(file);
|
textInputPath->setText(file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,49 +53,34 @@ public:
|
|||||||
setFixedHeight(BAR_HEIGHT);
|
setFixedHeight(BAR_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setProgress(const bitfield &pieces, const bitfield &downloading_pieces) {
|
void setProgress(bitfield pieces) {
|
||||||
if(pieces.empty()) {
|
if(pieces.empty()) {
|
||||||
// Empty bar
|
// Empty bar
|
||||||
QPixmap pix = QPixmap(1, 1);
|
QPixmap pix = QPixmap(1, 1);
|
||||||
pix.fill();
|
pix.fill();
|
||||||
pixmap = pix;
|
pixmap = pix;
|
||||||
} else {
|
} else {
|
||||||
const int nb_pieces = pieces.size();
|
int nb_pieces = pieces.size();
|
||||||
// Reduce the number of pieces before creating the pixmap
|
// Reduce the number of pieces before creating the pixmap
|
||||||
// otherwise it can crash when there are too many pieces
|
// otherwise it can crash when there are too many pieces
|
||||||
if(nb_pieces > width()) {
|
if(nb_pieces > width()) {
|
||||||
const int ratio = floor(nb_pieces/(double)width());
|
int ratio = floor(nb_pieces/(double)width());
|
||||||
std::vector<bool> scaled_pieces;
|
QVector<bool> scaled_pieces;
|
||||||
std::vector<bool> scaled_downloading;
|
|
||||||
for(int i=0; i<nb_pieces; i+= ratio) {
|
for(int i=0; i<nb_pieces; i+= ratio) {
|
||||||
bool have = true;
|
bool have = true;
|
||||||
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
||||||
if(!pieces[i]) { have = false; break; }
|
if(!pieces[i]) { have = false; break; }
|
||||||
}
|
}
|
||||||
scaled_pieces.push_back(have);
|
scaled_pieces << have;
|
||||||
if(have) {
|
|
||||||
scaled_downloading.push_back(false);
|
|
||||||
} else {
|
|
||||||
bool downloading = false;
|
|
||||||
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
|
||||||
if(downloading_pieces[i]) { downloading = true; break; }
|
|
||||||
}
|
|
||||||
scaled_downloading.push_back(downloading);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
QPixmap pix = QPixmap(scaled_pieces.size(), 1);
|
QPixmap pix = QPixmap(scaled_pieces.size(), 1);
|
||||||
pix.fill();
|
pix.fill();
|
||||||
QPainter painter(&pix);
|
QPainter painter(&pix);
|
||||||
for(uint i=0; i<scaled_pieces.size(); ++i) {
|
for(int i=0; i<scaled_pieces.size(); ++i) {
|
||||||
if(scaled_pieces[i]) {
|
if(scaled_pieces[i])
|
||||||
painter.setPen(Qt::blue);
|
painter.setPen(Qt::blue);
|
||||||
} else {
|
else
|
||||||
if(scaled_downloading[i]) {
|
painter.setPen(Qt::white);
|
||||||
painter.setPen(Qt::yellow);
|
|
||||||
} else {
|
|
||||||
painter.setPen(Qt::white);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
painter.drawPoint(i,0);
|
painter.drawPoint(i,0);
|
||||||
}
|
}
|
||||||
pixmap = pix;
|
pixmap = pix;
|
||||||
@@ -104,15 +89,10 @@ public:
|
|||||||
pix.fill();
|
pix.fill();
|
||||||
QPainter painter(&pix);
|
QPainter painter(&pix);
|
||||||
for(uint i=0; i<pieces.size(); ++i) {
|
for(uint i=0; i<pieces.size(); ++i) {
|
||||||
if(pieces[i]) {
|
if(pieces[i])
|
||||||
painter.setPen(Qt::blue);
|
painter.setPen(Qt::blue);
|
||||||
} else {
|
else
|
||||||
if(downloading_pieces[i]) {
|
painter.setPen(Qt::white);
|
||||||
painter.setPen(Qt::yellow);
|
|
||||||
} else {
|
|
||||||
painter.setPen(Qt::white);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
painter.drawPoint(i,0);
|
painter.drawPoint(i,0);
|
||||||
}
|
}
|
||||||
pixmap = pix;
|
pixmap = pix;
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
|||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
icon_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/url.png")));
|
icon_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/url.png")));
|
||||||
setModal(true);
|
|
||||||
show();
|
show();
|
||||||
// Paste clipboard if there is an URL in it
|
// Paste clipboard if there is an URL in it
|
||||||
QString clip_txt = qApp->clipboard()->text();
|
QString clip_txt = qApp->clipboard()->text();
|
||||||
|
|||||||
@@ -56,27 +56,14 @@ void downloadThread::processDlFinished(QNetworkReply* reply) {
|
|||||||
// Failure
|
// Failure
|
||||||
emit downloadFailure(url, errorCodeToString(reply->error()));
|
emit downloadFailure(url, errorCodeToString(reply->error()));
|
||||||
} else {
|
} else {
|
||||||
QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
|
||||||
if(redirection.isValid()) {
|
|
||||||
// We should redirect
|
|
||||||
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(redirection.toUrl().toString()));
|
|
||||||
redirect_mapping.insert(redirection.toUrl().toString(), url);
|
|
||||||
downloadUrl(redirection.toUrl().toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Checking if it was redirecting, restoring initial URL
|
|
||||||
if(redirect_mapping.contains(url)) {
|
|
||||||
url = redirect_mapping.take(url);
|
|
||||||
}
|
|
||||||
// Success
|
// Success
|
||||||
QString filePath;
|
QString filePath;
|
||||||
QTemporaryFile tmpfile;
|
QTemporaryFile tmpfile;
|
||||||
tmpfile.setAutoRemove(false);
|
tmpfile.setAutoRemove(false);
|
||||||
if (tmpfile.open()) {
|
if (tmpfile.open()) {
|
||||||
filePath = tmpfile.fileName();
|
filePath = tmpfile.fileName();
|
||||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
qDebug("Temporary filename is: %s", filePath.toLocal8Bit().data());
|
||||||
if(reply->open(QIODevice::ReadOnly)) {
|
if(reply->open(QIODevice::ReadOnly)) {
|
||||||
// TODO: Support GZIP compression
|
|
||||||
tmpfile.write(reply->readAll());
|
tmpfile.write(reply->readAll());
|
||||||
reply->close();
|
reply->close();
|
||||||
tmpfile.close();
|
tmpfile.close();
|
||||||
@@ -95,12 +82,7 @@ void downloadThread::processDlFinished(QNetworkReply* reply) {
|
|||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void downloadThread::downloadTorrentUrl(QString url){
|
void downloadThread::downloadUrl(QString url){
|
||||||
QNetworkReply *reply = downloadUrl(url);
|
|
||||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* downloadThread::downloadUrl(QString url){
|
|
||||||
// Update proxy settings
|
// Update proxy settings
|
||||||
applyProxySettings();
|
applyProxySettings();
|
||||||
// Process download request
|
// Process download request
|
||||||
@@ -109,27 +91,8 @@ QNetworkReply* downloadThread::downloadUrl(QString url){
|
|||||||
// Spoof Firefox 3.5 user agent to avoid
|
// Spoof Firefox 3.5 user agent to avoid
|
||||||
// Web server banning
|
// Web server banning
|
||||||
request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5");
|
request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5");
|
||||||
qDebug("Downloading %s...", qPrintable(request.url().toString()));
|
qDebug("Downloading %s...", request.url().toString().toLocal8Bit().data());
|
||||||
return networkManager->get(request);
|
networkManager->get(request);
|
||||||
}
|
|
||||||
|
|
||||||
void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
|
||||||
if(bytesTotal > 0) {
|
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
|
|
||||||
// Total number of bytes is available
|
|
||||||
if(bytesTotal > 1048576) {
|
|
||||||
// More than 1MB, this is probably not a torrent file, aborting...
|
|
||||||
reply->abort();
|
|
||||||
} else {
|
|
||||||
disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(bytesReceived > 1048576) {
|
|
||||||
// More than 1MB, this is probably not a torrent file, aborting...
|
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
|
|
||||||
reply->abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void downloadThread::applyProxySettings() {
|
void downloadThread::applyProxySettings() {
|
||||||
@@ -141,7 +104,7 @@ void downloadThread::applyProxySettings() {
|
|||||||
QString IP = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/IP"), "0.0.0.0").toString();
|
QString IP = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/IP"), "0.0.0.0").toString();
|
||||||
proxy.setHostName(IP);
|
proxy.setHostName(IP);
|
||||||
QString port = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/Port"), 8080).toString();
|
QString port = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/Port"), 8080).toString();
|
||||||
qDebug("Using proxy: %s", qPrintable(IP));
|
qDebug("Using proxy: %s", (IP+QString(":")+port).toLocal8Bit().data());
|
||||||
proxy.setPort(port.toUShort());
|
proxy.setPort(port.toUShort());
|
||||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||||
if(intValue == SOCKS5 || intValue == SOCKS5_PW) {
|
if(intValue == SOCKS5 || intValue == SOCKS5_PW) {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QHash>
|
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@ class downloadThread : public QObject {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QNetworkAccessManager *networkManager;
|
QNetworkAccessManager *networkManager;
|
||||||
QHash<QString, QString> redirect_mapping;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void downloadFinished(QString url, QString file_path);
|
void downloadFinished(QString url, QString file_path);
|
||||||
@@ -51,8 +49,7 @@ signals:
|
|||||||
public:
|
public:
|
||||||
downloadThread(QObject* parent);
|
downloadThread(QObject* parent);
|
||||||
~downloadThread();
|
~downloadThread();
|
||||||
QNetworkReply* downloadUrl(QString url);
|
void downloadUrl(QString url);
|
||||||
void downloadTorrentUrl(QString url);
|
|
||||||
//void setProxy(QString IP, int port, QString username, QString password);
|
//void setProxy(QString IP, int port, QString username, QString password);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -61,7 +58,6 @@ protected:
|
|||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void processDlFinished(QNetworkReply* reply);
|
void processDlFinished(QNetworkReply* reply);
|
||||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
|
|||||||
QStringList files=event->mimeData()->text().split(QString::fromUtf8("\n"));
|
QStringList files=event->mimeData()->text().split(QString::fromUtf8("\n"));
|
||||||
QString file;
|
QString file;
|
||||||
foreach(file, files) {
|
foreach(file, files) {
|
||||||
qDebug("dropped %s", qPrintable(file));
|
qDebug("dropped %s", file.toLocal8Bit().data());
|
||||||
file = file.replace("file://", "");
|
file = file.replace("file://", "");
|
||||||
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
|
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
|
||||||
downloader->downloadUrl(file);
|
downloader->downloadUrl(file);
|
||||||
@@ -99,7 +99,7 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
|
|||||||
void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
|
void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
|
||||||
QString mime;
|
QString mime;
|
||||||
foreach(mime, event->mimeData()->formats()){
|
foreach(mime, event->mimeData()->formats()){
|
||||||
qDebug("mimeData: %s", qPrintable(mime));
|
qDebug("mimeData: %s", mime.toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
|
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
@@ -251,12 +251,12 @@ bool engineSelectDlg::isUpdateNeeded(QString plugin_name, float new_version) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
||||||
qDebug("Asked to install plugin at %s", qPrintable(path));
|
qDebug("Asked to install plugin at %s", path.toLocal8Bit().data());
|
||||||
float new_version = SearchEngine::getPluginVersion(path);
|
float new_version = SearchEngine::getPluginVersion(path);
|
||||||
qDebug("Version to be installed: %.2f", new_version);
|
qDebug("Version to be installed: %.2f", new_version);
|
||||||
if(!isUpdateNeeded(plugin_name, new_version)) {
|
if(!isUpdateNeeded(plugin_name, new_version)) {
|
||||||
qDebug("Apparently update is not needed, we have a more recent version");
|
qDebug("Apparently update is not needed, we have a more recent version");
|
||||||
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name));
|
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Process with install
|
// Process with install
|
||||||
@@ -280,12 +280,12 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
|||||||
// restore backup
|
// restore backup
|
||||||
QFile::copy(dest_path+".bak", dest_path);
|
QFile::copy(dest_path+".bak", dest_path);
|
||||||
QFile::remove(dest_path+".bak");
|
QFile::remove(dest_path+".bak");
|
||||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name));
|
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Remove broken file
|
// Remove broken file
|
||||||
QFile::remove(dest_path);
|
QFile::remove(dest_path);
|
||||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name));
|
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,10 +294,10 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
|||||||
QFile::remove(dest_path+".bak");
|
QFile::remove(dest_path+".bak");
|
||||||
}
|
}
|
||||||
if(update) {
|
if(update) {
|
||||||
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name));
|
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name));
|
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,17 +390,17 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
|
|||||||
plugin_name.chop(1); // remove trailing ':'
|
plugin_name.chop(1); // remove trailing ':'
|
||||||
bool ok;
|
bool ok;
|
||||||
float version = list.last().toFloat(&ok);
|
float version = list.last().toFloat(&ok);
|
||||||
qDebug("read line %s: %.2f", qPrintable(plugin_name), version);
|
qDebug("read line %s: %.2f", plugin_name.toLocal8Bit().data(), version);
|
||||||
if(!ok) continue;
|
if(!ok) continue;
|
||||||
file_correct = true;
|
file_correct = true;
|
||||||
if(isUpdateNeeded(plugin_name, version)) {
|
if(isUpdateNeeded(plugin_name, version)) {
|
||||||
qDebug("Plugin: %s is outdated", qPrintable(plugin_name));
|
qDebug("Plugin: %s is outdated", plugin_name.toLocal8Bit().data());
|
||||||
// Downloading update
|
// Downloading update
|
||||||
downloader->downloadUrl(UPDATE_URL+plugin_name+".py");
|
downloader->downloadUrl(UPDATE_URL+plugin_name+".py");
|
||||||
//downloader->downloadUrl(UPDATE_URL+plugin_name+".png");
|
//downloader->downloadUrl(UPDATE_URL+plugin_name+".png");
|
||||||
updated = true;
|
updated = true;
|
||||||
}else {
|
}else {
|
||||||
qDebug("Plugin: %s is up to date", qPrintable(plugin_name));
|
qDebug("Plugin: %s is up to date", plugin_name.toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Close file
|
// Close file
|
||||||
@@ -414,7 +414,7 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
|
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
|
||||||
qDebug("engineSelectDlg received %s", qPrintable(url));
|
qDebug("engineSelectDlg received %s", url.toLocal8Bit().data());
|
||||||
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
||||||
// Icon downloaded
|
// Icon downloaded
|
||||||
QImage fileIcon;
|
QImage fileIcon;
|
||||||
@@ -456,7 +456,7 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
|
|||||||
|
|
||||||
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
|
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
|
||||||
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
||||||
qDebug("Could not download favicon: %s, reason: %s", qPrintable(url), qPrintable(reason));
|
qDebug("Could not download favicon: %s, reason: %s", url.toLocal8Bit().data(), reason.toLocal8Bit().data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(url.endsWith("versions.txt")) {
|
if(url.endsWith("versions.txt")) {
|
||||||
@@ -467,6 +467,6 @@ void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
|
|||||||
// a plugin update download has been failed
|
// a plugin update download has been failed
|
||||||
QString plugin_name = url.split('/').last();
|
QString plugin_name = url.split('/').last();
|
||||||
plugin_name.replace(".py", "", Qt::CaseInsensitive);
|
plugin_name.replace(".py", "", Qt::CaseInsensitive);
|
||||||
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name));
|
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
#include "eventmanager.h"
|
#include "eventmanager.h"
|
||||||
#include "bittorrent.h"
|
#include "bittorrent.h"
|
||||||
#include "scannedfoldersmodel.h"
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "preferences.h"
|
#include "preferences.h"
|
||||||
//#include "proplistdelegate.h"
|
//#include "proplistdelegate.h"
|
||||||
@@ -130,27 +129,8 @@ 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_dirs")) {
|
if(m.contains("scan_dir"))
|
||||||
QStringList old_folders = Preferences::getScanDirs();
|
Preferences::setScanDir(m["scan_dir"].toString());
|
||||||
QStringList new_folders = m["scan_dirs"].toStringList();
|
|
||||||
foreach(const QString &old_folder, old_folders) {
|
|
||||||
// Update deleted folders
|
|
||||||
if(!new_folders.contains(old_folder)) {
|
|
||||||
BTSession->getScanFoldersModel()->removePath(old_folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach(const QString &new_folder, new_folders) {
|
|
||||||
// Update new folders
|
|
||||||
if(!old_folders.contains(new_folder)) {
|
|
||||||
BTSession->getScanFoldersModel()->addPath(new_folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Preferences::setScanDirs(new_folders);
|
|
||||||
}
|
|
||||||
if(m.contains("download_in_scan_dirs"))
|
|
||||||
Preferences::setDownloadInScanDirs(m["download_in_scan_dirs"].toList());
|
|
||||||
if(m.contains("export_dir"))
|
|
||||||
Preferences::setExportDir(m["export_dir"].toString());
|
|
||||||
if(m.contains("preallocate_all"))
|
if(m.contains("preallocate_all"))
|
||||||
Preferences::preAllocateAllFiles(m["preallocate_all"].toBool());
|
Preferences::preAllocateAllFiles(m["preallocate_all"].toBool());
|
||||||
if(m.contains("queueing_enabled"))
|
if(m.contains("queueing_enabled"))
|
||||||
@@ -247,10 +227,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_dirs"] = Preferences::getScanDirs();
|
data["scan_dir_enabled"] = Preferences::isDirScanEnabled();
|
||||||
data["download_in_scan_dirs"] = Preferences::getDownloadInScanDirs();
|
data["scan_dir"] = Preferences::getScanDir();
|
||||||
data["export_dir_enabled"] = Preferences::isTorrentExportEnabled();
|
|
||||||
data["export_dir"] = Preferences::getExportDir();
|
|
||||||
data["preallocate_all"] = Preferences::preAllocateAllFiles();
|
data["preallocate_all"] = Preferences::preAllocateAllFiles();
|
||||||
data["queueing_enabled"] = Preferences::isQueueingSystemEnabled();
|
data["queueing_enabled"] = Preferences::isQueueingSystemEnabled();
|
||||||
data["max_active_downloads"] = Preferences::getMaxActiveDownloads();
|
data["max_active_downloads"] = Preferences::getMaxActiveDownloads();
|
||||||
@@ -304,30 +282,28 @@ QVariantMap EventManager::getPropGeneralInfo(QString hash) const {
|
|||||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||||
if(h.is_valid() && h.has_metadata()) {
|
if(h.is_valid() && h.has_metadata()) {
|
||||||
// Save path
|
// Save path
|
||||||
QString p = TorrentPersistentData::getSavePath(hash);
|
data["save_path"] = TorrentPersistentData::getSavePath(hash);
|
||||||
if(p.isEmpty()) p = h.save_path();
|
|
||||||
data["save_path"] = p;
|
|
||||||
// Creation date
|
// Creation date
|
||||||
data["creation_date"] = h.creation_date();
|
data["creation_date"] = h.creation_date();
|
||||||
// Comment
|
// Comment
|
||||||
data["comment"] = h.comment();
|
data["comment"] = h.comment();
|
||||||
data["total_wasted"] = QVariant(misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes()));
|
data["total_wasted"] = misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes());
|
||||||
data["total_uploaded"] = QVariant(misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")");
|
data["total_uploaded"] = misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")";
|
||||||
data["total_downloaded"] = QVariant(misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")");
|
data["total_downloaded"] = misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")";
|
||||||
if(h.upload_limit() <= 0)
|
if(h.upload_limit() <= 0)
|
||||||
data["up_limit"] = QString::fromUtf8("∞");
|
data["up_limit"] = QString::fromUtf8("∞");
|
||||||
else
|
else
|
||||||
data["up_limit"] = QVariant(misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)"));
|
data["up_limit"] = misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)");
|
||||||
if(h.download_limit() <= 0)
|
if(h.download_limit() <= 0)
|
||||||
data["dl_limit"] = QString::fromUtf8("∞");
|
data["dl_limit"] = QString::fromUtf8("∞");
|
||||||
else
|
else
|
||||||
data["dl_limit"] = QVariant(misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)"));
|
data["dl_limit"] = misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)");
|
||||||
QString elapsed_txt = misc::userFriendlyDuration(h.active_time());
|
QString elapsed_txt = misc::userFriendlyDuration(h.active_time());
|
||||||
if(h.is_seed()) {
|
if(h.is_seed()) {
|
||||||
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")";
|
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")";
|
||||||
}
|
}
|
||||||
data["time_elapsed"] = elapsed_txt;
|
data["time_elapsed"] = elapsed_txt;
|
||||||
data["nb_connections"] = QVariant(QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")");
|
data["nb_connections"] = QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")";
|
||||||
// Update ratio info
|
// Update ratio info
|
||||||
double ratio = BTSession->getRealRatio(h.hash());
|
double ratio = BTSession->getRealRatio(h.hash());
|
||||||
if(ratio > 100.)
|
if(ratio > 100.)
|
||||||
|
|||||||
@@ -28,16 +28,15 @@ public:
|
|||||||
setColumnCount(1);
|
setColumnCount(1);
|
||||||
QTreeWidgetItem *___qtreewidgetitem = headerItem();
|
QTreeWidgetItem *___qtreewidgetitem = headerItem();
|
||||||
___qtreewidgetitem->setText(0, QApplication::translate("RSS", "RSS feeds", 0, QApplication::UnicodeUTF8));
|
___qtreewidgetitem->setText(0, QApplication::translate("RSS", "RSS feeds", 0, QApplication::UnicodeUTF8));
|
||||||
|
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
||||||
unread_item = new QTreeWidgetItem(this);
|
unread_item = new QTreeWidgetItem(this);
|
||||||
unread_item->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->getNbUnRead(), 10)+ QString(")"));
|
unread_item->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->getNbUnRead(), 10)+ QString(")"));
|
||||||
unread_item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/mail-folder-inbox.png")));
|
unread_item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/mail-folder-inbox.png")));
|
||||||
itemAdded(unread_item, rssmanager);
|
itemAdded(unread_item, rssmanager);
|
||||||
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
|
||||||
setCurrentItem(unread_item);
|
setCurrentItem(unread_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
~FeedList() {
|
~FeedList() {
|
||||||
disconnect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
|
||||||
delete unread_item;
|
delete unread_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,19 +121,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RssFile* getRSSItem(QTreeWidgetItem *item) const {
|
RssFile* getRSSItem(QTreeWidgetItem *item) const {
|
||||||
return mapping.value(item, 0);
|
return mapping[item];
|
||||||
}
|
}
|
||||||
|
|
||||||
RssFile::FileType getItemType(QTreeWidgetItem *item) const {
|
RssFile::FileType getItemType(QTreeWidgetItem *item) const {
|
||||||
return mapping.value(item)->getType();
|
return mapping[item]->getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getItemID(QTreeWidgetItem *item) const {
|
QString getItemID(QTreeWidgetItem *item) const {
|
||||||
return mapping.value(item)->getID();
|
return mapping[item]->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* getTreeItemFromUrl(QString url) const{
|
QTreeWidgetItem* getTreeItemFromUrl(QString url) const{
|
||||||
return feeds_items.value(url, 0);
|
return feeds_items[url];
|
||||||
}
|
}
|
||||||
|
|
||||||
RssStream* getRSSItemFromUrl(QString url) const {
|
RssStream* getRSSItemFromUrl(QString url) const {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
#include "bittorrent.h"
|
#include "bittorrent.h"
|
||||||
#include "ui_feeddownloader.h"
|
#include "ui_feeddownloader.h"
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040500
|
#ifdef QT_4_5
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#else
|
#else
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
@@ -64,9 +64,11 @@ public:
|
|||||||
|
|
||||||
bool matches(QString s) {
|
bool matches(QString s) {
|
||||||
QStringList match_tokens = getMatchingTokens();
|
QStringList match_tokens = getMatchingTokens();
|
||||||
|
//qDebug("Checking matching tokens: \"%s\"", getMatchingTokens_str().toLocal8Bit().data());
|
||||||
foreach(const QString& token, match_tokens) {
|
foreach(const QString& token, match_tokens) {
|
||||||
if(token.isEmpty() || token == "")
|
if(token.isEmpty() || token == "")
|
||||||
continue;
|
continue;
|
||||||
|
//qDebug("Token: %s", token.toLocal8Bit().data());
|
||||||
QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard);
|
QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||||
//reg.setMinimal(false);
|
//reg.setMinimal(false);
|
||||||
if(reg.indexIn(s) < 0) return false;
|
if(reg.indexIn(s) < 0) return false;
|
||||||
@@ -224,7 +226,7 @@ public:
|
|||||||
void save() {
|
void save() {
|
||||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||||
qDebug("Saving filters for feed: %s (%d filters)", qPrintable(feed_url), (*this).size());
|
qDebug("Saving filters for feed: %s (%d filters)", feed_url.toLocal8Bit().data(), (*this).size());
|
||||||
all_feeds_filters[feed_url] = *this;
|
all_feeds_filters[feed_url] = *this;
|
||||||
qBTRSS.setValue("feed_filters", all_feeds_filters);
|
qBTRSS.setValue("feed_filters", all_feeds_filters);
|
||||||
}
|
}
|
||||||
@@ -259,6 +261,7 @@ public:
|
|||||||
// Restore saved info
|
// Restore saved info
|
||||||
enableDl_cb->setChecked(filters.isDownloadingEnabled());
|
enableDl_cb->setChecked(filters.isDownloadingEnabled());
|
||||||
fillFiltersList();
|
fillFiltersList();
|
||||||
|
filtersList->sortItems(Qt::AscendingOrder);
|
||||||
if(filters.size() > 0) {
|
if(filters.size() > 0) {
|
||||||
// Select first filter
|
// Select first filter
|
||||||
filtersList->setCurrentItem(filtersList->item(0));
|
filtersList->setCurrentItem(filtersList->item(0));
|
||||||
@@ -385,6 +388,7 @@ protected slots:
|
|||||||
if(selected_filter == current_name)
|
if(selected_filter == current_name)
|
||||||
selected_filter = new_name;
|
selected_filter = new_name;
|
||||||
item->setText(new_name);
|
item->setText(new_name);
|
||||||
|
filtersList->sortItems(Qt::AscendingOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,6 +442,7 @@ protected slots:
|
|||||||
}
|
}
|
||||||
}while(!validated);
|
}while(!validated);
|
||||||
QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList);
|
QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList);
|
||||||
|
filtersList->sortItems(Qt::AscendingOrder);
|
||||||
filtersList->setCurrentItem(it);
|
filtersList->setCurrentItem(it);
|
||||||
//showFilterSettings(it);
|
//showFilterSettings(it);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,14 +34,12 @@
|
|||||||
class FileSystemWatcher: public QFileSystemWatcher {
|
class FileSystemWatcher: public QFileSystemWatcher {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
QList<QDir> watched_folders;
|
private:
|
||||||
|
QDir watched_folder;
|
||||||
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;
|
||||||
@@ -49,10 +47,10 @@ protected:
|
|||||||
file += QDir::separator();
|
file += QDir::separator();
|
||||||
file += ".";
|
file += ".";
|
||||||
struct statfs buf;
|
struct statfs buf;
|
||||||
if(!statfs(file.toLocal8Bit().constData(), &buf)) {
|
if(!statfs(file.toLocal8Bit().data(), &buf)) {
|
||||||
return (buf.f_type == (long)CIFS_MAGIC_NUMBER || buf.f_type == (long)NFS_SUPER_MAGIC);
|
return (buf.f_type == (long)CIFS_MAGIC_NUMBER || buf.f_type == (long)NFS_SUPER_MAGIC);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Error: statfs() call failed for " << qPrintable(file) << ". Supposing it is a local folder..." << std::endl;
|
std::cerr << "Error: statfs() call failed for " << file.toLocal8Bit().data() << ". Supposing it is a local folder..." << std::endl;
|
||||||
switch(errno) {
|
switch(errno) {
|
||||||
case EACCES:
|
case EACCES:
|
||||||
std::cerr << "Search permission is denied for a component of the path prefix of the path" << std::endl;
|
std::cerr << "Search permission is denied for a component of the path prefix of the path" << std::endl;
|
||||||
@@ -100,7 +98,13 @@ protected:
|
|||||||
public:
|
public:
|
||||||
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
||||||
filters << "*.torrent";
|
filters << "*.torrent";
|
||||||
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
|
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanFolder()));
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSystemWatcher(QString path, QObject *parent): QFileSystemWatcher(parent) {
|
||||||
|
filters << "*.torrent";
|
||||||
|
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanFolder()));
|
||||||
|
addPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
~FileSystemWatcher() {
|
~FileSystemWatcher() {
|
||||||
@@ -111,40 +115,33 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
QStringList directories() const {
|
QStringList directories() const {
|
||||||
QStringList dirs;
|
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
if(watch_timer) {
|
if(watch_timer)
|
||||||
foreach (const QDir &dir, watched_folders)
|
return QStringList(watched_folder.path());
|
||||||
dirs << dir.canonicalPath();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
dirs << QFileSystemWatcher::directories();
|
return QFileSystemWatcher::directories();
|
||||||
return dirs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPath(const QString & path) {
|
void addPath(const QString & path) {
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
QDir dir(path);
|
watched_folder = QDir(path);
|
||||||
if (!dir.exists())
|
if(!watched_folder.exists()) return;
|
||||||
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
|
||||||
qDebug("Network folder detected: %s", qPrintable(path));
|
Q_ASSERT(!watch_timer);
|
||||||
|
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
|
||||||
if (!watch_timer) {
|
watch_timer = new QTimer(this);
|
||||||
watch_timer = new QTimer(this);
|
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanFolder()));
|
||||||
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanNetworkFolders()));
|
watch_timer->start(5000); // 5 sec
|
||||||
watch_timer->start(5000); // 5 sec
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
// Normal mode
|
// Normal mode
|
||||||
qDebug("FS Watching is watching %s in normal mode", qPrintable(path));
|
qDebug("FS Watching is watching %s in normal mode", path.toLocal8Bit().data());
|
||||||
QFileSystemWatcher::addPath(path);
|
QFileSystemWatcher::addPath(path);
|
||||||
scanLocalFolder(path);
|
scanFolder();
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -152,58 +149,38 @@ public:
|
|||||||
|
|
||||||
void removePath(const QString & path) {
|
void removePath(const QString & path) {
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
QDir dir(path);
|
if(watch_timer) {
|
||||||
for (int i = 0; i < watched_folders.count(); ++i) {
|
// Network mode
|
||||||
if (QDir(watched_folders.at(i)) == dir) {
|
if(QDir(path) == watched_folder) {
|
||||||
watched_folders.removeAt(i);
|
delete watch_timer;
|
||||||
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:
|
||||||
void scanLocalFolder(QString path) {
|
// XXX: Does not detect file size changes to improve performance.
|
||||||
qDebug("scanLocalFolder(%s) called", qPrintable(path));
|
void scanFolder() {
|
||||||
|
qDebug("Scan folder was called");
|
||||||
QStringList torrents;
|
QStringList torrents;
|
||||||
// Local folders scan
|
if(watch_timer) {
|
||||||
addTorrentsFromDir(QDir(path), torrents);
|
torrents = watched_folder.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||||
// Report detected torrent files
|
} else {
|
||||||
if(!torrents.empty()) {
|
torrents = QDir(QFileSystemWatcher::directories().first()).entryList(filters, QDir::Files, QDir::Unsorted);
|
||||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
qDebug("FSWatcher: Polling manually folder %s", QFileSystemWatcher::directories().first().toLocal8Bit().data());
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ protected:
|
|||||||
static QString geoipFolder(bool embedded=false) {
|
static QString geoipFolder(bool embedded=false) {
|
||||||
if(embedded)
|
if(embedded)
|
||||||
return ":/geoip/";
|
return ":/geoip/";
|
||||||
return misc::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
return misc::qBittorrentPath()+"geoip"+QDir::separator();
|
||||||
#else
|
#else
|
||||||
static QString geoipFolder(bool) {
|
static QString geoipFolder(bool) {
|
||||||
if(QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
if(QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
||||||
@@ -86,9 +86,9 @@ public:
|
|||||||
exportEmbeddedDb();
|
exportEmbeddedDb();
|
||||||
#endif
|
#endif
|
||||||
if(QFile::exists(geoipDBpath(false))) {
|
if(QFile::exists(geoipDBpath(false))) {
|
||||||
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
|
qDebug("Loading GeoIP database from %s...", geoipDBpath(false).toLocal8Bit().data());
|
||||||
if(!s->load_country_db(geoipDBpath(false).toLocal8Bit().constData())) {
|
if(!s->load_country_db(geoipDBpath(false).toLocal8Bit().data())) {
|
||||||
std::cerr << "Failed to load Geoip Database at " << qPrintable(geoipDBpath(false)) << std::endl;
|
std::cerr << "Failed to load Geoip Database at " << geoipDBpath(false).toLocal8Bit().data() << std::endl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug("ERROR: Impossible to find local Geoip Database");
|
qDebug("ERROR: Impossible to find local Geoip Database");
|
||||||
|
|||||||
@@ -41,98 +41,97 @@
|
|||||||
class HeadlessLoader: QObject {
|
class HeadlessLoader: QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
private:
|
||||||
HeadlessLoader(QStringList torrentCmdLine) {
|
QLocalServer *localServer;
|
||||||
// Enable Web UI
|
Bittorrent *BTSession;
|
||||||
Preferences::setWebUiEnabled(true);
|
|
||||||
// Instanciate Bittorrent Object
|
public:
|
||||||
BTSession = new Bittorrent();
|
HeadlessLoader(QStringList torrentCmdLine) {
|
||||||
connect(BTSession, SIGNAL(newConsoleMessage(QString)), this, SLOT(displayConsoleMessage(QString)));
|
// Enable Web UI
|
||||||
// Resume unfinished torrents
|
Preferences::setWebUiEnabled(true);
|
||||||
BTSession->startUpTorrents();
|
// Instanciate Bittorrent Object
|
||||||
// Process command line parameters
|
BTSession = new Bittorrent();
|
||||||
processParams(torrentCmdLine);
|
connect(BTSession, SIGNAL(newConsoleMessage(QString)), this, SLOT(displayConsoleMessage(QString)));
|
||||||
// Use a tcp server to allow only one instance of qBittorrent
|
// Resume unfinished torrents
|
||||||
localServer = new QLocalServer();
|
BTSession->startUpTorrents();
|
||||||
const QString &uid = QString::number(getuid());
|
// Process command line parameters
|
||||||
|
processParams(torrentCmdLine);
|
||||||
|
// Use a tcp server to allow only one instance of qBittorrent
|
||||||
|
localServer = new QLocalServer();
|
||||||
|
QString uid = QString::number(getuid());
|
||||||
#ifdef Q_WS_X11
|
#ifdef Q_WS_X11
|
||||||
if(QFile::exists(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid)) {
|
if(QFile::exists(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid)) {
|
||||||
// Socket was not closed cleanly
|
// Socket was not closed cleanly
|
||||||
std::cerr << "Warning: Local domain socket was not closed cleanly, deleting file..." << std::endl;
|
std::cerr << "Warning: Local domain socket was not closed cleanly, deleting file...\n";
|
||||||
QFile::remove(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid);
|
QFile::remove(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!localServer->listen("qBittorrent-"+uid)) {
|
if (!localServer->listen("qBittorrent-"+uid)) {
|
||||||
std::cerr << "Couldn't create socket, single instance mode won't work..." << std::endl;
|
std::cerr << "Couldn't create socket, single instance mode won't work...\n";
|
||||||
|
}
|
||||||
|
connect(localServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
|
||||||
|
// Display some information to the user
|
||||||
|
std::cout << std::endl << "******** " << tr("Information").toLocal8Bit().data() << " ********" << std::endl;
|
||||||
|
std::cout << tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(Preferences::getWebUiPort())).toLocal8Bit().data() << std::endl;
|
||||||
|
std::cout << tr("The Web UI administrator user name is: %1").arg(Preferences::getWebUiUsername()).toLocal8Bit().data() << std::endl;
|
||||||
|
if(Preferences::getWebUiPassword() == "f6fdffe48c908deb0f4c3bd36c032e72") {
|
||||||
|
std::cout << tr("The Web UI administrator password is still the default one: %1").arg("adminadmin").toLocal8Bit().data() << std::endl;
|
||||||
|
std::cout << tr("This is a security risk, please consider changing your password from program preferences.").toLocal8Bit().data() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
connect(localServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
|
|
||||||
// Display some information to the user
|
~HeadlessLoader() {
|
||||||
std::cout << std::endl << "******** " << qPrintable(tr("Information")) << " ********" << std::endl;
|
delete BTSession;
|
||||||
std::cout << qPrintable(tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(Preferences::getWebUiPort()))) << std::endl;
|
|
||||||
std::cout << qPrintable(tr("The Web UI administrator user name is: %1").arg(Preferences::getWebUiUsername())) << std::endl;
|
|
||||||
if(Preferences::getWebUiPassword() == "f6fdffe48c908deb0f4c3bd36c032e72") {
|
|
||||||
std::cout << qPrintable(tr("The Web UI administrator password is still the default one: %1").arg("adminadmin")) << std::endl;
|
|
||||||
std::cout << qPrintable(tr("This is a security risk, please consider changing your password from program preferences.")) << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
~HeadlessLoader() {
|
public slots:
|
||||||
delete localServer;
|
// Call this function to exit qBittorrent headless loader
|
||||||
delete BTSession;
|
// and return to prompt (object will be deleted by main)
|
||||||
}
|
void exit() {
|
||||||
|
qApp->quit();
|
||||||
|
}
|
||||||
|
|
||||||
public slots:
|
void displayConsoleMessage(QString msg) {
|
||||||
// Call this function to exit qBittorrent headless loader
|
std::cout << msg.toLocal8Bit().data() << std::endl;
|
||||||
// and return to prompt (object will be deleted by main)
|
}
|
||||||
void exit() {
|
|
||||||
qApp->quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayConsoleMessage(QString msg) {
|
// As program parameters, we can get paths or urls.
|
||||||
std::cout << qPrintable(msg) << std::endl;
|
// This function parse the parameters and call
|
||||||
}
|
// the right addTorrent function, considering
|
||||||
|
// the parameter type.
|
||||||
// As program parameters, we can get paths or urls.
|
void processParams(const QStringList& params) {
|
||||||
// This function parse the parameters and call
|
foreach(QString param, params) {
|
||||||
// the right addTorrent function, considering
|
param = param.trimmed();
|
||||||
// the parameter type.
|
if(param.startsWith("--")) continue;
|
||||||
void processParams(const QStringList& params) {
|
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||||
foreach(QString param, params) {
|
BTSession->downloadFromUrl(param);
|
||||||
param = param.trimmed();
|
}else{
|
||||||
if(param.startsWith("--")) continue;
|
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
BTSession->addMagnetUri(param);
|
||||||
BTSession->downloadFromUrl(param);
|
} else {
|
||||||
}else{
|
BTSession->addTorrent(param);
|
||||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
}
|
||||||
BTSession->addMagnetUri(param);
|
|
||||||
} else {
|
|
||||||
BTSession->addTorrent(param);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void acceptConnection() {
|
void acceptConnection() {
|
||||||
QLocalSocket *clientConnection = localServer->nextPendingConnection();
|
QLocalSocket *clientConnection = localServer->nextPendingConnection();
|
||||||
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(readParamsOnSocket()));
|
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(readParamsOnSocket()));
|
||||||
qDebug("accepted connection from another instance");
|
qDebug("accepted connection from another instance");
|
||||||
}
|
|
||||||
|
|
||||||
void readParamsOnSocket() {
|
|
||||||
QLocalSocket *clientConnection = static_cast<QLocalSocket*>(sender());
|
|
||||||
if(clientConnection) {
|
|
||||||
const QByteArray ¶ms = clientConnection->readAll();
|
|
||||||
if(!params.isEmpty()) {
|
|
||||||
processParams(QString(params).split("\n"));
|
|
||||||
qDebug("Received parameters from another instance");
|
|
||||||
}
|
|
||||||
clientConnection->deleteLater();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
void readParamsOnSocket() {
|
||||||
QLocalServer *localServer;
|
QLocalSocket *clientConnection = static_cast<QLocalSocket*>(sender());
|
||||||
Bittorrent *BTSession;
|
if(clientConnection) {
|
||||||
|
QByteArray params = clientConnection->readAll();
|
||||||
|
if(!params.isEmpty()) {
|
||||||
|
processParams(QString::fromUtf8(params.data()).split(QString::fromUtf8("\n")));
|
||||||
|
qDebug("Received parameters from another instance");
|
||||||
|
}
|
||||||
|
clientConnection->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||