Compare commits
39 Commits
release-2.
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cf2b44b8a | ||
|
|
ba22fa8331 | ||
|
|
5ce02cb612 | ||
|
|
1013f39a42 | ||
|
|
cd5c4bf464 | ||
|
|
84bfc54b03 | ||
|
|
5b3b5eb2ef | ||
|
|
990a863d41 | ||
|
|
7f27d10735 | ||
|
|
1377a75a53 | ||
|
|
bcd33fc861 | ||
|
|
46d8fa1656 | ||
|
|
28cf69b84d | ||
|
|
89389df74d | ||
|
|
77c29f48cb | ||
|
|
c5d92f3d69 | ||
|
|
54487c8247 | ||
|
|
be64008870 | ||
|
|
8113b150dd | ||
|
|
4a33367cb0 | ||
|
|
0af5d82114 | ||
|
|
10c4fd330a | ||
|
|
9a30d5a295 | ||
|
|
724b47d999 | ||
|
|
2c0f7c33a2 | ||
|
|
ce33e266fe | ||
|
|
2f291daefa | ||
|
|
722f2aeb5d | ||
|
|
d5b9598b5b | ||
|
|
cc7d74b67c | ||
|
|
e853b0b736 | ||
|
|
5e395b24a9 | ||
|
|
9c3789f83f | ||
|
|
758595dc8c | ||
|
|
01f9e989ef | ||
|
|
eb9f0cb559 | ||
|
|
2592948182 | ||
|
|
6f6ab1c439 | ||
|
|
b10e606dda |
11
AUTHORS
@@ -3,19 +3,12 @@ Author:
|
||||
|
||||
Contributors:
|
||||
* Stefanos Antaris <santaris@csd.auth.gr>
|
||||
* Mohammad Dib <mdib@qbittorrent.org>
|
||||
* Mirco Chinelli <infinity89@fastwebmail.it>
|
||||
* Ishan Arora <ishan@qbittorrent.org>
|
||||
* Arnaud Demaizière <arnaud@qbittorrent.org>
|
||||
* Grigis Gaëtan <cipher16@gmail.com>
|
||||
* Christian Kandeler <zambesi@users.sourceforge.net>
|
||||
* Silvan Scherrer <silvan.scherrer@aroa.ch>
|
||||
|
||||
Code from other projects:
|
||||
* files src/qtsingleapp/* src/lineedit/*
|
||||
copyright: Nokia Corporation
|
||||
license: LGPL
|
||||
|
||||
* files src/ico.cpp src/ico.h
|
||||
copyright: Malte Starostik <malte@kde.org>
|
||||
license: LGPL
|
||||
@@ -67,13 +60,11 @@ Images Authors:
|
||||
Translations authors:
|
||||
* files: src/lang/*.ts
|
||||
copyright:
|
||||
- Arabic: SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)
|
||||
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
|
||||
- Bulgarian: Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)
|
||||
- Catalan: Francisco Luque Contreras (frannoe@ya.com)
|
||||
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
|
||||
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
|
||||
- Croatian: Oliver Mucafir (oliver.untwist@gmail.com)
|
||||
- Czech: Jirka Vilim (web@tets.cz)
|
||||
- Danish: Mathias Nielsen (comoneo@gmail.com)
|
||||
- Dutch: Joost Schipper (heavyjoost@users.sourceforge.net)
|
||||
@@ -83,7 +74,7 @@ Translations authors:
|
||||
- German: Niels Hoffmann (zentralmaschine@users.sourceforge.net)
|
||||
- Greek: Tsvetan Bankov (emerge_life@users.sourceforge.net) and Stephanos Antaris (santaris@csd.auth.gr)
|
||||
- Hungarian: Majoros Péter (majoros.j.p@t-online.hu)
|
||||
- Italian: Matteo Sechi (bu17714@gmail.com)
|
||||
- Italian: Mirko Ferrari (mirkoferrari@gmail.com) and Ferraro Luciano (luciano.ferraro@gmail.com)
|
||||
- Japanese: Nardog (alphisation@gmail.com)
|
||||
- Korean: Jin Woo Sin (jin828sin@users.sourceforge.net)
|
||||
- Norwegian: Lars-Erik Labori (hamil@users.sourceforge.net)
|
||||
|
||||
147
Changelog
@@ -1,128 +1,29 @@
|
||||
* Wed Nov 10 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.10
|
||||
- BUGFIX: Fix possible crash when selecting a RSS item (really closes #575624)
|
||||
- BUGFIX: Improved IPv6 support (IP filter and Peer list)
|
||||
- BUGFIX: Make IP filter more tolerant towards strangely formatted IPs
|
||||
- BUGFIX: More reliable folder scanning
|
||||
- BUGFIX: Do not create the torrent root folder at final destination if
|
||||
torrent is in the temp dir (closes #673271)
|
||||
- BUGFIX: Fix compilation with libnotify v0.7.0 (closes #671769)
|
||||
- BUGFIX: Use a pointing cursor over status bar buttons
|
||||
* Sun Apr 04 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.3
|
||||
- BUGFIX: Fix possible crash when deleting a torrent just after pausing it
|
||||
- BUGFIX: Enable Apply button when alternative rate limits are changed
|
||||
- BUGFIX: Source compatibility with Windows (Thanks Ishan Arora)
|
||||
- BUGFIX: Source compatibility with eCS (OS/2) (Thanks Silvan Scherrer)
|
||||
- BUGFIX: Cleaner binutils gold linker support
|
||||
- BUGFIX: Clean fix for progress display with cleanlooks style
|
||||
|
||||
* Sun Oct 31 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.9
|
||||
- BUGFIX: Fix crash when pressing enter in save path field in torrent addition dialog
|
||||
- BUGFIX: Fix crash when deleting a torrent with no metadata (closes #667528)
|
||||
- BUGFIX: Fix possible crash on clicking a RSS article (closes #575624)
|
||||
- BUGFIX: Correctly update total number of torrents when a torrent is automatically removed (closes #668726)
|
||||
- BUGFIX: Correctly display the hash of torrents with no metadata
|
||||
- BUGFIX: Elide status bar text if it is too wide
|
||||
- BUGFIX: Make sure the splash screen is displayed for 2 seconds
|
||||
- BUGFIX: Make listening on a particular interface more reliable
|
||||
- BUGFIX: Fix torrent size update in torrent addition dialog
|
||||
- BUGFIX: Fix possible crash on qBittorrent shutdown
|
||||
- BUGFIX: Fix and improve file priorities editing (closes #669084)
|
||||
- I18N: Updated Arabic, Italian and Croatian translations
|
||||
* Mon Mar 22 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.2
|
||||
- FEATURE: DHT port can be set from Web UI
|
||||
- BUGFIX: Fix possible crash with folder scanning
|
||||
- BUGFIX: Fix Mac compilation
|
||||
- BUGFIX: Save fast resume data every 3 minutes (for robustness)
|
||||
- I18N: Updated Polish translation (thanks Szymon Świerkosz)
|
||||
|
||||
* Sun Oct 24 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.8
|
||||
- BUGFIX: Fix possible crash on manual peer ban
|
||||
- BUGFIX: Improved hostname resolution code
|
||||
- BUGFIX: Several search plugins fixed
|
||||
- BUGFIX: Auto-disable the shutdown feature
|
||||
- BUGFIX: Remember the current property tab on startup
|
||||
- BUGFIX: Fix status list widget height issue on style change
|
||||
- BUGFIX: Fix rounding issue in torrent progress display
|
||||
- BUGFIX: Fix issue when altering files priorities of a seeding torrent
|
||||
- BUGFIX: Better fix for save path editing issues in torrent addition dialog
|
||||
- BUGFIX: Peers can now be sorted by country
|
||||
|
||||
* Tue Oct 19 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.7
|
||||
- BUGFIX: Display the priority column when the queueing system gets enabled
|
||||
- BUGFIX: Fix encoding problem in file renaming
|
||||
- BUGFIX: Delete uneeded files on torrent "soft" deletion
|
||||
- BUGFIX: Fix issues when marking a file as 'not downloaded' causes the torrent to complete
|
||||
- BUGFIX: Improved "Set Location" and "Change save path" dialogs
|
||||
- BUGFIX: Fix display of queued seeding torrents
|
||||
|
||||
* Sun Oct 17 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.6
|
||||
- BUGFIX: Fix "torrent seeding after creation" feature
|
||||
- BUGFIX: The properties panel data would sometimes not match the selected torrent
|
||||
- BUGFIX: Fix detection of files at final destination when temp dir is used
|
||||
- BUGFIX: Fix moving of a torrent to an unexisting directory
|
||||
|
||||
* Tue Oct 12 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.5
|
||||
- BUGFIX: Remember torrent completion date correctly
|
||||
- BUGFIX: Fix feature to keep incomplete torrents in a separate folder
|
||||
- BUGFIX: Fix display of URL seeds in the UI
|
||||
- BUGFIX: Improved peer hostname resolution with caching
|
||||
- BUGFIX: Piece availability/downloaded widgets performance improvement
|
||||
|
||||
* Fri Oct 1 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.4
|
||||
- BUGFIX: Clean program exit on system shutdown/logout
|
||||
- BUGFIX: Fix possible search engine plugin update
|
||||
|
||||
* Tue Sep 28 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.3
|
||||
- BUGFIX: Fix encoding issue in command line parameters processing
|
||||
- BUGFIX: Fix possible crash when changing the save path in addition dialog
|
||||
- BUGFIX: Fix wrong mapping to source model
|
||||
|
||||
* Sun Sep 26 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.2
|
||||
- BUGFIX: Fix display of torrent content in addition dialog
|
||||
- BUGFIX: Really fix manual editing of save path in torrent addition dialog
|
||||
|
||||
* Sun Sep 26 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.1
|
||||
- I18N: Updated Arabic translation
|
||||
- I18N: Fixes to German translation
|
||||
- BUGFIX: Save path can now be edited in torrent addition dialog
|
||||
- BUGFIX: Fix save path encoding on non-utf8 systems
|
||||
- BUGFIX: Fix saving to drive root on Windows
|
||||
- BUGFIX: OGV can now be previewed
|
||||
- BUGFIX: Maximum download limit is now 10MB/s
|
||||
- BUGFIX: Fix 'download in scan dir' persistence
|
||||
- BUGFIX: Add .torrent extension only when missing (torrent creator)
|
||||
- BUGFIX: Fix possible issue with temporary download path persistence
|
||||
- BUGFIX: Added support for | (OR) operator in RSS feed downloader
|
||||
- BUGFIX: Fix Web UI for spanish users
|
||||
- BUGFIX: Fix locale switching from Web UI
|
||||
- BUGFIX: Use AND operator for torrentdownloads.net searches
|
||||
- BUGFIX: Limit torrent addition dialog width to fit the screen
|
||||
- COSMETIC: Fix progress bars style on Windows
|
||||
|
||||
* Tue Aug 24 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.0
|
||||
- FEATURE: Added actions to "Move to top/bottom" of priority queue
|
||||
- FEATURE: Auto-Shutdown on downloads completion
|
||||
- FEATURE: Email notification on download completion
|
||||
- FEATURE: Added button to password-lock the UI
|
||||
- FEATURE: Added label-level Pause/Resume/Delete actions
|
||||
- FEATURE: Torrents can now be filtered by name
|
||||
- FEATURE: Run external program on torrent completion
|
||||
- FEATURE: Detect executable updates in order to advise the user to restart
|
||||
|
||||
* Tue Jul 27 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.3.0
|
||||
- FEATURE: Simplified torrent root folder renaming/truncating (< v2.3.0 is no longer forward compatible)
|
||||
- FEATURE: Remember previous save paths in torrent addition dialog
|
||||
- FEATURE: Max number of half-open connections can now be edited
|
||||
- FEATURE: Added support for strict super seeding
|
||||
- FEATURE: The user can force listening on a particular network interface
|
||||
- FEATURE: Added cookie support for RSS feeds
|
||||
- FEATURE: User can force tracker reannounce
|
||||
- FEATURE: Added "No action" setting for double-click action
|
||||
- FEATURE: Several torrents can be moved at once
|
||||
- FEATURE: Added error state for torrents (error is displayed in a tooltip)
|
||||
- FEATURE: Added filter for paused/error torrents
|
||||
- FEATURE: Add Check/Uncheck all feature in Web UI
|
||||
- FEATURE: Search engine can now be disabled
|
||||
- FEATURE: Torrents can be automatically paused once they reach a given ratio
|
||||
- FEATURE: Several files can now be disabled at once
|
||||
- FEATURE: Added "Select All/None" buttons to files list
|
||||
- FEATURE: Added support for BitComet links (bc://bt/...)
|
||||
- BUGFIX: Hide seeding torrents files priorities in Web UI
|
||||
- BUGFIX: The user can disable permanently recursive torrent download
|
||||
- BUGFIX: Peer Exchange status is now correctly reported
|
||||
- BUGFIX: Use an INI file instead of the registry on Windows (More reliable)
|
||||
- BUGFIX: Removed client spoofing feature to avoid tracker blacklisting
|
||||
- COSMETIC: Display peers country name in tooltip
|
||||
- COSMETIC: Display number of torrents in transfers tab label
|
||||
- COSMETIC: Simplified program preferences
|
||||
- COSMETIC: Fix naming of actions opening new dialogs (use Name...)
|
||||
* Sat Mar 20 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.1
|
||||
- FEATURE: Display pieces that are being downloaded
|
||||
- FEATURE: Added back folder watching in Web UI
|
||||
- FEATURE: Added back file prioritizing in Web UI
|
||||
- BUGFIX: Fix compilation with Qt 4.4
|
||||
- BUGFIX: Fix Web UI compatibility with Safari
|
||||
- BUGFIX: Fix progress display with cleanlook style
|
||||
- BUGFIX: Fix file filtering in complex torrents
|
||||
- BUGFIX: Ask for user confirmation for recursive torrent download
|
||||
- BUGFIX: Fix "add file" dialog in torrent creation tool
|
||||
- BUGFIX: Fix "Ctrl+A" in Web UI
|
||||
|
||||
* Sun Mar 14 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.0
|
||||
- FEATURE: User can set alternative speed limits for fast toggling
|
||||
|
||||
6
INSTALL
@@ -14,13 +14,11 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
|
||||
- pkg-config executable
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, compatible with v0.15.x)
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, >= v0.15.0 ADVISED)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
- libboost 1.34.x (libboost-filesystem, libboost-thread, libboost-date-time) + libasio
|
||||
or
|
||||
- libboost >= 1.35.x (libboost-system, libboost-filesystem, libboost-thread, libboost-date-time)
|
||||
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
|
||||
|
||||
- python >= 2.3 (needed by search engine)
|
||||
* Run time only dependency
|
||||
|
||||
62
README.os2
@@ -1,62 +0,0 @@
|
||||
qBittorrent - A BitTorrent client in Qt4
|
||||
------------------------------------------
|
||||
|
||||
This is the eComStation (OS/2) qBittorrent part of the readme. See also README for more general information.
|
||||
|
||||
|
||||
Building qBittorrent
|
||||
********************
|
||||
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- gcc based build env (recommended gcc v4.4.2 or greater)
|
||||
|
||||
- Qt4 for eCS (OS/2) dev package (see http://svn.netlabs.org/qt4 for more information)
|
||||
|
||||
- libtorrent-rasterbar for eCS (OS/2) port (see http://svn.netlabs.org/ports for more information)
|
||||
|
||||
- boost for eCS (OS/2) port (see http://svn.netlabs.org/ports for more information)
|
||||
|
||||
|
||||
How to build
|
||||
============
|
||||
|
||||
First you need to create the conf.pri file in the same dir as this readme.os2 is.
|
||||
the conf.pri file has the following content:
|
||||
|
||||
##### conf.pri content beginn #####
|
||||
PREFIX = .
|
||||
BINDIR = ./bin
|
||||
INCDIR = ./include
|
||||
LIBDIR = ./lib
|
||||
DATADIR = ./share
|
||||
|
||||
CONFIG += staticlib
|
||||
INCLUDEPATH += x:/trees/libtorrent/trunk/include
|
||||
LIBS += -Lx:/trees/libtorrent/trunk/src/.libs \
|
||||
-Lx:/trees/boost/trunk/stage/lib \
|
||||
-Lx:/trees/openssl \
|
||||
-Lx:/extras/lib
|
||||
##### conf.pri content end #####
|
||||
|
||||
Of course all the above path references have to be adjusted to your build env.
|
||||
|
||||
It should now be easy to build qBittorrent:
|
||||
|
||||
Simply type:
|
||||
$ qmake
|
||||
|
||||
Followed by:
|
||||
$ make
|
||||
|
||||
If all works fine you should get a working qbittorrent executable.
|
||||
|
||||
If you have any question regarding the eCS (OS/2) port of qBittorrent you can meet me (_diver) on IRC:
|
||||
#netlabs on irc.freenode.net
|
||||
|
||||
------------------------------------------
|
||||
Silvan Scherrer <silvan.scherrer@aroa.ch>
|
||||
|
||||
|
||||
183
configure
vendored
@@ -18,24 +18,15 @@ Main options:
|
||||
--help This help text.
|
||||
|
||||
Dependency options:
|
||||
--disable-gui Disable qBittorrent
|
||||
Graphical user interface for
|
||||
headless running
|
||||
--with-libboost-inc=[path] Path to libboost include
|
||||
files
|
||||
--with-libboost-lib=[path] Path to libboost library
|
||||
files
|
||||
--disable-libnotify Disable use of libnotify
|
||||
--disable-geoip-database Disable use of geoip-database
|
||||
--with-geoip-database-embedded Geoip Database will be
|
||||
embedded in qBittorrent
|
||||
executable (please follow
|
||||
instructions in
|
||||
src/geoip/README)
|
||||
--disable-qtsingleapplication Disable use of libboost
|
||||
--with-qtsingleapplication=[system|shipped] Use the shipped
|
||||
qtsingleapplication library
|
||||
or the system one
|
||||
--disable-gui Disable qBittorrent Graphical user
|
||||
interface for headless running
|
||||
--with-libboost-inc=[path] Path to libboost include files
|
||||
--with-libboost-lib=[path] Path to libboost library files
|
||||
--disable-libnotify Disable use of libnotify
|
||||
--disable-geoip-database Disable use of geoip-database
|
||||
--with-geoip-database-embedded Geoip Database will be embedded in
|
||||
qBittorrent executable (please follow
|
||||
instructions in src/geoip/README)
|
||||
|
||||
EOT
|
||||
}
|
||||
@@ -182,16 +173,6 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-qtsingleapplication)
|
||||
QC_DISABLE_qtsingleapplication="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-qtsingleapplication=*)
|
||||
QC_WITH_QTSINGLEAPPLICATION=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--verbose)
|
||||
QC_VERBOSE="Y"
|
||||
shift
|
||||
@@ -219,8 +200,6 @@ echo QC_WITH_LIBBOOST_LIB=$QC_WITH_LIBBOOST_LIB
|
||||
echo QC_DISABLE_libnotify=$QC_DISABLE_libnotify
|
||||
echo QC_DISABLE_geoip_database=$QC_DISABLE_geoip_database
|
||||
echo QC_WITH_GEOIP_DATABASE_EMBEDDED=$QC_WITH_GEOIP_DATABASE_EMBEDDED
|
||||
echo QC_DISABLE_qtsingleapplication=$QC_DISABLE_qtsingleapplication
|
||||
echo QC_WITH_QTSINGLEAPPLICATION=$QC_WITH_QTSINGLEAPPLICATION
|
||||
echo
|
||||
fi
|
||||
|
||||
@@ -376,15 +355,27 @@ public:
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.4";
|
||||
QString adv_ver = "0.15.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
conf->addLib("-lcrypto");
|
||||
}
|
||||
//if(!libs.isEmpty())
|
||||
// conf->addLib(libs);
|
||||
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());
|
||||
else
|
||||
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());
|
||||
//libcrypto
|
||||
conf->addLib("-lcrypto");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -396,36 +387,12 @@ arg: with-libboost-inc=[path], Path to libboost include files
|
||||
arg: with-libboost-lib=[path], Path to libboost library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <boost/version.hpp>
|
||||
class qc_libboost : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
QString findBoostLib(QString path, QString lib) const {
|
||||
QString name;
|
||||
QDir libDir(path);
|
||||
QStringList filters;
|
||||
filters << "libboost_"+lib+"*-mt*.so";
|
||||
QStringList result = libDir.entryList(filters, QDir::Files);
|
||||
if(!result.empty()) {
|
||||
name = result.first().mid(3);
|
||||
// Remove .so
|
||||
name.chop(3);
|
||||
} else {
|
||||
// Fall back to non -mt boost lib
|
||||
filters.clear();
|
||||
filters << "libboost_"+lib+"*.so";
|
||||
result = libDir.entryList(filters, QDir::Files);
|
||||
if(!result.empty()) {
|
||||
name = result.first().mid(3);
|
||||
// Remove .so
|
||||
name.chop(3);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
@@ -469,41 +436,28 @@ public:
|
||||
conf->addIncludePath(s);
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
QStringList required_libs;
|
||||
#if BOOST_VERSION >= 103500
|
||||
required_libs << "system";
|
||||
#endif
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
// Not required by nox
|
||||
required_libs << "filesystem" << "thread";
|
||||
}
|
||||
QStringList libDirs;
|
||||
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
|
||||
foreach(const QString& lib, required_libs) {
|
||||
if(!s.isEmpty()) {
|
||||
QString detected_name = findBoostLib(s, lib);
|
||||
if(detected_name.isEmpty()) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
} else {
|
||||
conf->addLib("-l"+detected_name);
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "boost_system-mt")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "boost_system-mt")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
conf->addLib("-lboost_system-mt -lboost_filesystem-mt -lboost_thread-mt");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -550,21 +504,10 @@ public:
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
QStringList incs3;
|
||||
QString req_ver3 = "2.0";
|
||||
QString version3, libs3, other3;
|
||||
if(conf->findPkgConfig("gtk+-2.0", mode, req_ver3, &version3, &incs3, &libs3, &other3)) {
|
||||
for(int n = 0; n < incs3.count(); ++n)
|
||||
conf->addIncludePath(incs3[n]);
|
||||
if(!libs3.isEmpty())
|
||||
conf->addLib(libs3);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -606,33 +549,6 @@ public:
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#line 1 "qtsingleapplication.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libboost
|
||||
arg: with-qtsingleapplication=[system|shipped], Use the shipped qtsingleapplication library or the system one
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_qtsingleapplication : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qtsingleapplication(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "qtsingleapplication library"; }
|
||||
QString shortname() const { return "qtsingleapplication"; }
|
||||
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_QTSINGLEAPPLICATION");
|
||||
if(s.compare("system", Qt::CaseInsensitive) == 0) {
|
||||
// System
|
||||
conf->addDefine("USE_SYSTEM_QTSINGLEAPPLICATION");
|
||||
printf(" [system] ");
|
||||
} else {
|
||||
printf(" [shipped] ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
EOT
|
||||
cat >$1/modules_new.cpp <<EOT
|
||||
@@ -654,9 +570,6 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_geoip_database(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_qtsingleapplication(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
|
||||
EOT
|
||||
cat >$1/conf4.h <<EOT
|
||||
@@ -1608,8 +1521,6 @@ export QC_WITH_LIBBOOST_LIB
|
||||
export QC_DISABLE_libnotify
|
||||
export QC_DISABLE_geoip_database
|
||||
export QC_WITH_GEOIP_DATABASE_EMBEDDED
|
||||
export QC_DISABLE_qtsingleapplication
|
||||
export QC_WITH_QTSINGLEAPPLICATION
|
||||
export QC_VERBOSE
|
||||
rm -rf .qconftemp
|
||||
(
|
||||
|
||||
@@ -19,6 +19,4 @@
|
||||
</dep>
|
||||
<dep type='geoip-database'>
|
||||
</dep>
|
||||
<dep type='qtsingleapplication'>
|
||||
</dep>
|
||||
</qconf>
|
||||
|
||||
@@ -5,36 +5,12 @@ arg: with-libboost-inc=[path], Path to libboost include files
|
||||
arg: with-libboost-lib=[path], Path to libboost library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <boost/version.hpp>
|
||||
class qc_libboost : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
QString findBoostLib(QString path, QString lib) const {
|
||||
QString name;
|
||||
QDir libDir(path);
|
||||
QStringList filters;
|
||||
filters << "libboost_"+lib+"*-mt*.so";
|
||||
QStringList result = libDir.entryList(filters, QDir::Files);
|
||||
if(!result.empty()) {
|
||||
name = result.first().mid(3);
|
||||
// Remove .so
|
||||
name.chop(3);
|
||||
} else {
|
||||
// Fall back to non -mt boost lib
|
||||
filters.clear();
|
||||
filters << "libboost_"+lib+"*.so";
|
||||
result = libDir.entryList(filters, QDir::Files);
|
||||
if(!result.empty()) {
|
||||
name = result.first().mid(3);
|
||||
// Remove .so
|
||||
name.chop(3);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
@@ -78,41 +54,28 @@ public:
|
||||
conf->addIncludePath(s);
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
QStringList required_libs;
|
||||
#if BOOST_VERSION >= 103500
|
||||
required_libs << "system";
|
||||
#endif
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
// Not required by nox
|
||||
required_libs << "filesystem" << "thread";
|
||||
}
|
||||
QStringList libDirs;
|
||||
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
|
||||
foreach(const QString& lib, required_libs) {
|
||||
if(!s.isEmpty()) {
|
||||
QString detected_name = findBoostLib(s, lib);
|
||||
if(detected_name.isEmpty()) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
} else {
|
||||
conf->addLib("-l"+detected_name);
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "boost_system-mt")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "boost_system-mt")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
conf->addLib("-lboost_system-mt -lboost_filesystem-mt -lboost_thread-mt");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,21 +40,10 @@ public:
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
QStringList incs3;
|
||||
QString req_ver3 = "2.0";
|
||||
QString version3, libs3, other3;
|
||||
if(conf->findPkgConfig("gtk+-2.0", mode, req_ver3, &version3, &incs3, &libs3, &other3)) {
|
||||
for(int n = 0; n < incs3.count(); ++n)
|
||||
conf->addIncludePath(incs3[n]);
|
||||
if(!libs3.isEmpty())
|
||||
conf->addLib(libs3);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,15 +13,27 @@ public:
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.4";
|
||||
QString adv_ver = "0.15.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
conf->addLib("-lcrypto");
|
||||
}
|
||||
//if(!libs.isEmpty())
|
||||
// conf->addLib(libs);
|
||||
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());
|
||||
else
|
||||
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());
|
||||
//libcrypto
|
||||
conf->addLib("-lcrypto");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libboost
|
||||
arg: with-qtsingleapplication=[system|shipped], Use the shipped qtsingleapplication library or the system one
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_qtsingleapplication : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qtsingleapplication(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "qtsingleapplication library"; }
|
||||
QString shortname() const { return "qtsingleapplication"; }
|
||||
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_QTSINGLEAPPLICATION");
|
||||
if(s.compare("system", Qt::CaseInsensitive) == 0) {
|
||||
// System
|
||||
conf->addDefine("USE_SYSTEM_QTSINGLEAPPLICATION");
|
||||
printf(" [system] ");
|
||||
} else {
|
||||
printf(" [shipped] ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
572
src/GUI.cpp
@@ -34,15 +34,15 @@
|
||||
#endif
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
#include <QDesktopServices>
|
||||
#include <QStatusBar>
|
||||
#include <QClipboard>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QCloseEvent>
|
||||
#include <QShortcut>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "GUI.h"
|
||||
#include "transferlistwidget.h"
|
||||
@@ -65,14 +65,11 @@
|
||||
#include "transferlistfilterswidget.h"
|
||||
#include "propertieswidget.h"
|
||||
#include "statusbar.h"
|
||||
#include "hidabletabwidget.h"
|
||||
#include "qinisettings.h"
|
||||
#ifdef Q_WS_MAC
|
||||
#include "qmacapplication.h"
|
||||
void qt_mac_set_dock_menu(QMenu *menu);
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
#include <windows.h>
|
||||
const int UNLEN = 256;
|
||||
#endif
|
||||
#include "lineedit.h"
|
||||
#include "sessionapplication.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
@@ -85,13 +82,10 @@ using namespace libtorrent;
|
||||
*****************************************************/
|
||||
|
||||
// Constructor
|
||||
GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), force_exit(false) {
|
||||
GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), displaySpeedInTitle(false), force_exit(false) {
|
||||
setupUi(this);
|
||||
ui_locked = Preferences::isUILocked();
|
||||
|
||||
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION)));
|
||||
displaySpeedInTitle = Preferences::speedInTitleBar();
|
||||
// Clean exit on log out
|
||||
connect(static_cast<SessionApplication*>(qApp), SIGNAL(sessionIsShuttingDown()), this, SLOT(deleteBTSession()));
|
||||
// Setting icons
|
||||
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png")));
|
||||
actionOpen->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/open.png")));
|
||||
@@ -113,11 +107,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
|
||||
actionSet_global_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
|
||||
actionSet_global_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/download.png")));
|
||||
actionDocumentation->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/qb_question.png")));
|
||||
actionLock_qBittorrent->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/encrypted32.png")));
|
||||
lockMenu = new QMenu();
|
||||
QAction *defineUiLockPasswdAct = lockMenu->addAction(tr("Set the password..."));
|
||||
connect(defineUiLockPasswdAct, SIGNAL(triggered()), this, SLOT(defineUILockPassword()));
|
||||
actionLock_qBittorrent->setMenu(lockMenu);
|
||||
prioSeparator = toolBar->insertSeparator(actionDecreasePriority);
|
||||
prioSeparator2 = menu_Edit->insertSeparator(actionDecreasePriority);
|
||||
prioSeparator->setVisible(false);
|
||||
@@ -134,12 +123,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
|
||||
connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
|
||||
connect(BTSession, SIGNAL(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
|
||||
connect(BTSession, SIGNAL(recursiveTorrentDownloadPossible(QTorrentHandle&)), this, SLOT(askRecursiveTorrentDownloadConfirmation(QTorrentHandle&)));
|
||||
#ifdef Q_WS_MAC
|
||||
connect(static_cast<QMacApplication*>(qApp), SIGNAL(newFileOpenMacEvent(QString)), this, SLOT(processParams(QString)));
|
||||
#endif
|
||||
|
||||
qDebug("create tabWidget");
|
||||
tabs = new HidableTabWidget();
|
||||
tabs = new QTabWidget();
|
||||
connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tab_changed(int)));
|
||||
vSplitter = new QSplitter(Qt::Horizontal);
|
||||
//vSplitter->setChildrenCollapsible(false);
|
||||
@@ -157,16 +143,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
|
||||
vSplitter->setCollapsible(0, true);
|
||||
vSplitter->setCollapsible(1, false);
|
||||
tabs->addTab(vSplitter, QIcon(QString::fromUtf8(":/Icons/oxygen/folder-remote.png")), tr("Transfers"));
|
||||
connect(transferList, SIGNAL(torrentStatusUpdate(uint,uint,uint,uint,uint)), this, SLOT(updateNbTorrents(uint,uint,uint,uint,uint)));
|
||||
vboxLayout->addWidget(tabs);
|
||||
|
||||
// Name filter
|
||||
search_filter = new LineEdit();
|
||||
QAction *separatorBFSearch = toolBar->insertSeparator(actionLock_qBittorrent);
|
||||
toolBar->insertWidget(separatorBFSearch, search_filter);
|
||||
search_filter->setFixedWidth(200);
|
||||
connect(search_filter, SIGNAL(textChanged(QString)), transferList, SLOT(applyNameFilter(QString)));
|
||||
|
||||
// Transfer list slots
|
||||
connect(actionStart, SIGNAL(triggered()), transferList, SLOT(startSelectedTorrents()));
|
||||
connect(actionStart_All, SIGNAL(triggered()), transferList, SLOT(startAllTorrents()));
|
||||
@@ -176,9 +154,38 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
|
||||
connect(actionIncreasePriority, SIGNAL(triggered()), transferList, SLOT(increasePrioSelectedTorrents()));
|
||||
connect(actionDecreasePriority, SIGNAL(triggered()), transferList, SLOT(decreasePrioSelectedTorrents()));
|
||||
|
||||
// Search engine tab
|
||||
searchEngine = new SearchEngine(this, BTSession);
|
||||
tabs->addTab(searchEngine, QIcon(QString::fromUtf8(":/Icons/oxygen/edit-find.png")), tr("Search"));
|
||||
|
||||
// Configure BT session according to options
|
||||
loadPreferences(false);
|
||||
|
||||
// Resume unfinished torrents
|
||||
BTSession->startUpTorrents();
|
||||
// Add torrent given on command line
|
||||
processParams(torrentCmdLine);
|
||||
// Use a tcp server to allow only one instance of qBittorrent
|
||||
localServer = new QLocalServer();
|
||||
QString uid = "";
|
||||
#ifdef Q_WS_WIN
|
||||
char buffer[UNLEN+1] = {0};
|
||||
DWORD buffer_len = UNLEN + 1;
|
||||
if (!GetUserName(buffer, &buffer_len))
|
||||
uid = QString(buffer)
|
||||
#else
|
||||
uid = QString::number(getuid());
|
||||
#endif
|
||||
#ifdef Q_WS_X11
|
||||
if(QFile::exists(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid)) {
|
||||
// Socket was not closed cleanly
|
||||
std::cerr << "Warning: Local domain socket was not closed cleanly, deleting file...\n";
|
||||
QFile::remove(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid);
|
||||
}
|
||||
#endif
|
||||
if (!localServer->listen("qBittorrent-"+uid)) {
|
||||
std::cerr << "Couldn't create socket, single instance mode won't work...\n";
|
||||
}
|
||||
connect(localServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
|
||||
// Start connection checking timer
|
||||
guiUpdater = new QTimer(this);
|
||||
connect(guiUpdater, SIGNAL(timeout()), this, SLOT(updateGUI()));
|
||||
@@ -190,19 +197,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
|
||||
status_bar = new StatusBar(QMainWindow::statusBar(), BTSession);
|
||||
connect(actionUse_alternative_speed_limits, SIGNAL(triggered()), status_bar, SLOT(toggleAlternativeSpeeds()));
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
#endif
|
||||
|
||||
// View settings
|
||||
actionTop_tool_bar->setChecked(Preferences::isToolbarDisplayed());
|
||||
actionSpeed_in_title_bar->setChecked(Preferences::speedInTitleBar());
|
||||
actionRSS_Reader->setChecked(Preferences::isRSSEnabled());
|
||||
actionSearch_engine->setChecked(Preferences::isSearchEnabled());
|
||||
displaySearchTab(actionSearch_engine->isChecked());
|
||||
displayRSSTab(actionRSS_Reader->isChecked());
|
||||
actionShutdown_when_downloads_complete->setChecked(Preferences::shutdownWhenDownloadsComplete());
|
||||
|
||||
show();
|
||||
|
||||
// Load Window state and sizes
|
||||
@@ -210,76 +204,35 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
|
||||
properties->readSettings();
|
||||
|
||||
// Limit status filters list height
|
||||
transferListFilters->getStatusFilters()->updateHeight();
|
||||
int cur_height = 80;
|
||||
do {
|
||||
transferListFilters->getStatusFilters()->setFixedHeight(cur_height);
|
||||
cur_height += 10;
|
||||
transferListFilters->getStatusFilters()->scrollToBottom();
|
||||
}while(transferListFilters->getStatusFilters()->verticalScrollBar()->sliderPosition() > 0);
|
||||
transferListFilters->getStatusFilters()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
if(ui_locked) {
|
||||
hide();
|
||||
} else {
|
||||
if(Preferences::startMinimized())
|
||||
showMinimized();
|
||||
if(Preferences::startMinimized()) {
|
||||
setWindowState(Qt::WindowMinimized);
|
||||
}
|
||||
|
||||
// Start watching the executable for updates
|
||||
executable_watcher = new QFileSystemWatcher();
|
||||
connect(executable_watcher, SIGNAL(fileChanged(QString)), this, SLOT(notifyOfUpdate(QString)));
|
||||
executable_watcher->addPath(qApp->applicationFilePath());
|
||||
|
||||
// Resume unfinished torrents
|
||||
BTSession->startUpTorrents();
|
||||
// Add torrent given on command line
|
||||
processParams(torrentCmdLine);
|
||||
|
||||
qDebug("GUI Built");
|
||||
#ifdef Q_WS_WIN
|
||||
if(!Preferences::neverCheckFileAssoc() && !Preferences::isFileAssocOk()) {
|
||||
if(QMessageBox::question(0, tr("Torrent file association"),
|
||||
tr("qBittorrent is not the default application to open torrent files or Magnet links.\nDo you want to associate qBittorrent to torrent files and Magnet links?"),
|
||||
QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
|
||||
Preferences::setFileAssoc();
|
||||
} else {
|
||||
Preferences::setNeverCheckFileAssoc();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_WS_MAC
|
||||
qt_mac_set_dock_menu(getTrayIconMenu());
|
||||
#endif
|
||||
}
|
||||
|
||||
void GUI::deleteBTSession() {
|
||||
guiUpdater->stop();
|
||||
status_bar->stopTimer();
|
||||
if(BTSession) {
|
||||
delete BTSession;
|
||||
BTSession = 0;
|
||||
}
|
||||
QTimer::singleShot(0, this, SLOT(close()));
|
||||
}
|
||||
|
||||
// Destructor
|
||||
GUI::~GUI() {
|
||||
qDebug("GUI destruction");
|
||||
hide();
|
||||
#ifdef Q_WS_MAC
|
||||
// Workaround to avoid bug http://bugreports.qt.nokia.com/browse/QTBUG-7305
|
||||
setUnifiedTitleAndToolBarOnMac(false);
|
||||
#endif
|
||||
// Async deletion of Bittorrent session as early as possible
|
||||
// in order to speed up exit
|
||||
session_proxy sp;
|
||||
if(BTSession)
|
||||
sp = BTSession->asyncDeletion();
|
||||
session_proxy sp = BTSession->asyncDeletion();
|
||||
// Some saving
|
||||
properties->saveSettings();
|
||||
disconnect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tab_changed(int)));
|
||||
// Delete other GUI objects
|
||||
if(executable_watcher)
|
||||
delete executable_watcher;
|
||||
delete status_bar;
|
||||
delete search_filter;
|
||||
delete transferList;
|
||||
delete guiUpdater;
|
||||
delete lockMenu;
|
||||
if(createTorrentDlg)
|
||||
delete createTorrentDlg;
|
||||
if(console)
|
||||
@@ -292,8 +245,7 @@ GUI::~GUI() {
|
||||
delete downloadFromURLDialog;
|
||||
if(rssWidget)
|
||||
delete rssWidget;
|
||||
if(searchEngine)
|
||||
delete searchEngine;
|
||||
delete searchEngine;
|
||||
delete transferListFilters;
|
||||
delete properties;
|
||||
delete hSplitter;
|
||||
@@ -303,10 +255,10 @@ GUI::~GUI() {
|
||||
}
|
||||
if(systrayIcon) {
|
||||
delete systrayIcon;
|
||||
}
|
||||
if(myTrayIconMenu) {
|
||||
delete myTrayIconMenu;
|
||||
}
|
||||
localServer->close();
|
||||
delete localServer;
|
||||
delete tabs;
|
||||
// Keyboard shortcuts
|
||||
delete switchSearchShortcut;
|
||||
@@ -314,8 +266,13 @@ GUI::~GUI() {
|
||||
delete switchTransferShortcut;
|
||||
delete switchRSSShortcut;
|
||||
// Delete BTSession objects
|
||||
qDebug("Deleting BTSession");
|
||||
delete BTSession;
|
||||
// Deleting remaining top level widgets
|
||||
qDebug("Deleting remaining top level widgets");
|
||||
foreach (QWidget *win, QApplication::topLevelWidgets()) {
|
||||
if(win && win != this)
|
||||
delete win;
|
||||
}
|
||||
// May freeze for a few seconds after the next line
|
||||
// because the Bittorrent session proxy will
|
||||
// actually be deleted now and destruction
|
||||
@@ -323,35 +280,6 @@ GUI::~GUI() {
|
||||
qDebug("Exiting GUI destructor...");
|
||||
}
|
||||
|
||||
void GUI::defineUILockPassword() {
|
||||
QString old_pass_md5 = Preferences::getUILockPasswordMD5();
|
||||
if(old_pass_md5.isNull()) old_pass_md5 = "";
|
||||
bool ok = false;
|
||||
QString new_clear_password = QInputDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, old_pass_md5, &ok);
|
||||
if(ok) {
|
||||
if(new_clear_password != old_pass_md5) {
|
||||
Preferences::setUILockPassword(new_clear_password);
|
||||
}
|
||||
QMessageBox::information(this, tr("Password update"), tr("The UI lock password has been successfully updated"));
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::on_actionLock_qBittorrent_triggered() {
|
||||
// Check if there is a password
|
||||
if(Preferences::getUILockPasswordMD5().isEmpty()) {
|
||||
// Ask for a password
|
||||
bool ok = false;
|
||||
QString clear_password = QInputDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok);
|
||||
if(!ok) return;
|
||||
Preferences::setUILockPassword(clear_password);
|
||||
}
|
||||
// Lock the interface
|
||||
ui_locked = true;
|
||||
Preferences::setUILocked(true);
|
||||
myTrayIconMenu->setEnabled(false);
|
||||
hide();
|
||||
}
|
||||
|
||||
void GUI::displayRSSTab(bool enable) {
|
||||
if(enable) {
|
||||
// RSS tab
|
||||
@@ -360,40 +288,13 @@ void GUI::displayRSSTab(bool enable) {
|
||||
int index_tab = tabs->addTab(rssWidget, tr("RSS"));
|
||||
tabs->setTabIcon(index_tab, QIcon(QString::fromUtf8(":/Icons/rss32.png")));
|
||||
}
|
||||
tabs->showTabBar(true);
|
||||
} else {
|
||||
if(rssWidget) {
|
||||
delete rssWidget;
|
||||
}
|
||||
if(!searchEngine)
|
||||
tabs->showTabBar(false);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::displaySearchTab(bool enable) {
|
||||
if(enable) {
|
||||
// RSS tab
|
||||
if(!searchEngine) {
|
||||
searchEngine = new SearchEngine(this, BTSession);
|
||||
tabs->insertTab(1, searchEngine, QIcon(QString::fromUtf8(":/Icons/oxygen/edit-find.png")), tr("Search"));
|
||||
}
|
||||
tabs->showTabBar(true);
|
||||
} else {
|
||||
if(searchEngine) {
|
||||
delete searchEngine;
|
||||
}
|
||||
if(!rssWidget)
|
||||
tabs->showTabBar(false);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::updateNbTorrents(unsigned int nb_downloading, unsigned int nb_seeding, unsigned int nb_active, unsigned int nb_inactive, unsigned int nb_paused) {
|
||||
Q_UNUSED(nb_downloading);
|
||||
Q_UNUSED(nb_seeding);
|
||||
Q_UNUSED(nb_paused);
|
||||
tabs->setTabText(0, tr("Transfers (%1)").arg(QString::number(nb_inactive+nb_active)));
|
||||
}
|
||||
|
||||
void GUI::on_actionWebsite_triggered() const {
|
||||
QDesktopServices::openUrl(QUrl(QString::fromUtf8("http://www.qbittorrent.org")));
|
||||
}
|
||||
@@ -407,25 +308,18 @@ void GUI::on_actionBugReport_triggered() const {
|
||||
}
|
||||
|
||||
void GUI::tab_changed(int new_tab) {
|
||||
Q_UNUSED(new_tab);
|
||||
// We cannot rely on the index new_tab
|
||||
// because the tab order is undetermined now
|
||||
if(tabs->currentWidget() == vSplitter) {
|
||||
if(new_tab == TAB_TRANSFER) {
|
||||
qDebug("Changed tab to transfer list, refreshing the list");
|
||||
transferList->refreshList();
|
||||
properties->loadDynamicData();
|
||||
return;
|
||||
}
|
||||
if(tabs->currentWidget() == searchEngine) {
|
||||
qDebug("Changed tab to search engine, giving focus to search input");
|
||||
searchEngine->giveFocusToSearchInput();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::writeSettings() {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
settings.beginGroup(QString::fromUtf8("MainWindow"));
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue(QString::fromUtf8("size"), size());
|
||||
settings.setValue(QString::fromUtf8("pos"), pos());
|
||||
// Splitter size
|
||||
QStringList sizes_str;
|
||||
sizes_str << QString::number(vSplitter->sizes().first());
|
||||
@@ -471,26 +365,25 @@ void GUI::createKeyboardShortcuts() {
|
||||
|
||||
// Keyboard shortcuts slots
|
||||
void GUI::displayTransferTab() const {
|
||||
tabs->setCurrentWidget(transferList);
|
||||
tabs->setCurrentIndex(TAB_TRANSFER);
|
||||
}
|
||||
|
||||
void GUI::displaySearchTab() const {
|
||||
if(searchEngine)
|
||||
tabs->setCurrentWidget(searchEngine);
|
||||
tabs->setCurrentIndex(TAB_SEARCH);
|
||||
}
|
||||
|
||||
void GUI::displayRSSTab() const {
|
||||
if(rssWidget)
|
||||
tabs->setCurrentWidget(rssWidget);
|
||||
tabs->setCurrentIndex(TAB_RSS);
|
||||
}
|
||||
|
||||
// End of keyboard shortcuts slots
|
||||
|
||||
void GUI::readSettings() {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
settings.beginGroup(QString::fromUtf8("MainWindow"));
|
||||
restoreGeometry(settings.value("geometry").toByteArray());
|
||||
const QStringList sizes_str = settings.value("vSplitterSizes", QStringList()).toStringList();
|
||||
resize(settings.value(QString::fromUtf8("size"), size()).toSize());
|
||||
move(settings.value(QString::fromUtf8("pos"), misc::screenCenter(this)).toPoint());
|
||||
const QStringList &sizes_str = settings.value("vSplitterSizes", QStringList()).toStringList();
|
||||
// Splitter size
|
||||
QList<int> sizes;
|
||||
if(sizes_str.size() == 2) {
|
||||
@@ -516,22 +409,29 @@ void GUI::balloonClicked() {
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::acceptConnection() {
|
||||
QLocalSocket *clientConnection = localServer->nextPendingConnection();
|
||||
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(readParamsOnSocket()));
|
||||
qDebug("accepted connection from another instance");
|
||||
}
|
||||
|
||||
void GUI::readParamsOnSocket() {
|
||||
QLocalSocket *clientConnection = static_cast<QLocalSocket*>(sender());
|
||||
if(clientConnection) {
|
||||
const QByteArray ¶ms = clientConnection->readAll();
|
||||
if(!params.isEmpty()) {
|
||||
processParams(QString::fromLocal8Bit(params.constData()).split("\n"));
|
||||
qDebug("Received parameters from another instance");
|
||||
}
|
||||
clientConnection->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::askRecursiveTorrentDownloadConfirmation(QTorrentHandle &h) {
|
||||
if(Preferences::recursiveDownloadDisabled()) return;
|
||||
QMessageBox confirmBox(QMessageBox::Question, tr("Recursive download confirmation"), tr("The torrent %1 contains torrent files, do you want to proceed with their download?").arg(h.name()));
|
||||
QPushButton *yes = confirmBox.addButton(tr("Yes"), QMessageBox::YesRole);
|
||||
/*QPushButton *no = */confirmBox.addButton(tr("No"), QMessageBox::NoRole);
|
||||
QPushButton *never = confirmBox.addButton(tr("Never"), QMessageBox::NoRole);
|
||||
confirmBox.exec();
|
||||
if(confirmBox.clickedButton() == 0) return;
|
||||
if(confirmBox.clickedButton() == yes) {
|
||||
BTSession->recursiveTorrentDownload(h);
|
||||
return;
|
||||
}
|
||||
if(confirmBox.clickedButton() == never) {
|
||||
Preferences::disableRecursiveDownload();
|
||||
}
|
||||
}
|
||||
if(QMessageBox::question(this, tr("Recursive download confirmation"), tr("The torrent %1 contains torrent files, do you want to proceed with their download?").arg(h.name()), QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) {
|
||||
BTSession->recursiveTorrentDownload(h);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::handleDownloadFromUrlFailure(QString url, QString reason) const{
|
||||
// Display a message box
|
||||
@@ -581,53 +481,20 @@ void GUI::on_actionExit_triggered() {
|
||||
close();
|
||||
}
|
||||
|
||||
QWidget* GUI::getCurrentTabWidget() const {
|
||||
int GUI::getCurrentTabIndex() const {
|
||||
if(isMinimized() || !isVisible())
|
||||
return 0;
|
||||
if(tabs->currentIndex() == 0)
|
||||
return transferList;
|
||||
return tabs->currentWidget();
|
||||
return -1;
|
||||
return tabs->currentIndex();
|
||||
}
|
||||
|
||||
void GUI::setTabText(int index, QString text) const {
|
||||
tabs->setTabText(index, text);
|
||||
}
|
||||
|
||||
bool GUI::unlockUI() {
|
||||
bool ok = false;
|
||||
QString clear_password = QInputDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok);
|
||||
if(!ok) return false;
|
||||
QString real_pass_md5 = Preferences::getUILockPasswordMD5();
|
||||
QCryptographicHash md5(QCryptographicHash::Md5);
|
||||
md5.addData(clear_password.toLocal8Bit());
|
||||
QString password_md5 = md5.result().toHex();
|
||||
if(real_pass_md5 == password_md5) {
|
||||
ui_locked = false;
|
||||
Preferences::setUILocked(false);
|
||||
myTrayIconMenu->setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
QMessageBox::warning(this, tr("Invalid password"), tr("The password is invalid"));
|
||||
return false;
|
||||
}
|
||||
|
||||
void GUI::notifyOfUpdate(QString) {
|
||||
// Show restart message
|
||||
status_bar->showRestartRequired();
|
||||
// Delete the executable watcher
|
||||
delete executable_watcher;
|
||||
executable_watcher = 0;
|
||||
}
|
||||
|
||||
// Toggle Main window visibility
|
||||
void GUI::toggleVisibility(QSystemTrayIcon::ActivationReason e) {
|
||||
if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) {
|
||||
if(isHidden()) {
|
||||
if(ui_locked) {
|
||||
// Ask for UI lock password
|
||||
if(!unlockUI())
|
||||
return;
|
||||
}
|
||||
show();
|
||||
if(isMinimized()) {
|
||||
if(isMaximized()) {
|
||||
@@ -656,7 +523,7 @@ void GUI::on_actionAbout_triggered() {
|
||||
|
||||
void GUI::showEvent(QShowEvent *e) {
|
||||
qDebug("** Show Event **");
|
||||
if(getCurrentTabWidget() == transferList) {
|
||||
if(getCurrentTabIndex() == TAB_TRANSFER) {
|
||||
qDebug("-> Refreshing transfer list");
|
||||
transferList->refreshList();
|
||||
properties->loadDynamicData();
|
||||
@@ -666,35 +533,28 @@ void GUI::showEvent(QShowEvent *e) {
|
||||
|
||||
// Called when we close the program
|
||||
void GUI::closeEvent(QCloseEvent *e) {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
const bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool();
|
||||
if(!force_exit && systrayIcon && goToSystrayOnExit && !this->isHidden()) {
|
||||
hide();
|
||||
//e->ignore();
|
||||
e->accept();
|
||||
return;
|
||||
}
|
||||
if(settings.value(QString::fromUtf8("Preferences/General/ExitConfirm"), true).toBool() && BTSession && BTSession->hasActiveTorrents()) {
|
||||
if(settings.value(QString::fromUtf8("Preferences/General/ExitConfirm"), true).toBool() && BTSession->hasActiveTorrents()) {
|
||||
show();
|
||||
if(!isMaximized())
|
||||
showNormal();
|
||||
if(e->spontaneous() || force_exit) {
|
||||
if(!isVisible())
|
||||
show();
|
||||
QMessageBox confirmBox(QMessageBox::Question, tr("Exiting qBittorrent"),
|
||||
tr("Some files are currently transferring.\nAre you sure you want to quit qBittorrent?"),
|
||||
QMessageBox::NoButton, this);
|
||||
QPushButton *noBtn = confirmBox.addButton(tr("No"), QMessageBox::NoRole);
|
||||
QPushButton *yesBtn = confirmBox.addButton(tr("Yes"), QMessageBox::YesRole);
|
||||
QPushButton *alwaysBtn = confirmBox.addButton(tr("Always"), QMessageBox::YesRole);
|
||||
confirmBox.setDefaultButton(yesBtn);
|
||||
confirmBox.exec();
|
||||
if(!confirmBox.clickedButton() || confirmBox.clickedButton() == noBtn) {
|
||||
// Cancel exit
|
||||
if(QMessageBox::question(this,
|
||||
tr("Are you sure you want to quit?")+QString::fromUtf8(" -- ")+tr("qBittorrent"),
|
||||
tr("Some files are currently transferring.\nAre you sure you want to quit qBittorrent?"),
|
||||
tr("&Yes"), tr("&No"),
|
||||
QString(), 0, 1)) {
|
||||
e->ignore();
|
||||
force_exit = false;
|
||||
return;
|
||||
}
|
||||
if(confirmBox.clickedButton() == alwaysBtn) {
|
||||
// Remember choice
|
||||
Preferences::setConfirmOnExit(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
hide();
|
||||
@@ -709,6 +569,7 @@ void GUI::closeEvent(QCloseEvent *e) {
|
||||
qApp->exit();
|
||||
}
|
||||
|
||||
|
||||
// Display window to create a torrent
|
||||
void GUI::on_actionCreate_torrent_triggered() {
|
||||
if(createTorrentDlg) {
|
||||
@@ -720,47 +581,15 @@ void GUI::on_actionCreate_torrent_triggered() {
|
||||
}
|
||||
|
||||
bool GUI::event(QEvent * e) {
|
||||
switch(e->type()) {
|
||||
case QEvent::WindowStateChange: {
|
||||
qDebug("Window change event");
|
||||
//Now check to see if the window is minimised
|
||||
if(isMinimized()) {
|
||||
qDebug("minimisation");
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
if(systrayIcon && settings.value(QString::fromUtf8("Preferences/General/MinimizeToTray"), false).toBool()) {
|
||||
qDebug("Has active window: %d", (int)(qApp->activeWindow() != 0));
|
||||
// Check if there is a modal window
|
||||
bool has_modal_window = false;
|
||||
foreach (QWidget *widget, QApplication::allWidgets()) {
|
||||
if(widget->isModal()) {
|
||||
has_modal_window = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Iconify if there is no modal window
|
||||
if(!has_modal_window) {
|
||||
qDebug("Minimize to Tray enabled, hiding!");
|
||||
e->accept();
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(e->type() == QEvent::WindowStateChange) {
|
||||
//Now check to see if the window is minimised
|
||||
if(isMinimized()) {
|
||||
qDebug("minimisation");
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
if(systrayIcon && settings.value(QString::fromUtf8("Preferences/General/MinimizeToTray"), false).toBool()) {
|
||||
hide();
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef Q_WS_MAC
|
||||
case QEvent::ToolBarChange: {
|
||||
qDebug("MAC: Received a toolbar change event!");
|
||||
bool ret = QMainWindow::event(e);
|
||||
|
||||
qDebug("MAC: new toolbar visibility is %d", !actionTop_tool_bar->isChecked());
|
||||
actionTop_tool_bar->toggle();
|
||||
Preferences::setToolbarDisplayed(actionTop_tool_bar->isChecked());
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QMainWindow::event(e);
|
||||
}
|
||||
@@ -770,7 +599,7 @@ void GUI::dropEvent(QDropEvent *event) {
|
||||
event->acceptProposedAction();
|
||||
QStringList files;
|
||||
if(event->mimeData()->hasUrls()) {
|
||||
const QList<QUrl> urls = event->mimeData()->urls();
|
||||
const QList<QUrl> &urls = event->mimeData()->urls();
|
||||
foreach(const QUrl &url, urls) {
|
||||
const QString tmp = url.toString().trimmed();
|
||||
if(!tmp.isEmpty())
|
||||
@@ -780,23 +609,15 @@ void GUI::dropEvent(QDropEvent *event) {
|
||||
files = event->mimeData()->text().split(QString::fromUtf8("\n"));
|
||||
}
|
||||
// Add file to download list
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
foreach(QString file, files) {
|
||||
#ifdef Q_WS_WIN
|
||||
file = file.trimmed().replace(QString::fromUtf8("file:///"), QString::fromUtf8(""), Qt::CaseInsensitive);
|
||||
#else
|
||||
file = file.trimmed().replace(QString::fromUtf8("file://"), QString::fromUtf8(""), Qt::CaseInsensitive);
|
||||
#endif
|
||||
qDebug("Dropped file %s on download list", file.toLocal8Bit().data());
|
||||
if(file.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
BTSession->downloadFromUrl(file);
|
||||
continue;
|
||||
}
|
||||
if(file.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
file = misc::bcLinkToMagnet(file);
|
||||
}
|
||||
if(file.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
// FIXME: Possibly skipped torrent addition dialog
|
||||
BTSession->addMagnetUri(file);
|
||||
@@ -830,12 +651,12 @@ void GUI::dragEnterEvent(QDragEnterEvent *event) {
|
||||
// Display a dialog to allow user to add
|
||||
// torrents to download list
|
||||
void GUI::on_actionOpen_triggered() {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
// Open File Open Dialog
|
||||
// Note: it is possible to select more than one file
|
||||
const QStringList pathsList = QFileDialog::getOpenFileNames(0,
|
||||
tr("Open Torrent Files"), settings.value(QString::fromUtf8("MainWindowLastDir"), QDir::homePath()).toString(),
|
||||
tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
|
||||
const QStringList &pathsList = QFileDialog::getOpenFileNames(0,
|
||||
tr("Open Torrent Files"), settings.value(QString::fromUtf8("MainWindowLastDir"), QDir::homePath()).toString(),
|
||||
tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
|
||||
if(!pathsList.empty()) {
|
||||
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
const uint listSize = pathsList.size();
|
||||
@@ -858,22 +679,15 @@ void GUI::on_actionOpen_triggered() {
|
||||
// This function parse the parameters and call
|
||||
// the right addTorrent function, considering
|
||||
// the parameter type.
|
||||
void GUI::processParams(const QString& params_str) {
|
||||
processParams(params_str.split("|", QString::SkipEmptyParts));
|
||||
}
|
||||
|
||||
void GUI::processParams(const QStringList& params) {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
foreach(QString param, params) {
|
||||
param = param.trimmed();
|
||||
if(param.startsWith("--")) continue;
|
||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
BTSession->downloadFromUrl(param);
|
||||
}else{
|
||||
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
param = misc::bcLinkToMagnet(param);
|
||||
}
|
||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
if(useTorrentAdditionDialog) {
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
|
||||
@@ -898,7 +712,7 @@ void GUI::addTorrent(QString path) {
|
||||
}
|
||||
|
||||
void GUI::processDownloadedFiles(QString path, QString url) {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
if(useTorrentAdditionDialog) {
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
|
||||
@@ -915,9 +729,7 @@ void GUI::optionsSaved() {
|
||||
// Load program preferences
|
||||
void GUI::loadPreferences(bool configure_session) {
|
||||
BTSession->addConsoleMessage(tr("Options were saved successfully."));
|
||||
#ifndef Q_WS_MAC
|
||||
const bool newSystrayIntegration = Preferences::systrayIntegration();
|
||||
actionLock_qBittorrent->setEnabled(newSystrayIntegration);
|
||||
if(newSystrayIntegration != (systrayIcon!=0)) {
|
||||
if(newSystrayIntegration) {
|
||||
// create the trayicon
|
||||
@@ -940,14 +752,17 @@ void GUI::loadPreferences(bool configure_session) {
|
||||
delete myTrayIconMenu;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// General
|
||||
const bool new_displaySpeedInTitle = Preferences::speedInTitleBar();
|
||||
if(!new_displaySpeedInTitle && new_displaySpeedInTitle != displaySpeedInTitle) {
|
||||
// Reset title
|
||||
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent vx.x").arg(QString::fromUtf8(VERSION)));
|
||||
}
|
||||
displaySpeedInTitle = new_displaySpeedInTitle;
|
||||
if(Preferences::isToolbarDisplayed()) {
|
||||
toolBar->setVisible(true);
|
||||
toolBar->layout()->setSpacing(7);
|
||||
} else {
|
||||
// Clear search filter before hiding the top toolbar
|
||||
search_filter->clear();
|
||||
toolBar->setVisible(false);
|
||||
}
|
||||
const uint new_refreshInterval = Preferences::getRefreshInterval();
|
||||
@@ -958,7 +773,7 @@ void GUI::loadPreferences(bool configure_session) {
|
||||
properties->getPeerList()->setAlternatingRowColors(Preferences::useAlternatingRowColors());
|
||||
// Queueing System
|
||||
if(Preferences::isQueueingSystemEnabled()) {
|
||||
if(!actionDecreasePriority->isVisible()) {
|
||||
if(!configure_session || !BTSession->isQueueingEnabled()) {
|
||||
transferList->hidePriorityColumn(false);
|
||||
actionDecreasePriority->setVisible(true);
|
||||
actionIncreasePriority->setVisible(true);
|
||||
@@ -967,7 +782,7 @@ void GUI::loadPreferences(bool configure_session) {
|
||||
toolBar->layout()->setSpacing(7);
|
||||
}
|
||||
} else {
|
||||
if(actionDecreasePriority->isVisible()) {
|
||||
if(BTSession->isQueueingEnabled()) {
|
||||
transferList->hidePriorityColumn(true);
|
||||
actionDecreasePriority->setVisible(false);
|
||||
actionIncreasePriority->setVisible(false);
|
||||
@@ -977,6 +792,14 @@ void GUI::loadPreferences(bool configure_session) {
|
||||
}
|
||||
}
|
||||
|
||||
// RSS
|
||||
if(Preferences::isRSSEnabled()) {
|
||||
displayRSSTab(true);
|
||||
rssWidget->updateRefreshInterval(Preferences::getRSSRefreshInterval());
|
||||
} else {
|
||||
displayRSSTab(false);
|
||||
}
|
||||
|
||||
// Torrent properties
|
||||
properties->reloadPreferences();
|
||||
|
||||
@@ -1004,9 +827,8 @@ void GUI::trackerAuthenticationRequired(QTorrentHandle& h) {
|
||||
// Check connection status and display right icon
|
||||
void GUI::updateGUI() {
|
||||
// update global informations
|
||||
#ifndef Q_WS_MAC
|
||||
if(systrayIcon) {
|
||||
#if defined(Q_WS_X11)
|
||||
#if defined(Q_WS_X11) || defined(Q_WS_MAC)
|
||||
QString html = "<div style='background-color: #678db2; color: #fff;height: 18px; font-weight: bold; margin-bottom: 5px;'>";
|
||||
html += tr("qBittorrent");
|
||||
html += "</div>";
|
||||
@@ -1024,35 +846,29 @@ void GUI::updateGUI() {
|
||||
#endif
|
||||
systrayIcon->setToolTip(html); // tray icon
|
||||
}
|
||||
#endif
|
||||
if(displaySpeedInTitle) {
|
||||
setWindowTitle(tr("qBittorrent %1 (Down: %2/s, Up: %3/s)", "%1 is qBittorrent version").arg(QString::fromUtf8(VERSION)).arg(misc::friendlyUnit(BTSession->getSessionStatus().payload_download_rate)).arg(misc::friendlyUnit(BTSession->getSessionStatus().payload_upload_rate)));
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::showNotificationBaloon(QString title, QString msg) const {
|
||||
if(!Preferences::useProgramNotification()) return;
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
if(settings.value(QString::fromUtf8("Preferences/General/NotificationBaloons"), true).toBool()) {
|
||||
#ifdef WITH_LIBNOTIFY
|
||||
if (notify_init ("summary-body")) {
|
||||
NotifyNotification* notification;
|
||||
|
||||
notification = notify_notification_new (qPrintable(title), qPrintable(msg), "qbittorrent"
|
||||
#if !defined(NOTIFY_VERSION_MINOR) || (NOTIFY_VERSION_MAJOR == 0 && NOTIFY_VERSION_MINOR < 7)
|
||||
, 0
|
||||
#endif
|
||||
);
|
||||
gboolean success = notify_notification_show (notification, NULL);
|
||||
g_object_unref(G_OBJECT(notification));
|
||||
notify_uninit ();
|
||||
if(success) {
|
||||
return;
|
||||
if (notify_init ("summary-body")) {
|
||||
NotifyNotification* notification;
|
||||
notification = notify_notification_new (qPrintable(title), qPrintable(msg), "qbittorrent", 0);
|
||||
gboolean success = notify_notification_show (notification, NULL);
|
||||
g_object_unref(G_OBJECT(notification));
|
||||
notify_uninit ();
|
||||
if(success) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(systrayIcon)
|
||||
systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON);
|
||||
}
|
||||
#endif
|
||||
#ifndef Q_WS_MAC
|
||||
if(systrayIcon && QSystemTrayIcon::supportsMessages())
|
||||
systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
@@ -1062,13 +878,9 @@ void GUI::showNotificationBaloon(QString title, QString msg) const {
|
||||
*****************************************************/
|
||||
|
||||
void GUI::downloadFromURLList(const QStringList& url_list) {
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
foreach(QString url, url_list) {
|
||||
if(url.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
url = misc::bcLinkToMagnet(url);
|
||||
}
|
||||
foreach(const QString& url, url_list) {
|
||||
if(url.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
if(useTorrentAdditionDialog) {
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
|
||||
@@ -1089,7 +901,6 @@ void GUI::downloadFromURLList(const QStringList& url_list) {
|
||||
*****************************************************/
|
||||
|
||||
void GUI::createSystrayDelayed() {
|
||||
#ifndef Q_WS_MAC
|
||||
static int timeout = 20;
|
||||
if(QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
// Ok, systray integration is now supported
|
||||
@@ -1110,23 +921,32 @@ void GUI::createSystrayDelayed() {
|
||||
Preferences::setSystrayIntegration(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GUI::updateAltSpeedsBtn(bool alternative) {
|
||||
actionUse_alternative_speed_limits->setChecked(alternative);
|
||||
if(alternative) {
|
||||
actionUse_alternative_speed_limits->setIcon(QIcon(":/Icons/slow.png"));
|
||||
actionUse_alternative_speed_limits->setText(tr("Use normal speed limits"));
|
||||
} else {
|
||||
actionUse_alternative_speed_limits->setIcon(QIcon(":/Icons/slow_off.png"));
|
||||
actionUse_alternative_speed_limits->setText(tr("Use alternative speed limits"));
|
||||
}
|
||||
}
|
||||
|
||||
QMenu* GUI::getTrayIconMenu() {
|
||||
if(myTrayIconMenu)
|
||||
return myTrayIconMenu;
|
||||
void GUI::createTrayIcon() {
|
||||
// Tray icon
|
||||
#ifdef Q_WS_WIN
|
||||
systrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent16.png")), this);
|
||||
#endif
|
||||
#ifndef Q_WS_WIN
|
||||
systrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")), this);
|
||||
#endif
|
||||
// Tray icon Menu
|
||||
myTrayIconMenu = new QMenu(this);
|
||||
myTrayIconMenu->addAction(actionOpen);
|
||||
myTrayIconMenu->addAction(actionDownload_from_URL);
|
||||
myTrayIconMenu->addSeparator();
|
||||
updateAltSpeedsBtn(Preferences::isAltBandwidthEnabled());
|
||||
actionUse_alternative_speed_limits->setChecked(Preferences::isAltBandwidthEnabled());
|
||||
myTrayIconMenu->addAction(actionUse_alternative_speed_limits);
|
||||
myTrayIconMenu->addAction(actionSet_global_download_limit);
|
||||
myTrayIconMenu->addAction(actionSet_global_upload_limit);
|
||||
@@ -1135,20 +955,7 @@ QMenu* GUI::getTrayIconMenu() {
|
||||
myTrayIconMenu->addAction(actionPause_All);
|
||||
myTrayIconMenu->addSeparator();
|
||||
myTrayIconMenu->addAction(actionExit);
|
||||
if(ui_locked)
|
||||
myTrayIconMenu->setEnabled(false);
|
||||
return myTrayIconMenu;
|
||||
}
|
||||
|
||||
void GUI::createTrayIcon() {
|
||||
// Tray icon
|
||||
#ifdef Q_WS_WIN
|
||||
systrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent16.png")), this);
|
||||
#else
|
||||
systrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")), this);
|
||||
#endif
|
||||
|
||||
systrayIcon->setContextMenu(getTrayIconMenu());
|
||||
systrayIcon->setContextMenu(myTrayIconMenu);
|
||||
connect(systrayIcon, SIGNAL(messageClicked()), this, SLOT(balloonClicked()));
|
||||
// End of Icon Menu
|
||||
connect(systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
|
||||
@@ -1166,36 +973,6 @@ void GUI::on_actionOptions_triggered() {
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::on_actionTop_tool_bar_triggered() {
|
||||
bool is_visible = static_cast<QAction*>(sender())->isChecked();
|
||||
toolBar->setVisible(is_visible);
|
||||
Preferences::setToolbarDisplayed(is_visible);
|
||||
}
|
||||
|
||||
void GUI::on_actionShutdown_when_downloads_complete_triggered() {
|
||||
bool is_checked = static_cast<QAction*>(sender())->isChecked();
|
||||
Preferences::setShutdownWhenDownloadsComplete(is_checked);
|
||||
}
|
||||
|
||||
void GUI::on_actionSpeed_in_title_bar_triggered() {
|
||||
displaySpeedInTitle = static_cast<QAction*>(sender())->isChecked();
|
||||
Preferences::showSpeedInTitleBar(displaySpeedInTitle);
|
||||
if(displaySpeedInTitle)
|
||||
updateGUI();
|
||||
else
|
||||
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION)));
|
||||
}
|
||||
|
||||
void GUI::on_actionRSS_Reader_triggered() {
|
||||
Preferences::setRSSEnabled(actionRSS_Reader->isChecked());
|
||||
displayRSSTab(actionRSS_Reader->isChecked());
|
||||
}
|
||||
|
||||
void GUI::on_actionSearch_engine_triggered() {
|
||||
Preferences::setSearchEnabled(actionSearch_engine->isChecked());
|
||||
displaySearchTab(actionSearch_engine->isChecked());
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* HTTP Downloader *
|
||||
@@ -1211,8 +988,3 @@ void GUI::on_actionDownload_from_URL_triggered() {
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::on_actionDonate_money_triggered()
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("http://sourceforge.net/donate/index.php?group_id=163414"));
|
||||
}
|
||||
|
||||
|
||||
40
src/GUI.h
@@ -37,10 +37,13 @@
|
||||
#include "ui_mainwindow.h"
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
enum TabIndex{TAB_TRANSFER, TAB_SEARCH, TAB_RSS};
|
||||
|
||||
class Bittorrent;
|
||||
class QTimer;
|
||||
class downloadFromURL;
|
||||
class SearchEngine;
|
||||
class QLocalServer;
|
||||
class QCloseEvent;
|
||||
class RSSImp;
|
||||
class QShortcut;
|
||||
@@ -56,9 +59,6 @@ class consoleDlg;
|
||||
class about;
|
||||
class createtorrent;
|
||||
class downloadFromURL;
|
||||
class HidableTabWidget;
|
||||
class LineEdit;
|
||||
class QFileSystemWatcher;
|
||||
|
||||
class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
Q_OBJECT
|
||||
@@ -68,10 +68,8 @@ public:
|
||||
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
|
||||
~GUI();
|
||||
// Methods
|
||||
QWidget* getCurrentTabWidget() const;
|
||||
int getCurrentTabIndex() const;
|
||||
TransferListWidget* getTransferList() const { return transferList; }
|
||||
QMenu* getTrayIconMenu();
|
||||
PropertiesWidget *getProperties() const { return properties; }
|
||||
|
||||
public slots:
|
||||
void trackerAuthenticationRequired(QTorrentHandle& h);
|
||||
@@ -79,8 +77,6 @@ public slots:
|
||||
void showNotificationBaloon(QString title, QString msg) const;
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
void updateAltSpeedsBtn(bool alternative);
|
||||
void updateNbTorrents(unsigned int nb_downloading, unsigned int nb_seeding, unsigned int nb_active, unsigned int nb_inactive, unsigned int nb_paused);
|
||||
void deleteBTSession();
|
||||
|
||||
protected slots:
|
||||
// GUI related slots
|
||||
@@ -92,6 +88,8 @@ protected slots:
|
||||
void on_actionWebsite_triggered() const;
|
||||
void on_actionBugReport_triggered() const;
|
||||
void on_actionShow_console_triggered();
|
||||
void readParamsOnSocket();
|
||||
void acceptConnection();
|
||||
void balloonClicked();
|
||||
void writeSettings();
|
||||
void readSettings();
|
||||
@@ -101,10 +99,6 @@ protected slots:
|
||||
void handleDownloadFromUrlFailure(QString, QString) const;
|
||||
void createSystrayDelayed();
|
||||
void tab_changed(int);
|
||||
void on_actionLock_qBittorrent_triggered();
|
||||
void defineUILockPassword();
|
||||
bool unlockUI();
|
||||
void notifyOfUpdate(QString);
|
||||
// Keyboard shortcuts
|
||||
void createKeyboardShortcuts();
|
||||
void displayTransferTab() const;
|
||||
@@ -117,7 +111,6 @@ protected slots:
|
||||
void on_actionOpen_triggered();
|
||||
void updateGUI();
|
||||
void loadPreferences(bool configure_session=true);
|
||||
void processParams(const QString& params);
|
||||
void processParams(const QStringList& params);
|
||||
void addTorrent(QString path);
|
||||
void addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker);
|
||||
@@ -135,16 +128,14 @@ protected:
|
||||
void showEvent(QShowEvent *);
|
||||
bool event(QEvent * event);
|
||||
void displayRSSTab(bool enable);
|
||||
void displaySearchTab(bool enable);
|
||||
|
||||
private:
|
||||
QFileSystemWatcher *executable_watcher;
|
||||
// Bittorrent
|
||||
Bittorrent *BTSession;
|
||||
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; // Still needed?
|
||||
// GUI related
|
||||
QTimer *guiUpdater;
|
||||
HidableTabWidget *tabs;
|
||||
QTabWidget *tabs;
|
||||
StatusBar *status_bar;
|
||||
QPointer<options_imp> options;
|
||||
QPointer<consoleDlg> console;
|
||||
@@ -153,14 +144,12 @@ private:
|
||||
QPointer<downloadFromURL> downloadFromURLDialog;
|
||||
QPointer<QSystemTrayIcon> systrayIcon;
|
||||
QPointer<QTimer> systrayCreator;
|
||||
QPointer<QMenu> myTrayIconMenu;
|
||||
QMenu *myTrayIconMenu;
|
||||
TransferListWidget *transferList;
|
||||
TransferListFiltersWidget *transferListFilters;
|
||||
PropertiesWidget *properties;
|
||||
bool displaySpeedInTitle;
|
||||
bool force_exit;
|
||||
bool ui_locked;
|
||||
LineEdit *search_filter;
|
||||
// Keyboard shortcuts
|
||||
QShortcut *switchSearchShortcut;
|
||||
QShortcut *switchSearchShortcut2;
|
||||
@@ -171,19 +160,12 @@ private:
|
||||
QAction *prioSeparator2;
|
||||
QSplitter *hSplitter;
|
||||
QSplitter *vSplitter;
|
||||
QMenu *lockMenu;
|
||||
// Search
|
||||
QPointer<SearchEngine> searchEngine;
|
||||
SearchEngine *searchEngine;
|
||||
// RSS
|
||||
QPointer<RSSImp> rssWidget;
|
||||
|
||||
private slots:
|
||||
void on_actionSearch_engine_triggered();
|
||||
void on_actionRSS_Reader_triggered();
|
||||
void on_actionSpeed_in_title_bar_triggered();
|
||||
void on_actionTop_tool_bar_triggered();
|
||||
void on_actionShutdown_when_downloads_complete_triggered();
|
||||
void on_actionDonate_money_triggered();
|
||||
// Misc
|
||||
QLocalServer *localServer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
Before Width: | Height: | Size: 322 B |
BIN
src/Icons/L.gif
|
Before Width: | Height: | Size: 66 B |
|
Before Width: | Height: | Size: 546 B |
BIN
src/Icons/locale.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 892 B |
|
Before Width: | Height: | Size: 996 B |
|
Before Width: | Height: | Size: 929 B |
BIN
src/Icons/oxygen/mail-queue.png
Normal file
|
After Width: | Height: | Size: 860 B |
BIN
src/Icons/oxygen/wallet.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,9 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Network;P2P;
|
||||
Comment=V2.4.10
|
||||
Comment=V2.2.3
|
||||
Exec=qbittorrent %f
|
||||
GenericName=Bittorrent client
|
||||
GenericName[ar]=العميل Bittorrent
|
||||
GenericName[bg]=Торент клиент
|
||||
GenericName[cs]=Bittorrent klient
|
||||
GenericName[de]=Bittorren Client
|
||||
@@ -11,7 +10,6 @@ GenericName[el]=Bittorrent πελάτης
|
||||
GenericName[es]=Cliente Bittorrent
|
||||
GenericName[fi]=Bittorrent-ohjelma
|
||||
GenericName[fr]=Client Bittorrent
|
||||
GenericName[hr]=Bittorrent klijent
|
||||
GenericName[hu]=Bittorrent kliens
|
||||
GenericName[it]=Client Bittorrent
|
||||
GenericName[ja]=Bittorrent クライアント
|
||||
|
||||
|
Before Width: | Height: | Size: 54 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
src/Icons/skin/checkingUP.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
src/Icons/skin/pausedUP.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/Icons/skin/properties.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
src/Icons/skin/queuedUP.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 79 KiB |
BIN
src/Icons/skin/stalled.png
Normal file
|
After Width: | Height: | Size: 315 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 910 B |
BIN
src/Icons/slow48.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 680 B |
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>torrent</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>qBitTorrentDocument</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>BitTorrent Document</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/x-bittorrent</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Owner</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>org.bittorrent.torrent</string>
|
||||
</array>
|
||||
<key>LSIsAppleDefaultForType</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>magnet</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>BitTorrent Magnet URL</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>qbittorrent_mac.icns</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>2.4.10</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>qbittorrent</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.qbittorrent</string>
|
||||
<key>NOTE</key>
|
||||
<string>This file was generated by Qt/QMake.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +0,0 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>gpl.html</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
437
src/about_imp.h
@@ -32,7 +32,7 @@
|
||||
#define ABOUT_H
|
||||
|
||||
#include "ui_about.h"
|
||||
#include <QFile>
|
||||
#include <QScrollBar>
|
||||
|
||||
class about : public QDialog, private Ui::AboutDlg{
|
||||
Q_OBJECT
|
||||
@@ -47,56 +47,403 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
// Set icons
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
|
||||
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/mascot.png")));
|
||||
//Title
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
// Thanks
|
||||
QString thanks_txt;
|
||||
thanks_txt += QString::fromUtf8("<p>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</p>");
|
||||
thanks_txt += QString::fromUtf8("<p>I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated</p>");
|
||||
thanks_txt += QString::fromUtf8("<p>I also want to thank Στέφανος Αντάρης (santaris@csd.auth.gr) and Mirco Chinelli (infinity89@fastwebmail.it) for working on Mac OS X packaging.</p>");
|
||||
thanks_txt += QString::fromUtf8("<p>I am grateful to Peter Koeleman (peter@qbittorrent.org) and Mohammad Dib (mdib@qbittorrent.org) for working on qBittorrent port to Windows.</p>");
|
||||
thanks_txt += QString::fromUtf8("<p>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</p>");
|
||||
te_thanks->setHtml(thanks_txt);
|
||||
te_thanks->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
te_thanks->append(QString::fromUtf8("<ul><li>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>I also want to thank Jeffery Fernandez (jeffery@qbittorrent.org), project consultant, for his help and support since the beginning of this project.</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>I am grateful to Peter Koeleman (peter@qbittorrent.org) for working on qBittorrent port to Windows.</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</li></ul><br><br>"));
|
||||
te_thanks->scrollToAnchor(QString::fromUtf8("top"));
|
||||
// Translation
|
||||
QString trans_txt = "<p>"+tr("I would like to thank the following people who volunteered to translate qBittorrent:")+"</p>";
|
||||
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)</li>\
|
||||
<li><u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Bulgarian:</u> Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)</li>\
|
||||
<li><u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||
<li><u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)</li>\
|
||||
<li><u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)</li>\
|
||||
<li><u>Croatian:</u> Oliver Mucafir (oliver.untwist@gmail.com)</li>\
|
||||
<li><u>Czech:</u> Jirka Vilim (web@tets.cz)</li>\
|
||||
<li><u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)</li>\
|
||||
<li><u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net) and Peter Koeleman (peter@peerweb.nl)</li>\
|
||||
<li><u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)</li>\
|
||||
<li><u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)</li>\
|
||||
<li><u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)</li>\
|
||||
<li><u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)</li>\
|
||||
<li><u>Italian:</u> Matteo Sechi (bu17714@gmail.com)</li>\
|
||||
<li><u>Japanese:</u> Nardog (alphisation@gmail.com)</li>\
|
||||
<li><u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)</li>\
|
||||
<li><u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)</li>\
|
||||
<li><u>Polish:</u> Mariusz Fik (fisiu@opensuse.org)</li>\
|
||||
<li><u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)</li>\
|
||||
<li><u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)</li>\
|
||||
<li><u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)</li>\
|
||||
<li><u>Slovak:</u> helix84</li>\
|
||||
<li><u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se)</li>\
|
||||
<li><u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)</li>\
|
||||
<li><u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)</li></ul>");
|
||||
trans_txt += "<p>"+tr("Please contact me if you would like to translate qBittorrent into your own language.")+"</p>";
|
||||
te_translation->setHtml(trans_txt);
|
||||
te_translation->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
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(
|
||||
"<i>- <u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
|
||||
- <u>Bulgarian:</u> Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)<br>\
|
||||
- <u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.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>Czech:</u> Jirka Vilim (web@tets.cz)<br>\
|
||||
- <u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)<br>\
|
||||
- <u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net) and Peter Koeleman (peter@peerweb.nl)<br>\
|
||||
- <u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)<br>\
|
||||
- <u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)<br>\
|
||||
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||
- <u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)<br>\
|
||||
- <u>Italian:</u> Mirko Ferrari (mirkoferrari@gmail.com) and Ferraro Luciano (luciano.ferraro@gmail.com)<br>\
|
||||
- <u>Japanese:</u> Nardog (alphisation@gmail.com)<br>\
|
||||
- <u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)<br>\
|
||||
- <u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)<br>\
|
||||
- <u>Polish:</u> Mariusz Fik (fisiu@opensuse.org)<br>\
|
||||
- <u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
|
||||
- <u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)<br>\
|
||||
- <u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)<br>\
|
||||
- <u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)<br>\
|
||||
- <u>Slovak:</u> helix84<br>\
|
||||
- <u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)<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>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)<br><br>"));
|
||||
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
|
||||
te_translation->scrollToAnchor(QString::fromUtf8("top"));
|
||||
// License
|
||||
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
QFile licensefile(":/gpl.html");
|
||||
if(licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||
te_license->setHtml(licensefile.readAll());
|
||||
licensefile.close();
|
||||
}
|
||||
show();
|
||||
#ifdef Q_WS_WIN
|
||||
te_license->append(QString::fromUtf8("qBittorrent is licensed under the GNU General Public License version 2."));
|
||||
#else
|
||||
te_license->append(QString::fromUtf8("qBittorrent is licensed under the GNU General Public License version 2 with the\
|
||||
addition of the following special exception:\
|
||||
<br><br>\
|
||||
<i>In addition, as a special exception, the copyright holders give permission to\
|
||||
link this program with the OpenSSL project\'s \"OpenSSL\" library (or with\
|
||||
modified versions of it that use the same license as the \"OpenSSL\" library),\
|
||||
and distribute the linked executables. You must obey the GNU General Public\
|
||||
License in all respects for all of the code used other than \"OpenSSL\". If you\
|
||||
modify file(s), you may extend this exception to your version of the file(s),\
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this\
|
||||
exception statement from your version.</i>\
|
||||
<br><br>\
|
||||
<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
|
||||
<center>Version 2, June 1991</center><br>\
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>\
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
|
||||
Everyone is permitted to copy and distribute verbatim copies<br>\
|
||||
of this license document, but changing it is not allowed.<br>\
|
||||
<br>\
|
||||
<center><b>Preamble</b></center><br>\
|
||||
The licenses for most software are designed to take away your<br>\
|
||||
freedom to share and change it. By contrast, the GNU General Public<br>\
|
||||
License is intended to guarantee your freedom to share and change free<br>\
|
||||
software--to make sure the software is free for all its users. This<br>\
|
||||
General Public License applies to most of the Free Software<br>\
|
||||
Foundation's software and to any other program whose authors commit to<br>\
|
||||
using it. (Some other Free Software Foundation software is covered by<br>\
|
||||
the GNU Library General Public License instead.) You can apply it to<br>\
|
||||
your programs, too.<br>\
|
||||
<br>\
|
||||
When we speak of free software, we are referring to freedom, not<br>\
|
||||
price. Our General Public Licenses are designed to make sure that you<br>\
|
||||
have the freedom to distribute copies of free software (and charge for<br>\
|
||||
this service if you wish), that you receive source code or can get it<br>\
|
||||
if you want it, that you can change the software or use pieces of it<br>\
|
||||
in new free programs; and that you know you can do these things.<br>\
|
||||
<br>\
|
||||
To protect your rights, we need to make restrictions that forbid<br>\
|
||||
anyone to deny you these rights or to ask you to surrender the rights.<br>\
|
||||
These restrictions translate to certain responsibilities for you if you<br>\
|
||||
distribute copies of the software, or if you modify it.<br>\
|
||||
<br>\
|
||||
For example, if you distribute copies of such a program, whether<br>\
|
||||
gratis or for a fee, you must give the recipients all the rights that<br>\
|
||||
you have. You must make sure that they, too, receive or can get the<br>\
|
||||
source code. And you must show them these terms so they know their<br>\
|
||||
rights.<br>\
|
||||
<br>\
|
||||
We protect your rights with two steps: (1) copyright the software, and<br>\
|
||||
(2) offer you this license which gives you legal permission to copy,<br>\
|
||||
distribute and/or modify the software.<br>\
|
||||
<br>\
|
||||
Also, for each author's protection and ours, we want to make certain<br>\
|
||||
that everyone understands that there is no warranty for this free<br>\
|
||||
software. If the software is modified by someone else and passed on, we<br>\
|
||||
want its recipients to know that what they have is not the original, so<br>\
|
||||
that any problems introduced by others will not reflect on the original<br>\
|
||||
authors' reputations.<br>\
|
||||
<br>\
|
||||
Finally, any free program is threatened constantly by software<br>\
|
||||
patents. We wish to avoid the danger that redistributors of a free<br>\
|
||||
program will individually obtain patent licenses, in effect making the<br>\
|
||||
program proprietary. To prevent this, we have made it clear that any<br>\
|
||||
patent must be licensed for everyone's free use or not licensed at all.<br>\
|
||||
<br>\
|
||||
The precise terms and conditions for copying, distribution and<br>\
|
||||
modification follow.<br>\
|
||||
<br>\
|
||||
<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
|
||||
<center><b>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</b></center><br>\
|
||||
0. This License applies to any program or other work which contains<br>\
|
||||
a notice placed by the copyright holder saying it may be distributed<br>\
|
||||
under the terms of this General Public License. The 'Program', below,<br>\
|
||||
refers to any such program or work, and a 'work based on the Program'<br>\
|
||||
means either the Program or any derivative work under copyright law:<br>\
|
||||
that is to say, a work containing the Program or a portion of it,<br>\
|
||||
either verbatim or with modifications and/or translated into another<br>\
|
||||
language. (Hereinafter, translation is included without limitation in<br>\
|
||||
the term 'modification'.) Each licensee is addressed as 'you'.<br>\
|
||||
<br>\
|
||||
Activities other than copying, distribution and modification are not<br>\
|
||||
covered by this License; they are outside its scope. The act of<br>\
|
||||
running the Program is not restricted, and the output from the Program<br>\
|
||||
is covered only if its contents constitute a work based on the<br>\
|
||||
Program (independent of having been made by running the Program).<br>\
|
||||
Whether that is true depends on what the Program does.<br>\
|
||||
<br>\
|
||||
1. You may copy and distribute verbatim copies of the Program's<br>\
|
||||
source code as you receive it, in any medium, provided that you<br>\
|
||||
conspicuously and appropriately publish on each copy an appropriate<br>\
|
||||
copyright notice and disclaimer of warranty; keep intact all the<br>\
|
||||
notices that refer to this License and to the absence of any warranty;<br>\
|
||||
and give any other recipients of the Program a copy of this License<br>\
|
||||
along with the Program.<br>\
|
||||
<br>\
|
||||
You may charge a fee for the physical act of transferring a copy, and<br>\
|
||||
you may at your option offer warranty protection in exchange for a fee.<br>\
|
||||
<br>\
|
||||
2. You may modify your copy or copies of the Program or any portion<br>\
|
||||
of it, thus forming a work based on the Program, and copy and<br>\
|
||||
distribute such modifications or work under the terms of Section 1<br>\
|
||||
above, provided that you also meet all of these conditions:<br>\
|
||||
<br>\
|
||||
a) You must cause the modified files to carry prominent notices<br>\
|
||||
stating that you changed the files and the date of any change.<br>\
|
||||
<br>\
|
||||
b) You must cause any work that you distribute or publish, that in<br>\
|
||||
whole or in part contains or is derived from the Program or any<br>\
|
||||
part thereof, to be licensed as a whole at no charge to all third<br>\
|
||||
parties under the terms of this License.<br>\
|
||||
<br>\
|
||||
c) If the modified program normally reads commands interactively<br>\
|
||||
when run, you must cause it, when started running for such<br>\
|
||||
interactive use in the most ordinary way, to print or display an<br>\
|
||||
announcement including an appropriate copyright notice and a<br>\
|
||||
notice that there is no warranty (or else, saying that you provide<br>\
|
||||
a warranty) and that users may redistribute the program under<br>\
|
||||
these conditions, and telling the user how to view a copy of this<br>\
|
||||
License. (Exception: if the Program itself is interactive but<br>\
|
||||
does not normally print such an announcement, your work based on<br>\
|
||||
the Program is not required to print an announcement.)<br>\
|
||||
<br>\
|
||||
These requirements apply to the modified work as a whole. If<br>\
|
||||
identifiable sections of that work are not derived from the Program,<br>\
|
||||
and can be reasonably considered independent and separate works in<br>\
|
||||
themselves, then this License, and its terms, do not apply to those<br>\
|
||||
sections when you distribute them as separate works. But when you<br>\
|
||||
distribute the same sections as part of a whole which is a work based<br>\
|
||||
on the Program, the distribution of the whole must be on the terms of<br>\
|
||||
this License, whose permissions for other licensees extend to the<br>\
|
||||
entire whole, and thus to each and every part regardless of who wrote it.<br>\
|
||||
<br>\
|
||||
Thus, it is not the intent of this section to claim rights or contest<br>\
|
||||
your rights to work written entirely by you; rather, the intent is to<br>\
|
||||
exercise the right to control the distribution of derivative or<br>\
|
||||
collective works based on the Program.<br>\
|
||||
<br>\
|
||||
In addition, mere aggregation of another work not based on the Program<br>\
|
||||
with the Program (or with a work based on the Program) on a volume of<br>\
|
||||
a storage or distribution medium does not bring the other work under<br>\
|
||||
the scope of this License.<br>\
|
||||
<br>\
|
||||
3. You may copy and distribute the Program (or a work based on it,<br>\
|
||||
under Section 2) in object code or executable form under the terms of<br>\
|
||||
Sections 1 and 2 above provided that you also do one of the following:<br>\
|
||||
<br>\
|
||||
a) Accompany it with the complete corresponding machine-readable<br>\
|
||||
source code, which must be distributed under the terms of Sections<br>\
|
||||
1 and 2 above on a medium customarily used for software interchange; or,<br>\
|
||||
<br>\
|
||||
b) Accompany it with a written offer, valid for at least three<br>\
|
||||
years, to give any third party, for a charge no more than your<br>\
|
||||
cost of physically performing source distribution, a complete<br>\
|
||||
machine-readable copy of the corresponding source code, to be<br>\
|
||||
distributed under the terms of Sections 1 and 2 above on a medium<br>\
|
||||
customarily used for software interchange; or,<br>\
|
||||
<br>\
|
||||
c) Accompany it with the information you received as to the offer<br>\
|
||||
to distribute corresponding source code. (This alternative is<br>\
|
||||
allowed only for noncommercial distribution and only if you<br>\
|
||||
received the program in object code or executable form with such<br>\
|
||||
an offer, in accord with Subsection b above.)<br>\
|
||||
<br>\
|
||||
The source code for a work means the preferred form of the work for<br>\
|
||||
making modifications to it. For an executable work, complete source<br>\
|
||||
code means all the source code for all modules it contains, plus any<br>\
|
||||
associated interface definition files, plus the scripts used to<br>\
|
||||
control compilation and installation of the executable. However, as a<br>\
|
||||
special exception, the source code distributed need not include<br>\
|
||||
anything that is normally distributed (in either source or binary<br>\
|
||||
form) with the major components (compiler, kernel, and so on) of the<br>\
|
||||
operating system on which the executable runs, unless that component<br>\
|
||||
itself accompanies the executable.<br>\
|
||||
<br>\
|
||||
If distribution of executable or object code is made by offering<br>\
|
||||
access to copy from a designated place, then offering equivalent<br>\
|
||||
access to copy the source code from the same place counts as<br>\
|
||||
distribution of the source code, even though third parties are not<br>\
|
||||
compelled to copy the source along with the object code.<br>\
|
||||
<br>\
|
||||
4. You may not copy, modify, sublicense, or distribute the Program<br>\
|
||||
except as expressly provided under this License. Any attempt<br>\
|
||||
otherwise to copy, modify, sublicense or distribute the Program is<br>\
|
||||
void, and will automatically terminate your rights under this License.<br>\
|
||||
However, parties who have received copies, or rights, from you under<br>\
|
||||
this License will not have their licenses terminated so long as such<br>\
|
||||
parties remain in full compliance.<br>\
|
||||
<br>\
|
||||
5. You are not required to accept this License, since you have not<br>\
|
||||
signed it. However, nothing else grants you permission to modify or<br>\
|
||||
distribute the Program or its derivative works. These actions are<br>\
|
||||
prohibited by law if you do not accept this License. Therefore, by<br>\
|
||||
modifying or distributing the Program (or any work based on the<br>\
|
||||
Program), you indicate your acceptance of this License to do so, and<br>\
|
||||
all its terms and conditions for copying, distributing or modifying<br>\
|
||||
the Program or works based on it.<br>\
|
||||
<br>\
|
||||
6. Each time you redistribute the Program (or any work based on the<br>\
|
||||
Program), the recipient automatically receives a license from the<br>\
|
||||
original licensor to copy, distribute or modify the Program subject to<br>\
|
||||
these terms and conditions. You may not impose any further<br>\
|
||||
restrictions on the recipients' exercise of the rights granted herein.<br>\
|
||||
You are not responsible for enforcing compliance by third parties to<br>\
|
||||
this License.<br>\
|
||||
<br>\
|
||||
7. If, as a consequence of a court judgment or allegation of patent<br>\
|
||||
infringement or for any other reason (not limited to patent issues),<br>\
|
||||
conditions are imposed on you (whether by court order, agreement or<br>\
|
||||
otherwise) that contradict the conditions of this License, they do not<br>\
|
||||
excuse you from the conditions of this License. If you cannot<br>\
|
||||
distribute so as to satisfy simultaneously your obligations under this<br>\
|
||||
License and any other pertinent obligations, then as a consequence you<br>\
|
||||
may not distribute the Program at all. For example, if a patent<br>\
|
||||
license would not permit royalty-free redistribution of the Program by<br>\
|
||||
all those who receive copies directly or indirectly through you, then<br>\
|
||||
the only way you could satisfy both it and this License would be to<br>\
|
||||
refrain entirely from distribution of the Program.<br>\
|
||||
<br>\
|
||||
If any portion of this section is held invalid or unenforceable under<br>\
|
||||
any particular circumstance, the balance of the section is intended to<br>\
|
||||
apply and the section as a whole is intended to apply in other<br>\
|
||||
circumstances.<br>\
|
||||
<br>\
|
||||
It is not the purpose of this section to induce you to infringe any<br>\
|
||||
patents or other property right claims or to contest validity of any<br>\
|
||||
such claims; this section has the sole purpose of protecting the<br>\
|
||||
integrity of the free software distribution system, which is<br>\
|
||||
implemented by public license practices. Many people have made<br>\
|
||||
generous contributions to the wide range of software distributed<br>\
|
||||
through that system in reliance on consistent application of that<br>\
|
||||
system; it is up to the author/donor to decide if he or she is willing<br>\
|
||||
to distribute software through any other system and a licensee cannot<br>\
|
||||
impose that choice.<br>\
|
||||
<br>\
|
||||
This section is intended to make thoroughly clear what is believed to<br>\
|
||||
be a consequence of the rest of this License.<br>\
|
||||
<br>\
|
||||
8. If the distribution and/or use of the Program is restricted in<br>\
|
||||
certain countries either by patents or by copyrighted interfaces, the<br>\
|
||||
original copyright holder who places the Program under this License<br>\
|
||||
may add an explicit geographical distribution limitation excluding<br>\
|
||||
those countries, so that distribution is permitted only in or among<br>\
|
||||
countries not thus excluded. In such case, this License incorporates<br>\
|
||||
the limitation as if written in the body of this License.<br>\
|
||||
<br>\
|
||||
9. The Free Software Foundation may publish revised and/or new versions<br>\
|
||||
of the General Public License from time to time. Such new versions will<br>\
|
||||
be similar in spirit to the present version, but may differ in detail to<br>\
|
||||
address new problems or concerns.<br>\
|
||||
<br>\
|
||||
Each version is given a distinguishing version number. If the Program<br>\
|
||||
specifies a version number of this License which applies to it and 'any<br>\
|
||||
later version', you have the option of following the terms and conditions<br>\
|
||||
either of that version or of any later version published by the Free<br>\
|
||||
Software Foundation. If the Program does not specify a version number of<br>\
|
||||
this License, you may choose any version ever published by the Free Software<br>\
|
||||
Foundation.<br>\
|
||||
<br>\
|
||||
10. If you wish to incorporate parts of the Program into other free<br>\
|
||||
programs whose distribution conditions are different, write to the author<br>\
|
||||
to ask for permission. For software which is copyrighted by the Free<br>\
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes<br>\
|
||||
make exceptions for this. Our decision will be guided by the two goals<br>\
|
||||
of preserving the free status of all derivatives of our free software and<br>\
|
||||
of promoting the sharing and reuse of software generally.<br>\
|
||||
<br>\
|
||||
<center><b>NO WARRANTY</b></center><br>\
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY<br>\
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN<br>\
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES<br>\
|
||||
PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED<br>\
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF<br>\
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS<br>\
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE<br>\
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,<br>\
|
||||
REPAIR OR CORRECTION.<br>\
|
||||
<br>\
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING<br>\
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR<br>\
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,<br>\
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING<br>\
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED<br>\
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY<br>\
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER<br>\
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE<br>\
|
||||
POSSIBILITY OF SUCH DAMAGES.<br>\
|
||||
<br>\
|
||||
<center><b>END OF TERMS AND CONDITIONS</b></center><br>\
|
||||
<center>How to Apply These Terms to Your New Programs</center><br>\
|
||||
If you develop a new program, and you want it to be of the greatest<br>\
|
||||
possible use to the public, the best way to achieve this is to make it<br>\
|
||||
free software which everyone can redistribute and change under these terms.<br>\
|
||||
<br>\
|
||||
To do so, attach the following notices to the program. It is safest<br>\
|
||||
to attach them to the start of each source file to most effectively<br>\
|
||||
convey the exclusion of warranty; and each file should have at least<br>\
|
||||
the 'copyright' line and a pointer to where the full notice is found.<br>\
|
||||
<br>\
|
||||
<one line to give the program's name and a brief idea of what it does.><br>\
|
||||
Copyright (C) <year> <name of author><br>\
|
||||
<br>\
|
||||
This program is free software; you can redistribute it and/or modify<br>\
|
||||
it under the terms of the GNU General Public License as published by<br>\
|
||||
the Free Software Foundation; either version 2 of the License, or<br>\
|
||||
(at your option) any later version.<br>\
|
||||
<br>\
|
||||
This program is distributed in the hope that it will be useful,<br>\
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>\
|
||||
GNU General Public License for more details.<br>\
|
||||
<br>\
|
||||
You should have received a copy of the GNU General Public License<br>\
|
||||
along with this program; if not, write to the Free Software<br>\
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
|
||||
<br>\
|
||||
<br>\
|
||||
Also add information on how to contact you by electronic and paper mail.<br>\
|
||||
<br>\
|
||||
If the program is interactive, make it output a short notice like this<br>\
|
||||
when it starts in an interactive mode:<br>\
|
||||
<br>\
|
||||
Gnomovision version 69, Copyright (C) year name of author<br>\
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.<br>\
|
||||
This is free software, and you are welcome to redistribute it<br>\
|
||||
under certain conditions; type `show c' for details.<br>\
|
||||
<br>\
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate<br>\
|
||||
parts of the General Public License. Of course, the commands you use may<br>\
|
||||
be called something other than `show w' and `show c'; they could even be<br>\
|
||||
mouse-clicks or menu items--whatever suits your program.<br>\
|
||||
<br>\
|
||||
You should also get your employer (if you work as a programmer) or your<br>\
|
||||
school, if any, to sign a 'copyright disclaimer' for the program, if<br>\
|
||||
necessary. Here is a sample; alter the names:<br>\
|
||||
<br>\
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program<br>\
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.<br>\
|
||||
<br>\
|
||||
'signature of Ty Coon', 1 April 1989<br>\
|
||||
Ty Coon, President of Vice<br>\
|
||||
<br>\
|
||||
This General Public License does not permit incorporating your program into<br>\
|
||||
proprietary programs. If your program is a subroutine library, you may<br>\
|
||||
consider it more useful to permit linking proprietary applications with the<br>\
|
||||
library. If this is what you want to do, use the GNU Library General<br>\
|
||||
Public License instead of this License.<br>"));
|
||||
#endif
|
||||
te_license->scrollToAnchor(QString::fromUtf8("top"));
|
||||
show();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,22 +5,18 @@
|
||||
#include <QHeaderView>
|
||||
#include <QSpinBox>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QNetworkInterface>
|
||||
#include <libtorrent/version.hpp>
|
||||
#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, MAX_HALF_OPEN, SUPER_SEEDING, NETWORK_IFACE, PROGRAM_NOTIFICATIONS };
|
||||
#define ROW_COUNT 13
|
||||
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, *spin_maxhalfopen;
|
||||
QCheckBox *cb_ignore_limits_lan, *cb_count_overhead, *cb_recheck_completed, *cb_resolve_countries, *cb_resolve_hosts, *cb_super_seeding, *cb_program_notifications;
|
||||
QComboBox *combo_iface;
|
||||
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) {
|
||||
@@ -49,10 +45,6 @@ public:
|
||||
delete spin_list_refresh;
|
||||
delete cb_resolve_countries;
|
||||
delete cb_resolve_hosts;
|
||||
delete spin_maxhalfopen;
|
||||
delete cb_super_seeding;
|
||||
delete combo_iface;
|
||||
delete cb_program_notifications;
|
||||
}
|
||||
|
||||
public slots:
|
||||
@@ -73,21 +65,6 @@ public slots:
|
||||
// Peer resolution
|
||||
Preferences::resolvePeerCountries(cb_resolve_countries->isChecked());
|
||||
Preferences::resolvePeerHostNames(cb_resolve_hosts->isChecked());
|
||||
// Max Half-Open connections
|
||||
Preferences::setMaxHalfOpenConnections(spin_maxhalfopen->value());
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
// Super seeding
|
||||
Preferences::enableSuperSeeding(cb_super_seeding->isChecked());
|
||||
#endif
|
||||
// Network interface
|
||||
if(combo_iface->currentIndex() == 0) {
|
||||
// All interfaces (default)
|
||||
Preferences::setNetworkInterface(QString::null);
|
||||
} else {
|
||||
Preferences::setNetworkInterface(combo_iface->currentText());
|
||||
}
|
||||
// Program notification
|
||||
Preferences::useProgramNotification(cb_program_notifications->isChecked());
|
||||
}
|
||||
|
||||
protected slots:
|
||||
@@ -156,45 +133,6 @@ protected slots:
|
||||
connect(cb_resolve_hosts, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
||||
cb_resolve_hosts->setChecked(Preferences::resolvePeerHostNames());
|
||||
setCellWidget(RESOLVE_HOSTS, VALUE, cb_resolve_hosts);
|
||||
// Max Half Open connections
|
||||
setItem(MAX_HALF_OPEN, PROPERTY, new QTableWidgetItem(tr("Maximum number of half-open connections [0: Disabled]")));
|
||||
spin_maxhalfopen = new QSpinBox();
|
||||
connect(spin_maxhalfopen, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
|
||||
spin_maxhalfopen->setMinimum(0);
|
||||
spin_maxhalfopen->setMaximum(99999);
|
||||
spin_maxhalfopen->setValue(Preferences::getMaxHalfOpenConnections());
|
||||
setCellWidget(MAX_HALF_OPEN, VALUE, spin_maxhalfopen);
|
||||
// Super seeding
|
||||
setItem(SUPER_SEEDING, PROPERTY, new QTableWidgetItem(tr("Strict super seeding")));
|
||||
cb_super_seeding = new QCheckBox();
|
||||
connect(cb_super_seeding, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
cb_super_seeding->setChecked(Preferences::isSuperSeedingEnabled());
|
||||
#else
|
||||
cb_super_seeding->setEnabled(false);
|
||||
#endif
|
||||
setCellWidget(SUPER_SEEDING, VALUE, cb_super_seeding);
|
||||
// Network interface
|
||||
setItem(NETWORK_IFACE, PROPERTY, new QTableWidgetItem(tr("Network Interface (requires restart)")));
|
||||
combo_iface = new QComboBox;
|
||||
combo_iface->addItem(tr("Any interface", "i.e. Any network interface"));
|
||||
const QString current_iface = Preferences::getNetworkInterface();
|
||||
int i = 1;
|
||||
foreach(const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
|
||||
if(iface.name() == "lo") continue;
|
||||
combo_iface->addItem(iface.name());
|
||||
if(!current_iface.isEmpty() && iface.name() == current_iface)
|
||||
combo_iface->setCurrentIndex(i);
|
||||
++i;
|
||||
}
|
||||
connect(combo_iface, SIGNAL(currentIndexChanged(int)), this, SLOT(emitSettingsChanged()));
|
||||
setCellWidget(NETWORK_IFACE, VALUE, combo_iface);
|
||||
// Program notifications
|
||||
setItem(PROGRAM_NOTIFICATIONS, PROPERTY, new QTableWidgetItem(tr("Display program notification baloons")));
|
||||
cb_program_notifications = new QCheckBox();
|
||||
connect(cb_program_notifications, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
|
||||
cb_program_notifications->setChecked(Preferences::useProgramNotification());
|
||||
setCellWidget(PROGRAM_NOTIFICATIONS, VALUE, cb_program_notifications);
|
||||
}
|
||||
|
||||
void emitSettingsChanged() {
|
||||
|
||||
1400
src/bittorrent.cpp
@@ -43,7 +43,6 @@
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/ip_filter.hpp>
|
||||
#include "qtorrenthandle.h"
|
||||
@@ -64,7 +63,7 @@ public:
|
||||
QString name_or_url;
|
||||
QString last_message;
|
||||
unsigned long num_peers;
|
||||
#if LIBTORRENT_VERSION_MINOR < 15
|
||||
#ifndef LIBTORRENT_0_15
|
||||
bool verified;
|
||||
uint fail_count;
|
||||
#endif
|
||||
@@ -75,13 +74,13 @@ public:
|
||||
Q_ASSERT(!name_or_url.isEmpty());
|
||||
last_message = b.last_message;
|
||||
num_peers = b.num_peers;
|
||||
#if LIBTORRENT_VERSION_MINOR < 15
|
||||
#ifndef LIBTORRENT_0_15
|
||||
verified = b.verified;
|
||||
fail_count = b.fail_count;
|
||||
#endif
|
||||
}
|
||||
TrackerInfos(QString name_or_url): name_or_url(name_or_url), last_message(""), num_peers(0) {
|
||||
#if LIBTORRENT_VERSION_MINOR < 15
|
||||
#ifndef LIBTORRENT_0_15
|
||||
fail_count = 0;
|
||||
verified = false;
|
||||
#endif
|
||||
@@ -108,7 +107,6 @@ public:
|
||||
session* getSession() const;
|
||||
QHash<QString, TrackerInfos> getTrackersInfo(QString hash) const;
|
||||
bool hasActiveTorrents() const;
|
||||
bool hasDownloadingTorrents() const;
|
||||
bool isQueueingEnabled() const;
|
||||
int getMaximumActiveDownloads() const;
|
||||
int getMaximumActiveTorrents() const;
|
||||
@@ -119,10 +117,6 @@ public:
|
||||
bool useTemporaryFolder() const;
|
||||
QString getDefaultSavePath() const;
|
||||
ScanFoldersModel* getScanFoldersModel() const;
|
||||
bool isPexEnabled() const;
|
||||
#if LIBTORRENT_VERSION_MINOR < 15
|
||||
void saveDHTEntry();
|
||||
#endif
|
||||
|
||||
public slots:
|
||||
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
|
||||
@@ -141,6 +135,7 @@ public slots:
|
||||
void resumeTorrent(QString hash);
|
||||
void resumeAllTorrents();
|
||||
/* End Web UI */
|
||||
void saveDHTEntry();
|
||||
void preAllocateAllFiles(bool b);
|
||||
void saveFastResumeData();
|
||||
void enableIPFilter(QString filter);
|
||||
@@ -155,7 +150,8 @@ public slots:
|
||||
void setMaxUploadsPerTorrent(int max);
|
||||
void setDownloadRateLimit(long rate);
|
||||
void setUploadRateLimit(long rate);
|
||||
void setMaxRatio(float ratio);
|
||||
void setGlobalRatio(float ratio);
|
||||
void setDeleteRatio(float ratio);
|
||||
void setDHTPort(int dht_port);
|
||||
void setPeerProxySettings(const proxy_settings &proxySettings);
|
||||
void setHTTPProxySettings(const proxy_settings &proxySettings);
|
||||
@@ -163,10 +159,10 @@ public slots:
|
||||
void startTorrentsInPause(bool b);
|
||||
void setDefaultTempPath(QString temppath);
|
||||
void setAppendLabelToSavePath(bool append);
|
||||
void appendLabelToTorrentSavePath(QTorrentHandle &h);
|
||||
void changeLabelInTorrentSavePath(QTorrentHandle &h, QString old_label, QString new_label);
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
void appendqBextensionToTorrent(QTorrentHandle &h, bool append);
|
||||
void appendLabelToTorrentSavePath(QTorrentHandle h);
|
||||
void changeLabelInTorrentSavePath(QTorrentHandle h, QString old_label, QString new_label);
|
||||
#ifdef LIBTORRENT_0_15
|
||||
void appendqBextensionToTorrent(QTorrentHandle h, bool append);
|
||||
void setAppendqBExtension(bool append);
|
||||
#endif
|
||||
void applyEncryptionSettings(pe_settings se);
|
||||
@@ -190,19 +186,16 @@ public slots:
|
||||
void recursiveTorrentDownload(const QTorrentHandle &h);
|
||||
|
||||
protected:
|
||||
QString getSavePath(QString hash, bool fromScanDir = false, QString filePath = QString::null, QString root_folder=QString::null);
|
||||
QString getSavePath(QString hash, bool fromScanDir = false, QString filePath = QString());
|
||||
bool initWebUi(QString username, QString password, int port);
|
||||
|
||||
protected slots:
|
||||
void addTorrentsFromScanFolder(QStringList&);
|
||||
void readAlerts();
|
||||
void processBigRatios();
|
||||
void deleteBigRatios();
|
||||
void takeETASamples();
|
||||
void exportTorrentFiles(QString path);
|
||||
void saveTempFastResumeData();
|
||||
void sendNotificationEmail(QTorrentHandle h);
|
||||
void autoRunExternalProgram(QTorrentHandle h, bool async=true);
|
||||
void cleanUpAutoRunProcess(int);
|
||||
|
||||
signals:
|
||||
void addedTorrent(QTorrentHandle& h);
|
||||
@@ -230,7 +223,6 @@ private:
|
||||
QPointer<BandwidthScheduler> bd_scheduler;
|
||||
QMap<QUrl, QString> savepath_fromurl;
|
||||
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
|
||||
QHash<QString, QString> savePathsToRemove;
|
||||
QStringList torrentsToPausedAfterChecking;
|
||||
QTimer resumeDataTimer;
|
||||
// Ratio
|
||||
@@ -246,7 +238,6 @@ private:
|
||||
bool preAllocateAll;
|
||||
bool addInPause;
|
||||
float ratio_limit;
|
||||
int high_ratio_action;
|
||||
bool UPnPEnabled;
|
||||
bool NATPMPEnabled;
|
||||
bool LSDEnabled;
|
||||
@@ -256,7 +247,7 @@ private:
|
||||
bool queueingEnabled;
|
||||
bool appendLabelToSavePath;
|
||||
bool torrentExport;
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
#ifdef LIBTORRENT_0_15
|
||||
bool appendqBExtension;
|
||||
#endif
|
||||
QString defaultSavePath;
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org arnaud@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "cookiesdlg.h"
|
||||
#include "ui_cookiesdlg.h"
|
||||
|
||||
#include <QNetworkCookie>
|
||||
|
||||
enum CookiesCols { COOKIE_KEY, COOKIE_VALUE};
|
||||
|
||||
CookiesDlg::CookiesDlg(QWidget *parent, const QList<QByteArray> &raw_cookies) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CookiesDlg)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->infos_lbl->setText(tr("Common keys for cookies are : '%1', '%2'.\nYou should get this information from your Web browser preferences.").arg("uid").arg("pass"));
|
||||
foreach(const QByteArray &raw_cookie, raw_cookies) {
|
||||
QList<QByteArray> cookie_parts = raw_cookie.split('=');
|
||||
if(cookie_parts.size() != 2) continue;
|
||||
const int i = ui->cookiesTable->rowCount();
|
||||
ui->cookiesTable->setRowCount(i+1);
|
||||
ui->cookiesTable->setItem(i, COOKIE_KEY, new QTableWidgetItem(cookie_parts.first().data()));
|
||||
ui->cookiesTable->setItem(i, COOKIE_VALUE, new QTableWidgetItem(cookie_parts.last().data()));
|
||||
}
|
||||
}
|
||||
|
||||
CookiesDlg::~CookiesDlg()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CookiesDlg::on_add_btn_clicked() {
|
||||
ui->cookiesTable->setRowCount(ui->cookiesTable->rowCount()+1);
|
||||
// Edit first column
|
||||
ui->cookiesTable->editItem(ui->cookiesTable->item(ui->cookiesTable->rowCount()-1, COOKIE_KEY));
|
||||
}
|
||||
|
||||
void CookiesDlg::on_del_btn_clicked() {
|
||||
// Get selected cookie
|
||||
QList<QTableWidgetItem*> selection = ui->cookiesTable->selectedItems();
|
||||
if(!selection.isEmpty()) {
|
||||
ui->cookiesTable->removeRow(selection.first()->row());
|
||||
}
|
||||
}
|
||||
|
||||
QList<QByteArray> CookiesDlg::getCookies() const {
|
||||
QList<QByteArray> ret;
|
||||
for(int i=0; i<ui->cookiesTable->rowCount(); ++i) {
|
||||
QString key = ui->cookiesTable->item(i, COOKIE_KEY)->text().trimmed();
|
||||
QString value = ui->cookiesTable->item(i, COOKIE_VALUE)->text().trimmed();
|
||||
if(!key.isEmpty() && !value.isEmpty()) {
|
||||
const QString raw_cookie = key+"="+value;
|
||||
qDebug("Cookie: %s", qPrintable(raw_cookie));
|
||||
ret << raw_cookie.toLocal8Bit();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<QByteArray> CookiesDlg::askForCookies(QWidget *parent, const QList<QByteArray> &raw_cookies, bool *ok) {
|
||||
CookiesDlg dlg(parent, raw_cookies);
|
||||
if(dlg.exec()) {
|
||||
*ok = true;
|
||||
return dlg.getCookies();
|
||||
}
|
||||
*ok = false;
|
||||
return QList<QByteArray>();
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org arnaud@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef COOKIESDLG_H
|
||||
#define COOKIESDLG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class CookiesDlg;
|
||||
}
|
||||
|
||||
class CookiesDlg : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CookiesDlg(QWidget *parent = 0, const QList<QByteArray> &raw_cookies = QList<QByteArray>());
|
||||
~CookiesDlg();
|
||||
QList<QByteArray> getCookies() const;
|
||||
static QList<QByteArray> askForCookies(QWidget *parent, const QList<QByteArray> &raw_cookies, bool *ok);
|
||||
|
||||
protected slots:
|
||||
void on_add_btn_clicked();
|
||||
void on_del_btn_clicked();
|
||||
|
||||
private:
|
||||
Ui::CookiesDlg *ui;
|
||||
};
|
||||
|
||||
#endif // COOKIESDLG_H
|
||||
@@ -37,7 +37,6 @@
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
@@ -50,7 +49,6 @@
|
||||
#include "torrentpersistentdata.h"
|
||||
#include "createtorrent_imp.h"
|
||||
#include "misc.h"
|
||||
#include "qinisettings.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
using namespace boost::filesystem;
|
||||
@@ -69,7 +67,7 @@ createtorrent::createtorrent(QWidget *parent): QDialog(parent){
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setModal(true);
|
||||
creatorThread = new torrentCreatorThread(this);
|
||||
connect(creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString)));
|
||||
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(updateProgress(int)), this, SLOT(updateProgressBar(int)));
|
||||
path::default_name_check(no_check);
|
||||
@@ -81,29 +79,15 @@ createtorrent::~createtorrent() {
|
||||
}
|
||||
|
||||
void createtorrent::on_addFolder_button_clicked(){
|
||||
QIniSettings settings("qBittorrent", "qBittorrent");
|
||||
QString last_path = settings.value("CreateTorrent/last_add_path", QDir::homePath()).toString();
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), last_path, QFileDialog::ShowDirsOnly);
|
||||
if(!dir.isEmpty()) {
|
||||
settings.setValue("CreateTorrent/last_add_path", dir);
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
dir = dir.replace("/", "\\");
|
||||
#endif
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), QDir::homePath(), QFileDialog::ShowDirsOnly);
|
||||
if(!dir.isEmpty())
|
||||
textInputPath->setText(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void createtorrent::on_addFile_button_clicked(){
|
||||
QIniSettings settings("qBittorrent", "qBittorrent");
|
||||
QString last_path = settings.value("CreateTorrent/last_add_path", QDir::homePath()).toString();
|
||||
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), last_path);
|
||||
if(!file.isEmpty()) {
|
||||
settings.setValue("CreateTorrent/last_add_path", misc::removeLastPathPart(file));
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
file = file.replace("/", "\\");
|
||||
#endif
|
||||
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath());
|
||||
if(!file.isEmpty())
|
||||
textInputPath->setText(file);
|
||||
}
|
||||
}
|
||||
|
||||
void createtorrent::on_removeTracker_button_clicked() {
|
||||
@@ -184,59 +168,39 @@ void createtorrent::on_createButton_clicked(){
|
||||
return;
|
||||
}
|
||||
QStringList trackers = allItems(trackers_list);
|
||||
|
||||
QIniSettings settings("qBittorrent", "qBittorrent");
|
||||
QString last_path = settings.value("CreateTorrent/last_save_path", QDir::homePath()).toString();
|
||||
|
||||
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), last_path, tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
|
||||
/*if(!trackers.size()){
|
||||
QMessageBox::critical(0, tr("No tracker path set"), tr("Please set at least one tracker"));
|
||||
return;
|
||||
}*/
|
||||
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
|
||||
if(!destination.isEmpty()) {
|
||||
settings.setValue("CreateTorrent/last_save_path", misc::removeLastPathPart(destination));
|
||||
if(!destination.toUpper().endsWith(".TORRENT"))
|
||||
if(!destination.endsWith(QString::fromUtf8(".torrent")))
|
||||
destination += QString::fromUtf8(".torrent");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
// Disable dialog
|
||||
setEnabled(false);
|
||||
// Set busy cursor
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
// Actually create the torrent
|
||||
QStringList url_seeds = allItems(URLSeeds_list);
|
||||
QString comment = txt_comment->toPlainText();
|
||||
creatorThread->create(input, destination, trackers, url_seeds, comment, check_private->isChecked(), getPieceSize());
|
||||
}
|
||||
|
||||
void createtorrent::handleCreationFailure(QString msg) {
|
||||
// Enable dialog
|
||||
setEnabled(true);
|
||||
// Remove busy cursor
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(msg));
|
||||
}
|
||||
|
||||
void createtorrent::handleCreationSuccess(QString path, QString branch_path) {
|
||||
// Enable Dialog
|
||||
setEnabled(true);
|
||||
// Remove busy cursor
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
void createtorrent::handleCreationSuccess(QString path, const char* branch_path) {
|
||||
if(checkStartSeeding->isChecked()) {
|
||||
QString root_folder;
|
||||
// Create save path temp data
|
||||
boost::intrusive_ptr<torrent_info> t;
|
||||
try {
|
||||
t = new torrent_info(path.toUtf8().data());
|
||||
root_folder = misc::truncateRootFolder(t);
|
||||
t = new torrent_info(path.toLocal8Bit().data());
|
||||
} catch(std::exception&) {
|
||||
QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
|
||||
return;
|
||||
}
|
||||
QString hash = misc::toQString(t->info_hash());
|
||||
QString save_path = branch_path;
|
||||
if(!root_folder.isEmpty()) {
|
||||
save_path = QDir(save_path).absoluteFilePath(root_folder);
|
||||
}
|
||||
TorrentTempData::setSavePath(hash, save_path);
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
TorrentTempData::setSavePath(hash, QString(branch_path));
|
||||
#ifdef LIBTORRENT_0_15
|
||||
// Enable seeding mode (do not recheck the files)
|
||||
TorrentTempData::setSeedingMode(hash, true);
|
||||
#endif
|
||||
@@ -246,18 +210,6 @@ void createtorrent::handleCreationSuccess(QString path, QString branch_path) {
|
||||
close();
|
||||
}
|
||||
|
||||
void createtorrent::on_cancelButton_clicked() {
|
||||
// End torrent creation thread
|
||||
if(creatorThread->isRunning()) {
|
||||
creatorThread->abortCreation();
|
||||
creatorThread->terminate();
|
||||
// Wait for termination
|
||||
creatorThread->wait();
|
||||
}
|
||||
// Close the dialog
|
||||
reject();
|
||||
}
|
||||
|
||||
void createtorrent::updateProgressBar(int progress) {
|
||||
progressBar->setValue(progress);
|
||||
}
|
||||
@@ -291,7 +243,8 @@ void torrentCreatorThread::run() {
|
||||
char const* creator_str = "qBittorrent "VERSION;
|
||||
try {
|
||||
file_storage fs;
|
||||
path full_path = complete(path(input_path.toUtf8().constData()));
|
||||
file_pool fp;
|
||||
path full_path = complete(path(input_path.toLocal8Bit().data()));
|
||||
// Adding files to the torrent
|
||||
add_files(fs, full_path, file_filter);
|
||||
if(abort) return;
|
||||
@@ -311,15 +264,15 @@ void torrentCreatorThread::run() {
|
||||
// Set qBittorrent as creator and add user comment to
|
||||
// torrent_info structure
|
||||
t.set_creator(creator_str);
|
||||
t.set_comment((const char*)comment.toUtf8());
|
||||
t.set_comment((const char*)comment.toLocal8Bit());
|
||||
// Is private ?
|
||||
t.set_priv(is_private);
|
||||
if(abort) return;
|
||||
// create the torrent and print it to out
|
||||
ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
|
||||
ofstream out(complete(path((const char*)save_path.toLocal8Bit())), std::ios_base::binary);
|
||||
bencode(std::ostream_iterator<char>(out), t.generate());
|
||||
emit updateProgress(100);
|
||||
emit creationSuccess(save_path, QString::fromUtf8(full_path.branch_path().string().c_str()));
|
||||
emit creationSuccess(save_path, full_path.branch_path().string().c_str());
|
||||
}
|
||||
catch (std::exception& e){
|
||||
emit creationFailure(QString::fromUtf8(e.what()));
|
||||
|
||||
@@ -58,14 +58,13 @@ class torrentCreatorThread : public QThread {
|
||||
}
|
||||
void create(QString _input_path, QString _save_path, QStringList _trackers, QStringList _url_seeds, QString _comment, bool _is_private, int _piece_size);
|
||||
void sendProgressSignal(int progress);
|
||||
void abortCreation() { abort = true; }
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void creationFailure(QString msg);
|
||||
void creationSuccess(QString path, QString branch_path);
|
||||
void creationSuccess(QString path, const char* branch_path);
|
||||
|
||||
signals:
|
||||
void updateProgress(int progress);
|
||||
@@ -88,7 +87,6 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
||||
|
||||
public slots:
|
||||
void updateProgressBar(int progress);
|
||||
void on_cancelButton_clicked();
|
||||
|
||||
protected slots:
|
||||
void on_createButton_clicked();
|
||||
@@ -99,7 +97,7 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
||||
void on_addURLSeed_button_clicked();
|
||||
void on_removeURLSeed_button_clicked();
|
||||
void handleCreationFailure(QString msg);
|
||||
void handleCreationSuccess(QString path, QString branch_path);
|
||||
void handleCreationSuccess(QString path, const char* branch_path);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include "ui_confirmdeletiondlg.h"
|
||||
#include "preferences.h"
|
||||
#include "misc.h"
|
||||
|
||||
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
@@ -43,9 +42,6 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
DeletionConfirmationDlg(QWidget *parent=0): QDialog(parent) {
|
||||
setupUi(this);
|
||||
move(misc::screenCenter(this));
|
||||
checkPermDelete->setChecked(Preferences::deleteTorrentFilesAsDefault());
|
||||
connect(checkPermDelete, SIGNAL(clicked()), this, SLOT(updateRememberButtonState()));
|
||||
buttonBox->setFocus();
|
||||
}
|
||||
|
||||
bool shouldDeleteLocalFiles() const {
|
||||
@@ -61,15 +57,6 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
return false;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void updateRememberButtonState() {
|
||||
rememberBtn->setEnabled(checkPermDelete->isChecked() != Preferences::deleteTorrentFilesAsDefault());
|
||||
}
|
||||
|
||||
void on_rememberBtn_clicked() {
|
||||
Preferences::setDeleteTorrentFilesAsDefault(checkPermDelete->isChecked());
|
||||
rememberBtn->setEnabled(false);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DELETIONCONFIRMATIONDLG_H
|
||||
|
||||
@@ -60,34 +60,31 @@ public:
|
||||
pix.fill();
|
||||
pixmap = pix;
|
||||
} else {
|
||||
const qulonglong nb_pieces = pieces.size();
|
||||
const int nb_pieces = pieces.size();
|
||||
// Reduce the number of pieces before creating the pixmap
|
||||
// otherwise it can crash when there are too many pieces
|
||||
const uint w = width();
|
||||
if(nb_pieces > w) {
|
||||
const uint ratio = floor(nb_pieces/(double)w);
|
||||
bitfield scaled_pieces(ceil(nb_pieces/(double)ratio), false);
|
||||
bitfield scaled_downloading(ceil(nb_pieces/(double)ratio), false);
|
||||
uint scaled_index = 0;
|
||||
for(qulonglong i=0; i<nb_pieces; i+= ratio) {
|
||||
if(nb_pieces > width()) {
|
||||
const int ratio = floor(nb_pieces/(double)width());
|
||||
std::vector<bool> scaled_pieces;
|
||||
std::vector<bool> scaled_downloading;
|
||||
for(int i=0; i<nb_pieces; i+= ratio) {
|
||||
bool have = true;
|
||||
for(qulonglong 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; }
|
||||
}
|
||||
scaled_pieces.push_back(have);
|
||||
if(have) {
|
||||
scaled_pieces.set_bit(scaled_index);
|
||||
scaled_downloading.push_back(false);
|
||||
} else {
|
||||
bool downloading = false;
|
||||
for(qulonglong j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
||||
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
||||
if(downloading_pieces[i]) { downloading = true; break; }
|
||||
}
|
||||
if(downloading)
|
||||
scaled_downloading.set_bit(scaled_index);
|
||||
scaled_downloading.push_back(downloading);
|
||||
}
|
||||
++scaled_index;
|
||||
}
|
||||
QPixmap pix = QPixmap(scaled_pieces.size(), 1);
|
||||
//pix.fill();
|
||||
pix.fill();
|
||||
QPainter painter(&pix);
|
||||
for(uint i=0; i<scaled_pieces.size(); ++i) {
|
||||
if(scaled_pieces[i]) {
|
||||
@@ -104,7 +101,7 @@ public:
|
||||
pixmap = pix;
|
||||
} else {
|
||||
QPixmap pix = QPixmap(pieces.size(), 1);
|
||||
//pix.fill();
|
||||
pix.fill();
|
||||
QPainter painter(&pix);
|
||||
for(uint i=0; i<pieces.size(); ++i) {
|
||||
if(pieces[i]) {
|
||||
|
||||
@@ -51,7 +51,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
show();
|
||||
// Paste clipboard if there is an URL in it
|
||||
QString clip_txt = qApp->clipboard()->text();
|
||||
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive) || clip_txt.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
textUrls->setText(clip_txt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,34 +28,32 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "downloadthread.h"
|
||||
#include <QTemporaryFile>
|
||||
#include <QSettings>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkCookieJar>
|
||||
|
||||
#include "downloadthread.h"
|
||||
#include "preferences.h"
|
||||
#include "qinisettings.h"
|
||||
|
||||
enum ProxyType {HTTP=1, SOCKS5=2, HTTP_PW=3, SOCKS5_PW=4, SOCKS4=5};
|
||||
|
||||
/** Download Thread **/
|
||||
|
||||
downloadThread::downloadThread(QObject* parent) : QObject(parent) {
|
||||
connect(&networkManager, SIGNAL(finished (QNetworkReply*)), this, SLOT(processDlFinished(QNetworkReply*)));
|
||||
#ifndef QT_NO_OPENSSL
|
||||
connect(&networkManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
|
||||
#endif
|
||||
networkManager = new QNetworkAccessManager(this);
|
||||
connect(networkManager, SIGNAL(finished (QNetworkReply*)), this, SLOT(processDlFinished(QNetworkReply*)));
|
||||
}
|
||||
|
||||
downloadThread::~downloadThread(){
|
||||
qDebug("Deleting network manager");
|
||||
delete networkManager;
|
||||
qDebug("Deleted network manager");
|
||||
}
|
||||
|
||||
void downloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
QString url = reply->url().toEncoded().data();
|
||||
qDebug("Download finished: %s", qPrintable(url));
|
||||
QString url = reply->url().toString();
|
||||
if(reply->error() != QNetworkReply::NoError) {
|
||||
// Failure
|
||||
qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(reply->error())));
|
||||
emit downloadFailure(url, errorCodeToString(reply->error()));
|
||||
} else {
|
||||
QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
@@ -72,27 +70,24 @@ void downloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
}
|
||||
// Success
|
||||
QString filePath;
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
||||
tmpfile->setAutoRemove(false);
|
||||
if (tmpfile->open()) {
|
||||
filePath = tmpfile->fileName();
|
||||
QTemporaryFile tmpfile;
|
||||
tmpfile.setAutoRemove(false);
|
||||
if (tmpfile.open()) {
|
||||
filePath = tmpfile.fileName();
|
||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
||||
if(reply->open(QIODevice::ReadOnly)) {
|
||||
// TODO: Support GZIP compression
|
||||
tmpfile->write(reply->readAll());
|
||||
tmpfile.write(reply->readAll());
|
||||
reply->close();
|
||||
tmpfile->close();
|
||||
delete tmpfile;
|
||||
tmpfile.close();
|
||||
// Send finished signal
|
||||
emit downloadFinished(url, filePath);
|
||||
} else {
|
||||
// Error when reading the request
|
||||
tmpfile->close();
|
||||
delete tmpfile;
|
||||
tmpfile.close();
|
||||
emit downloadFailure(url, tr("I/O Error"));
|
||||
}
|
||||
} else {
|
||||
delete tmpfile;
|
||||
emit downloadFailure(url, tr("I/O Error"));
|
||||
}
|
||||
}
|
||||
@@ -100,28 +95,7 @@ void downloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void downloadThread::loadCookies(const QString &host_name, QString url) {
|
||||
const QList<QByteArray> raw_cookies = Preferences::getHostNameCookies(host_name);
|
||||
QNetworkCookieJar *cookie_jar = networkManager.cookieJar();
|
||||
QList<QNetworkCookie> cookies;
|
||||
qDebug("Loading cookies for host name: %s", qPrintable(host_name));
|
||||
foreach(const QByteArray& raw_cookie, raw_cookies) {
|
||||
QList<QByteArray> cookie_parts = raw_cookie.split('=');
|
||||
if(cookie_parts.size() == 2) {
|
||||
qDebug("Loading cookie: %s", raw_cookie.constData());
|
||||
cookies << QNetworkCookie(cookie_parts.first(), cookie_parts.last());
|
||||
}
|
||||
}
|
||||
cookie_jar->setCookiesFromUrl(cookies, url);
|
||||
networkManager.setCookieJar(cookie_jar);
|
||||
}
|
||||
|
||||
void downloadThread::downloadTorrentUrl(QString url){
|
||||
// Load cookies
|
||||
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
|
||||
if(!host_name.isEmpty())
|
||||
loadCookies(host_name, url);
|
||||
// Process request
|
||||
QNetworkReply *reply = downloadUrl(url);
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
||||
}
|
||||
@@ -129,24 +103,14 @@ void downloadThread::downloadTorrentUrl(QString url){
|
||||
QNetworkReply* downloadThread::downloadUrl(QString url){
|
||||
// Update proxy settings
|
||||
applyProxySettings();
|
||||
// Load cookies
|
||||
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
|
||||
if(!host_name.isEmpty())
|
||||
loadCookies(host_name, url);
|
||||
// Process download request
|
||||
qDebug("url is %s", qPrintable(url));
|
||||
const QUrl qurl = QUrl::fromEncoded(url.toLocal8Bit());
|
||||
QNetworkRequest request(qurl);
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl::fromEncoded(url.toLocal8Bit()));
|
||||
// Spoof Firefox 3.5 user agent to avoid
|
||||
// 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");
|
||||
qDebug("Downloading %s...", request.url().toEncoded().data());
|
||||
qDebug("%d cookies for this URL", networkManager.cookieJar()->cookiesForUrl(url).size());
|
||||
for(int i=0; i<networkManager.cookieJar()->cookiesForUrl(url).size(); ++i) {
|
||||
qDebug("%s=%s", networkManager.cookieJar()->cookiesForUrl(url).at(i).name().data(), networkManager.cookieJar()->cookiesForUrl(url).at(i).value().data());
|
||||
qDebug("Domain: %s, Path: %s", qPrintable(networkManager.cookieJar()->cookiesForUrl(url).at(i).domain()), qPrintable(networkManager.cookieJar()->cookiesForUrl(url).at(i).path()));
|
||||
}
|
||||
return networkManager.get(request);
|
||||
qDebug("Downloading %s...", qPrintable(request.url().toString()));
|
||||
return networkManager->get(request);
|
||||
}
|
||||
|
||||
void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
@@ -170,7 +134,7 @@ void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
||||
|
||||
void downloadThread::applyProxySettings() {
|
||||
QNetworkProxy proxy;
|
||||
QIniSettings settings("qBittorrent", "qBittorrent");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
int intValue = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxyType"), 0).toInt();
|
||||
if(intValue > 0) {
|
||||
// Proxy enabled
|
||||
@@ -198,7 +162,7 @@ void downloadThread::applyProxySettings() {
|
||||
} else {
|
||||
proxy.setType(QNetworkProxy::NoProxy);
|
||||
}
|
||||
networkManager.setProxy(proxy);
|
||||
networkManager->setProxy(proxy);
|
||||
}
|
||||
|
||||
QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
@@ -249,11 +213,3 @@ QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
return tr("Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void downloadThread::ignoreSslErrors(QNetworkReply* reply,QList<QSslError> errors) {
|
||||
Q_UNUSED(errors)
|
||||
// Ignore all SSL errors
|
||||
reply->ignoreSslErrors();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QSslError>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
@@ -42,7 +41,7 @@ class downloadThread : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QNetworkAccessManager networkManager;
|
||||
QNetworkAccessManager *networkManager;
|
||||
QHash<QString, QString> redirect_mapping;
|
||||
|
||||
signals:
|
||||
@@ -51,6 +50,7 @@ signals:
|
||||
|
||||
public:
|
||||
downloadThread(QObject* parent);
|
||||
~downloadThread();
|
||||
QNetworkReply* downloadUrl(QString url);
|
||||
void downloadTorrentUrl(QString url);
|
||||
//void setProxy(QString IP, int port, QString username, QString password);
|
||||
@@ -58,14 +58,10 @@ public:
|
||||
protected:
|
||||
QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
void applyProxySettings();
|
||||
void loadCookies(const QString &host_name, QString url);
|
||||
|
||||
protected slots:
|
||||
void processDlFinished(QNetworkReply* reply);
|
||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void ignoreSslErrors(QNetworkReply*,QList<QSslError>);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "pluginsource.h"
|
||||
#include <QProcess>
|
||||
#include <QHeaderView>
|
||||
#include <QSettings>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
@@ -44,7 +45,7 @@
|
||||
#include <QTemporaryFile>
|
||||
|
||||
enum EngineColumns {ENGINE_NAME, ENGINE_URL, ENGINE_STATE, ENGINE_ID};
|
||||
#define UPDATE_URL "http://qbittorrent.svn.sourceforge.net/viewvc/qbittorrent/branches/v2_4_x/src/search_engine/engines/"
|
||||
#define UPDATE_URL "http://qbittorrent.svn.sourceforge.net/viewvc/qbittorrent/trunk/src/search_engine/engines/"
|
||||
|
||||
engineSelectDlg::engineSelectDlg(QWidget *parent, SupportedEngines *supported_engines) : QDialog(parent), supported_engines(supported_engines) {
|
||||
setupUi(this);
|
||||
@@ -81,13 +82,8 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
|
||||
QString file;
|
||||
foreach(file, files) {
|
||||
qDebug("dropped %s", qPrintable(file));
|
||||
#ifdef Q_WS_WIN
|
||||
file = file.replace("file:///", "");
|
||||
#else
|
||||
file = file.replace("file://", "");
|
||||
#endif
|
||||
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
downloader->downloadUrl(file);
|
||||
continue;
|
||||
}
|
||||
@@ -112,7 +108,6 @@ void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
|
||||
|
||||
void engineSelectDlg::on_updateButton_clicked() {
|
||||
// Download version file from update server on sourceforge
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
downloader->downloadUrl(QString(UPDATE_URL)+"versions.txt");
|
||||
}
|
||||
|
||||
@@ -130,17 +125,18 @@ void engineSelectDlg::toggleEngineState(QTreeWidgetItem *item, int) {
|
||||
|
||||
void engineSelectDlg::displayContextMenu(const QPoint&) {
|
||||
QMenu myContextMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
|
||||
bool has_enable = false, has_disable = false;
|
||||
QTreeWidgetItem *item;
|
||||
foreach(item, items) {
|
||||
QString id = item->text(ENGINE_ID);
|
||||
if(supported_engines->value(id)->isEnabled() && !has_disable) {
|
||||
if(supported_engines->value(id)->isEnabled() and !has_disable) {
|
||||
myContextMenu.addAction(actionDisable);
|
||||
has_disable = true;
|
||||
}
|
||||
if(!supported_engines->value(id)->isEnabled() && !has_enable) {
|
||||
if(!supported_engines->value(id)->isEnabled() and !has_enable) {
|
||||
myContextMenu.addAction(actionEnable);
|
||||
has_enable = true;
|
||||
}
|
||||
@@ -269,8 +265,7 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
||||
if(QFile::exists(dest_path)) {
|
||||
// Backup in case install fails
|
||||
QFile::copy(dest_path, dest_path+".bak");
|
||||
misc::safeRemove(dest_path);
|
||||
misc::safeRemove(dest_path+"c");
|
||||
QFile::remove(dest_path);
|
||||
update = true;
|
||||
}
|
||||
// Copy the plugin
|
||||
@@ -281,22 +276,22 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
||||
if(!supported_engines->contains(plugin_name)) {
|
||||
if(update) {
|
||||
// Remove broken file
|
||||
misc::safeRemove(dest_path);
|
||||
QFile::remove(dest_path);
|
||||
// restore backup
|
||||
QFile::copy(dest_path+".bak", dest_path);
|
||||
misc::safeRemove(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));
|
||||
return;
|
||||
} else {
|
||||
// Remove broken file
|
||||
misc::safeRemove(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));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Install was successful, remove backup
|
||||
if(update) {
|
||||
misc::safeRemove(dest_path+".bak");
|
||||
QFile::remove(dest_path+".bak");
|
||||
}
|
||||
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));
|
||||
@@ -355,10 +350,8 @@ void engineSelectDlg::askForPluginUrl() {
|
||||
QString url = QInputDialog::getText(this, tr("New search engine plugin URL"),
|
||||
tr("URL:"), QLineEdit::Normal,
|
||||
"http://", &ok);
|
||||
if (ok && !url.isEmpty()) {
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
if (ok && !url.isEmpty())
|
||||
downloader->downloadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void engineSelectDlg::askForLocalPlugin() {
|
||||
@@ -403,7 +396,6 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
|
||||
if(isUpdateNeeded(plugin_name, version)) {
|
||||
qDebug("Plugin: %s is outdated", qPrintable(plugin_name));
|
||||
// Downloading update
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
downloader->downloadUrl(UPDATE_URL+plugin_name+".py");
|
||||
//downloader->downloadUrl(UPDATE_URL+plugin_name+".png");
|
||||
updated = true;
|
||||
@@ -414,7 +406,7 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
|
||||
// Close file
|
||||
versions.close();
|
||||
// Clean up tmp file
|
||||
misc::safeRemove(versions_file);
|
||||
QFile::remove(versions_file);
|
||||
if(file_correct && !updated) {
|
||||
QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("All your plugins are already up to date."));
|
||||
}
|
||||
@@ -422,7 +414,6 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
|
||||
}
|
||||
|
||||
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
qDebug("engineSelectDlg received %s", qPrintable(url));
|
||||
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
||||
// Icon downloaded
|
||||
@@ -444,27 +435,26 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
|
||||
}
|
||||
}
|
||||
// Delete tmp file
|
||||
misc::safeRemove(filePath);
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
if(url.endsWith("versions.txt")) {
|
||||
if(!parseVersionsFile(filePath)) {
|
||||
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
|
||||
}
|
||||
misc::safeRemove(filePath);
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
if(url.endsWith(".py", Qt::CaseInsensitive)) {
|
||||
QString plugin_name = url.split('/').last();
|
||||
plugin_name.replace(".py", "");
|
||||
installPlugin(filePath, plugin_name);
|
||||
misc::safeRemove(filePath);
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
|
||||
setCursor(QCursor(Qt::ArrowCursor));
|
||||
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
||||
qDebug("Could not download favicon: %s, reason: %s", qPrintable(url), qPrintable(reason));
|
||||
return;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include "eventmanager.h"
|
||||
#include "bittorrent.h"
|
||||
#include "scannedfoldersmodel.h"
|
||||
@@ -38,7 +37,6 @@
|
||||
//#include "proplistdelegate.h"
|
||||
#include "torrentpersistentdata.h"
|
||||
#include <QDebug>
|
||||
#include <QTranslator>
|
||||
|
||||
EventManager::EventManager(QObject *parent, Bittorrent *BTSession)
|
||||
: QObject(parent), BTSession(BTSession)
|
||||
@@ -62,7 +60,7 @@ QList<QVariantMap> EventManager::getPropTrackersInfo(QString hash) const {
|
||||
tracker["url"] = tracker_url;
|
||||
TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||
QString error_message = data.last_message.trimmed();
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
#ifdef LIBTORRENT_0_15
|
||||
if(it->verified) {
|
||||
tracker["status"] = tr("Working");
|
||||
} else {
|
||||
@@ -106,7 +104,7 @@ QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
|
||||
int i=0;
|
||||
for(fi=t.begin_files(); fi != t.end_files(); fi++) {
|
||||
QVariantMap file;
|
||||
QString path = QDir::cleanPath(misc::toQStringU(fi->path.string()));
|
||||
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
|
||||
QString name = path.split('/').last();
|
||||
file["name"] = name;
|
||||
file["size"] = misc::friendlyUnit((double)fi->size);
|
||||
@@ -115,8 +113,6 @@ QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
|
||||
else
|
||||
file["progress"] = 1.; // Empty file...
|
||||
file["priority"] = priorities[i];
|
||||
if(i == 0)
|
||||
file["is_seed"] = h.is_seed();
|
||||
files << file;
|
||||
++i;
|
||||
}
|
||||
@@ -125,20 +121,8 @@ QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
|
||||
|
||||
void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
// UI
|
||||
if(m.contains("locale")) {
|
||||
QString locale = m["locale"].toString();
|
||||
if(Preferences::getLocale() != locale) {
|
||||
QTranslator *translator = new QTranslator;
|
||||
if(translator->load(QString::fromUtf8(":/lang/qbittorrent_") + locale)){
|
||||
qDebug("%s locale recognized, using translation.", qPrintable(locale));
|
||||
}else{
|
||||
qDebug("%s locale unrecognized, using default (en_GB).", qPrintable(locale));
|
||||
}
|
||||
qApp->installTranslator(translator);
|
||||
}
|
||||
|
||||
Preferences::setLocale(locale);
|
||||
}
|
||||
if(m.contains("locale"))
|
||||
Preferences::setLocale(m["locale"].toString());
|
||||
// Downloads
|
||||
if(m.contains("save_path"))
|
||||
Preferences::setSavePath(m["save_path"].toString());
|
||||
@@ -147,11 +131,7 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
if(m.contains("temp_path"))
|
||||
Preferences::setTempPath(m["temp_path"].toString());
|
||||
if(m.contains("scan_dirs") && m.contains("download_in_scan_dirs")) {
|
||||
QVariantList download_at_path_tmp = m["download_in_scan_dirs"].toList();
|
||||
QList<bool> download_at_path;
|
||||
foreach(QVariant var, download_at_path_tmp) {
|
||||
download_at_path << var.toBool();
|
||||
}
|
||||
QVariantList download_at_path = m["download_in_scan_dirs"].toList();
|
||||
QStringList old_folders = Preferences::getScanDirs();
|
||||
QStringList new_folders = m["scan_dirs"].toStringList();
|
||||
if(download_at_path.size() == new_folders.size()) {
|
||||
@@ -165,10 +145,9 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
}
|
||||
int i = 0;
|
||||
foreach(const QString &new_folder, new_folders) {
|
||||
qDebug("New watched folder: %s", qPrintable(new_folder));
|
||||
// Update new folders
|
||||
if(!old_folders.contains(new_folder)) {
|
||||
BTSession->getScanFoldersModel()->addPath(new_folder, download_at_path.at(i));
|
||||
BTSession->getScanFoldersModel()->addPath(new_folder, download_at_path.at(i).toBool());
|
||||
}
|
||||
++i;
|
||||
}
|
||||
@@ -176,16 +155,6 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
}
|
||||
if(m.contains("export_dir"))
|
||||
Preferences::setExportDir(m["export_dir"].toString());
|
||||
if(m.contains("mail_notification_enabled"))
|
||||
Preferences::setMailNotificationEnabled(m["mail_notification_enabled"].toBool());
|
||||
if(m.contains("mail_notification_email"))
|
||||
Preferences::setMailNotificationEmail(m["mail_notification_email"].toString());
|
||||
if(m.contains("mail_notification_smtp"))
|
||||
Preferences::setMailNotificationSMTP(m["mail_notification_smtp"].toString());
|
||||
if(m.contains("autorun_enabled"))
|
||||
Preferences::setAutoRunEnabled(m["autorun_enabled"].toBool());
|
||||
if(m.contains("autorun_program"))
|
||||
Preferences::setAutoRunProgram(m["autorun_program"].toString());
|
||||
if(m.contains("preallocate_all"))
|
||||
Preferences::preAllocateAllFiles(m["preallocate_all"].toBool());
|
||||
if(m.contains("queueing_enabled"))
|
||||
@@ -196,7 +165,7 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
Preferences::setMaxActiveTorrents(m["max_active_torrents"].toInt());
|
||||
if(m.contains("max_active_uploads"))
|
||||
Preferences::setMaxActiveUploads(m["max_active_uploads"].toInt());
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
#ifdef LIBTORRENT_0_15
|
||||
if(m.contains("incomplete_files_ext"))
|
||||
Preferences::useIncompleteFilesExtension(m["incomplete_files_ext"].toBool());
|
||||
#endif
|
||||
@@ -231,6 +200,12 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
Preferences::setLSDEnabled(m["lsd"].toBool());
|
||||
if(m.contains("encryption"))
|
||||
Preferences::setEncryptionSetting(m["encryption"].toInt());
|
||||
if(m.contains("peer_id"))
|
||||
Preferences::setPeerID(m["peer_id"].toString());
|
||||
if(m.contains("peer_version"))
|
||||
Preferences::setClientVersion(m["peer_version"].toString());
|
||||
if(m.contains("peer_build"))
|
||||
Preferences::setClientBuild(m["peer_build"].toString());
|
||||
// Proxy
|
||||
if(m.contains("proxy_type"))
|
||||
Preferences::setPeerProxyType(m["proxy_type"].toInt());
|
||||
@@ -281,24 +256,15 @@ QVariantMap EventManager::getGlobalPreferences() const {
|
||||
data["temp_path_enabled"] = Preferences::isTempPathEnabled();
|
||||
data["temp_path"] = Preferences::getTempPath();
|
||||
data["scan_dirs"] = Preferences::getScanDirs();
|
||||
QVariantList var_list;
|
||||
foreach(bool b, Preferences::getDownloadInScanDirs()) {
|
||||
var_list << b;
|
||||
}
|
||||
data["download_in_scan_dirs"] = var_list;
|
||||
data["download_in_scan_dirs"] = Preferences::getDownloadInScanDirs();
|
||||
data["export_dir_enabled"] = Preferences::isTorrentExportEnabled();
|
||||
data["export_dir"] = Preferences::getExportDir();
|
||||
data["mail_notification_enabled"] = Preferences::isMailNotificationEnabled();
|
||||
data["mail_notification_email"] = Preferences::getMailNotificationEmail();
|
||||
data["mail_notification_smtp"] = Preferences::getMailNotificationSMTP();
|
||||
data["autorun_enabled"] = Preferences::isAutoRunEnabled();
|
||||
data["autorun_program"] = Preferences::getAutoRunProgram();
|
||||
data["preallocate_all"] = Preferences::preAllocateAllFiles();
|
||||
data["queueing_enabled"] = Preferences::isQueueingSystemEnabled();
|
||||
data["max_active_downloads"] = Preferences::getMaxActiveDownloads();
|
||||
data["max_active_torrents"] = Preferences::getMaxActiveTorrents();
|
||||
data["max_active_uploads"] = Preferences::getMaxActiveUploads();
|
||||
#if LIBTORRENT_VERSION_MINOR > 14
|
||||
#ifdef LIBTORRENT_0_15
|
||||
data["incomplete_files_ext"] = Preferences::useIncompleteFilesExtension();
|
||||
#endif
|
||||
// Connection
|
||||
@@ -317,6 +283,9 @@ QVariantMap EventManager::getGlobalPreferences() const {
|
||||
data["pex"] = Preferences::isPeXEnabled();
|
||||
data["lsd"] = Preferences::isLSDEnabled();
|
||||
data["encryption"] = Preferences::getEncryptionSetting();
|
||||
data["peer_id"] = Preferences::getPeerID();
|
||||
data["peer_version"] = Preferences::getClientVersion();
|
||||
data["peer_build"] = Preferences::getClientBuild();
|
||||
// Proxy
|
||||
data["proxy_type"] = Preferences::getPeerProxyType();
|
||||
data["proxy_ip"] = Preferences::getPeerProxyIp();
|
||||
@@ -395,14 +364,10 @@ void EventManager::modifiedTorrent(QTorrentHandle h)
|
||||
QVariantMap event;
|
||||
event["eta"] = QVariant(QString::fromUtf8("∞"));
|
||||
if(h.is_paused()) {
|
||||
if(h.has_error()) {
|
||||
event["state"] = QVariant("error");
|
||||
} else {
|
||||
if(h.is_seed())
|
||||
event["state"] = QVariant("pausedUP");
|
||||
else
|
||||
event["state"] = QVariant("pausedDL");
|
||||
}
|
||||
if(h.is_seed())
|
||||
event["state"] = QVariant("pausedUP");
|
||||
else
|
||||
event["state"] = QVariant("pausedDL");
|
||||
} else {
|
||||
if(BTSession->isQueueingEnabled() && h.is_queued()) {
|
||||
if(h.is_seed())
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define FEEDDOWNLOADER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QInputDialog>
|
||||
@@ -44,7 +45,6 @@
|
||||
|
||||
#include "bittorrent.h"
|
||||
#include "ui_feeddownloader.h"
|
||||
#include "qinisettings.h"
|
||||
|
||||
#if QT_VERSION >= 0x040500
|
||||
#include <QHash>
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
|
||||
QStringList getNotMatchingTokens() const {
|
||||
QString notmatching = this->value("not", "").toString();
|
||||
return notmatching.split(QRegExp("[\\s|]"));
|
||||
return notmatching.split(" ");
|
||||
}
|
||||
|
||||
QString getNotMatchingTokens_str() const {
|
||||
@@ -168,20 +168,20 @@ public:
|
||||
}
|
||||
|
||||
bool isDownloadingEnabled() const {
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
return feeds_w_downloader.value(feed_url, false).toBool();
|
||||
}
|
||||
|
||||
void setDownloadingEnabled(bool enabled) {
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
feeds_w_downloader[feed_url] = enabled;
|
||||
qBTRSS.setValue("downloader_on", feeds_w_downloader);
|
||||
}
|
||||
|
||||
static FeedFilters getFeedFilters(QString url) {
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||
return FeedFilters(url, all_feeds_filters.value(url, QHash<QString, QVariant>()).toHash());
|
||||
}
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
}
|
||||
|
||||
void save() {
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
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());
|
||||
all_feeds_filters[feed_url] = *this;
|
||||
@@ -297,7 +297,7 @@ protected slots:
|
||||
default_path = QDir::homePath();
|
||||
}
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
|
||||
if(!dir.isNull() && QDir(dir).exists()) {
|
||||
if(!dir.isNull() and QDir(dir).exists()) {
|
||||
savepath_line->setText(dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#define FILESYSTEMWATCHER_H
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QDir>
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
#include <QTimer>
|
||||
#include <QDir>
|
||||
#include <QPointer>
|
||||
#include <QStringList>
|
||||
#include <QSet>
|
||||
@@ -19,8 +19,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#ifndef CIFS_MAGIC_NUMBER
|
||||
#define CIFS_MAGIC_NUMBER 0xFF534D42
|
||||
#endif
|
||||
@@ -29,9 +27,6 @@
|
||||
#define NFS_SUPER_MAGIC 0x6969
|
||||
#endif
|
||||
|
||||
const int WATCH_INTERVAL = 10000; // 10 sec
|
||||
const int MAX_PARTIAL_RETRIES = 5;
|
||||
|
||||
/*
|
||||
* Subclassing QFileSystemWatcher in order to support Network File
|
||||
* System watching (NFS, CIFS) on Linux and Mac OS.
|
||||
@@ -44,14 +39,11 @@ private:
|
||||
QList<QDir> watched_folders;
|
||||
QPointer<QTimer> watch_timer;
|
||||
#endif
|
||||
QStringList m_filters;
|
||||
// Partial torrents
|
||||
QHash<QString, int> m_partialTorrents;
|
||||
QPointer<QTimer> m_partialTorrentTimer;
|
||||
QStringList filters;
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
private:
|
||||
static bool isNetworkFileSystem(QString path) {
|
||||
protected:
|
||||
bool isNetworkFileSystem(QString path) {
|
||||
QString file = path;
|
||||
if(!file.endsWith(QDir::separator()))
|
||||
file += QDir::separator();
|
||||
@@ -107,7 +99,7 @@ private:
|
||||
|
||||
public:
|
||||
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
||||
m_filters << "*.torrent";
|
||||
filters << "*.torrent";
|
||||
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
|
||||
}
|
||||
|
||||
@@ -116,8 +108,6 @@ public:
|
||||
if(watch_timer)
|
||||
delete watch_timer;
|
||||
#endif
|
||||
if(m_partialTorrentTimer)
|
||||
delete m_partialTorrentTimer;
|
||||
}
|
||||
|
||||
QStringList directories() const {
|
||||
@@ -147,7 +137,7 @@ public:
|
||||
if (!watch_timer) {
|
||||
watch_timer = new QTimer(this);
|
||||
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanNetworkFolders()));
|
||||
watch_timer->start(WATCH_INTERVAL); // 5 sec
|
||||
watch_timer->start(5000); // 5 sec
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
@@ -190,7 +180,6 @@ protected slots:
|
||||
}
|
||||
|
||||
void scanNetworkFolders() {
|
||||
#ifndef Q_WS_WIN
|
||||
qDebug("scanNetworkFolders() called");
|
||||
QStringList torrents;
|
||||
// Network folders scan
|
||||
@@ -203,75 +192,16 @@ protected slots:
|
||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||
emit torrentsAdded(torrents);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void processPartialTorrents() {
|
||||
QStringList no_longer_partial;
|
||||
|
||||
// Check which torrents are still partial
|
||||
foreach(const QString& torrent_path, m_partialTorrents.keys()) {
|
||||
if(!QFile::exists(torrent_path)) {
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
continue;
|
||||
}
|
||||
if(misc::isValidTorrentFile(torrent_path)) {
|
||||
no_longer_partial << torrent_path;
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
} else {
|
||||
if(m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
QFile::rename(torrent_path, torrent_path+".invalid");
|
||||
} else {
|
||||
m_partialTorrents[torrent_path]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the partial timer if necessary
|
||||
if(m_partialTorrents.empty()) {
|
||||
m_partialTorrentTimer->stop();
|
||||
m_partialTorrentTimer->deleteLater();
|
||||
qDebug("No longer any partial torrent.");
|
||||
} else {
|
||||
qDebug("Still %d partial torrents after delayed processing.", m_partialTorrents.count());
|
||||
m_partialTorrentTimer->start(WATCH_INTERVAL);
|
||||
}
|
||||
// Notify of new torrents
|
||||
if(!no_longer_partial.isEmpty())
|
||||
emit torrentsAdded(no_longer_partial);
|
||||
}
|
||||
|
||||
signals:
|
||||
void torrentsAdded(QStringList &pathList);
|
||||
|
||||
private:
|
||||
void startPartialTorrentTimer() {
|
||||
Q_ASSERT(!m_partialTorrents.isEmpty());
|
||||
if(!m_partialTorrentTimer) {
|
||||
m_partialTorrentTimer = new QTimer();
|
||||
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents()));
|
||||
m_partialTorrentTimer->setSingleShot(true);
|
||||
m_partialTorrentTimer->start(WATCH_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
|
||||
const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted);
|
||||
foreach(const QString &file, files) {
|
||||
const QString file_abspath = dir.absoluteFilePath(file);
|
||||
if(misc::isValidTorrentFile(file_abspath)) {
|
||||
torrents << file_abspath;
|
||||
} else {
|
||||
if(!m_partialTorrents.contains(file_abspath)) {
|
||||
qDebug("Partial torrent detected at: %s", qPrintable(file_abspath));
|
||||
qDebug("Delay the file's processing...");
|
||||
m_partialTorrents.insert(file_abspath, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!m_partialTorrents.empty())
|
||||
startPartialTorrentTimer();
|
||||
const QStringList &files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
foreach(const QString &file, files)
|
||||
torrents << dir.canonicalPath() + '/' + file;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <QThread>
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QRegExp>
|
||||
#include <QStringList>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/ip_filter.hpp>
|
||||
@@ -46,364 +46,373 @@ using namespace std;
|
||||
// P2B Stuff
|
||||
#include <string.h>
|
||||
#ifdef Q_WS_WIN
|
||||
#include <Winsock2.h>
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
// End of P2B stuff
|
||||
|
||||
class FilterParserThread : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
session *s;
|
||||
ip_filter filter;
|
||||
bool abort;
|
||||
QString filePath;
|
||||
|
||||
protected:
|
||||
QString cleanupIPAddress(QString _ip) {
|
||||
QHostAddress ip(_ip.trimmed());
|
||||
if(ip.isNull()) {
|
||||
return QString();
|
||||
}
|
||||
return ip.toString();
|
||||
}
|
||||
|
||||
void run(){
|
||||
qDebug("Processing filter file");
|
||||
if(filePath.endsWith(".dat", Qt::CaseInsensitive)) {
|
||||
// eMule DAT file
|
||||
parseDATFilterFile(filePath);
|
||||
} else {
|
||||
if(filePath.endsWith(".p2p", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2p file
|
||||
parseP2PFilterFile(filePath);
|
||||
private:
|
||||
session *s;
|
||||
ip_filter filter;
|
||||
bool abort;
|
||||
QString filePath;
|
||||
|
||||
protected:
|
||||
void run(){
|
||||
qDebug("Processing filter file");
|
||||
if(filePath.endsWith(".dat", Qt::CaseInsensitive)) {
|
||||
// eMule DAT file
|
||||
parseDATFilterFile(filePath);
|
||||
} else {
|
||||
if(filePath.endsWith(".p2b", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2b file
|
||||
parseP2BFilterFile(filePath);
|
||||
if(filePath.endsWith(".p2p", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2p file
|
||||
parseP2PFilterFile(filePath);
|
||||
} else {
|
||||
// Default: eMule DAT format
|
||||
parseDATFilterFile(filePath);
|
||||
if(filePath.endsWith(".p2b", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2b file
|
||||
parseP2BFilterFile(filePath);
|
||||
} else {
|
||||
// Default: eMule DAT format
|
||||
parseDATFilterFile(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
s->set_ip_filter(filter);
|
||||
qDebug("IP Filter thread: finished parsing, filter applied");
|
||||
}
|
||||
s->set_ip_filter(filter);
|
||||
qDebug("IP Filter thread: finished parsing, filter applied");
|
||||
}
|
||||
|
||||
public:
|
||||
FilterParserThread(QObject* parent, session *s) : QThread(parent), s(s), abort(false) {
|
||||
|
||||
}
|
||||
|
||||
~FilterParserThread(){
|
||||
abort = true;
|
||||
wait();
|
||||
}
|
||||
|
||||
// Parser for eMule ip filter in DAT format
|
||||
void parseDATFilterFile(QString filePath) {
|
||||
QFile file(filePath);
|
||||
if (file.exists()){
|
||||
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return;
|
||||
}
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine();
|
||||
// Ignoring empty lines
|
||||
line = line.trimmed();
|
||||
if(line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if(line.startsWith('#') || line.startsWith("//")) continue;
|
||||
|
||||
// Line should be splitted by commas
|
||||
QList<QByteArray> partsList = line.split(',');
|
||||
const uint nbElem = partsList.size();
|
||||
|
||||
// IP Range should be splitted by a dash
|
||||
QList<QByteArray> IPs = partsList.first().split('-');
|
||||
if(IPs.size() != 2) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Line was %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
const QString strStartIP = cleanupIPAddress(IPs.at(0));
|
||||
if(strStartIP.isEmpty()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec);
|
||||
if(ec) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
const QString strEndIP = cleanupIPAddress(IPs.at(1));
|
||||
if(strEndIP.isEmpty()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec);
|
||||
if(ec) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP));
|
||||
continue;
|
||||
}
|
||||
if(startAddr.is_v4() != endAddr.is_v4()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("One IP is IPv4 and the other is IPv6!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there is an access value (apparently not mandatory)
|
||||
int nbAccess = 0;
|
||||
if(nbElem > 1) {
|
||||
// There is possibly one
|
||||
nbAccess = partsList.at(1).trimmed().toInt();
|
||||
}
|
||||
|
||||
if(nbAccess > 127) {
|
||||
// Ignoring this rule because access value is too high
|
||||
continue;
|
||||
}
|
||||
// Now Add to the filter
|
||||
try {
|
||||
filter.add_rule(startAddr, endAddr, ip_filter::blocked);
|
||||
}catch(exception){
|
||||
qDebug("Bad line in filter file, avoided crash...");
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
public:
|
||||
FilterParserThread(QObject* parent, session *s) : QThread(parent), s(s), abort(false) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
void parseP2PFilterFile(QString filePath) {
|
||||
QFile file(filePath);
|
||||
QStringList IP;
|
||||
if (file.exists()){
|
||||
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return;
|
||||
}
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine().trimmed();
|
||||
if(line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if(line.startsWith('#') || line.startsWith("//")) continue;
|
||||
// Line is splitted by :
|
||||
QList<QByteArray> partsList = line.split(':');
|
||||
if(partsList.size() < 2){
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
// Get IP range
|
||||
QList<QByteArray> IPs = partsList.last().split('-');
|
||||
if(IPs.size() != 2) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
boost::system::error_code ec;
|
||||
QString strStartIP = cleanupIPAddress(IPs.at(0));
|
||||
if(strStartIP.isEmpty()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec);
|
||||
if(ec) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
QString strEndIP = cleanupIPAddress(IPs.at(1));
|
||||
if(strEndIP.isEmpty()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("End IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec);
|
||||
if(ec) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("End IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
if(startAddr.is_v4() != endAddr.is_v4()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
filter.add_rule(startAddr, endAddr, ip_filter::blocked);
|
||||
} catch(std::exception&) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
int getlineInStream(QDataStream& stream, string& name, char delim) {
|
||||
char c;
|
||||
int total_read = 0;
|
||||
int read;
|
||||
do {
|
||||
read = stream.readRawData(&c, 1);
|
||||
total_read += read;
|
||||
if(read > 0) {
|
||||
if(c != delim) {
|
||||
name += c;
|
||||
} else {
|
||||
// Delim found
|
||||
return total_read;
|
||||
}
|
||||
}
|
||||
} while(read > 0);
|
||||
return total_read;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
void parseP2BFilterFile(QString filePath) {
|
||||
QFile file(filePath);
|
||||
if (file.exists()){
|
||||
if(!file.open(QIODevice::ReadOnly)){
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return;
|
||||
}
|
||||
QDataStream stream(&file);
|
||||
// Read header
|
||||
char buf[7];
|
||||
unsigned char version;
|
||||
if(
|
||||
!stream.readRawData(buf, sizeof(buf)) ||
|
||||
memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) ||
|
||||
!stream.readRawData((char*)&version, sizeof(version))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(version==1 || version==2) {
|
||||
qDebug ("p2b version 1 or 2");
|
||||
unsigned int start, end;
|
||||
|
||||
string name;
|
||||
while(getlineInStream(stream, name, '\0') && !abort) {
|
||||
if(
|
||||
!stream.readRawData((char*)&start, sizeof(start)) ||
|
||||
!stream.readRawData((char*)&end, sizeof(end))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
address_v4 first(ntohl(start));
|
||||
address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(first, last, ip_filter::blocked);
|
||||
}
|
||||
}
|
||||
else if(version==3) {
|
||||
qDebug ("p2b version 3");
|
||||
unsigned int namecount;
|
||||
if(!stream.readRawData((char*)&namecount, sizeof(namecount))) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
namecount=ntohl(namecount);
|
||||
// Reading names although, we don't really care about them
|
||||
for(unsigned int i=0; i<namecount; i++) {
|
||||
string name;
|
||||
if(!getlineInStream(stream, name, '\0')) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
if(abort) return;
|
||||
}
|
||||
// Reading the ranges
|
||||
unsigned int rangecount;
|
||||
if(!stream.readRawData((char*)&rangecount, sizeof(rangecount))) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
rangecount=ntohl(rangecount);
|
||||
|
||||
unsigned int name, start, end;
|
||||
|
||||
for(unsigned int i=0; i<rangecount; i++) {
|
||||
if(
|
||||
!stream.readRawData((char*)&name, sizeof(name)) ||
|
||||
!stream.readRawData((char*)&start, sizeof(start)) ||
|
||||
!stream.readRawData((char*)&end, sizeof(end))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
address_v4 first(ntohl(start));
|
||||
address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(first, last, ip_filter::blocked);
|
||||
if(abort) return;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Process ip filter file
|
||||
// Supported formats:
|
||||
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
||||
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
||||
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
||||
void processFilterFile(QString _filePath){
|
||||
// First, import current filter
|
||||
filter = s->get_ip_filter();
|
||||
if(isRunning()) {
|
||||
// Already parsing a filter, abort first
|
||||
|
||||
~FilterParserThread(){
|
||||
abort = true;
|
||||
wait();
|
||||
}
|
||||
abort = false;
|
||||
filePath = _filePath;
|
||||
// Run it
|
||||
start();
|
||||
}
|
||||
|
||||
static void processFilterList(session *s, QStringList IPs) {
|
||||
// First, import current filter
|
||||
ip_filter filter = s->get_ip_filter();
|
||||
foreach(const QString &ip, IPs) {
|
||||
qDebug("Manual ban of peer %s", ip.toLocal8Bit().constData());
|
||||
boost::system::error_code ec;
|
||||
address_v4 addr = address_v4::from_string(ip.toLocal8Bit().constData(), ec);
|
||||
Q_ASSERT(!ec);
|
||||
if(!ec)
|
||||
filter.add_rule(addr, addr, ip_filter::blocked);
|
||||
|
||||
// Parser for eMule ip filter in DAT format
|
||||
void parseDATFilterFile(QString filePath) {
|
||||
const QRegExp is_ipv6(QString::fromUtf8("^[0-9a-f]{4}(:[0-9a-f]{4}){7}$"), Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
const QRegExp is_ipv4(QString::fromUtf8("^(([0-1]?[0-9]?[0-9])|(2[0-4][0-9])|(25[0-5]))(\\.(([0-1]?[0-9]?[0-9])|(2[0-4][0-9])|(25[0-5]))){3}$"), Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
QString strStartIP, strEndIP;
|
||||
bool IPv4 = true;
|
||||
QFile file(filePath);
|
||||
if (file.exists()){
|
||||
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return;
|
||||
}
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine();
|
||||
// Ignoring empty lines
|
||||
line = line.trimmed();
|
||||
if(line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if(line.startsWith('#') || line.startsWith("//")) continue;
|
||||
// Line is not commented
|
||||
QList<QByteArray> partsList = line.split(',');
|
||||
unsigned int nbElem = partsList.size();
|
||||
// IP Range can be splitted by a dash or a comma...
|
||||
// Check if there is a dash in first part
|
||||
QByteArray firstPart = partsList.at(0);
|
||||
int nbAccess = 0;
|
||||
if(firstPart.contains('-')) {
|
||||
// Range is splitted by a dash
|
||||
QList<QByteArray> IPs = firstPart.split('-');
|
||||
if(IPs.size() != 2) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
strStartIP = IPs.at(0).trimmed();
|
||||
strEndIP = IPs.at(1).trimmed();
|
||||
// Check if IPs are correct
|
||||
if(strStartIP.contains(is_ipv4) && strEndIP.contains(is_ipv4)) {
|
||||
IPv4 = true;
|
||||
} else {
|
||||
if(strStartIP.contains(is_ipv6) && strEndIP.contains(is_ipv6)) {
|
||||
IPv4 = false;
|
||||
} else {
|
||||
// Could not determine IP format
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check if there is an access value (apparently not mandatory)
|
||||
if(nbElem > 1) {
|
||||
// There is possibly one
|
||||
bool ok;
|
||||
nbAccess = partsList.at(1).trimmed().toInt(&ok);
|
||||
if(!ok){
|
||||
nbAccess = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Range is probably splitted by a comma
|
||||
unsigned int nbElem = partsList.size();
|
||||
if(nbElem > 1) {
|
||||
strStartIP = firstPart.trimmed();
|
||||
strEndIP = partsList.at(1).trimmed();
|
||||
// Check if IPs are correct
|
||||
if(strStartIP.contains(is_ipv4) && strEndIP.contains(is_ipv4)) {
|
||||
IPv4 = true;
|
||||
} else {
|
||||
if(strStartIP.contains(is_ipv6) && strEndIP.contains(is_ipv6)) {
|
||||
IPv4 = false;
|
||||
} else {
|
||||
// Could not determine IP format
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check if there is an access value (apparently not mandatory)
|
||||
if(nbElem > 2) {
|
||||
// There is possibly one
|
||||
bool ok;
|
||||
nbAccess = partsList.at(2).trimmed().toInt(&ok);
|
||||
if(!ok){
|
||||
nbAccess = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nbAccess > 127) {
|
||||
// Ignoring this rule because access value is too high
|
||||
continue;
|
||||
}
|
||||
// Now Add to the filter
|
||||
QStringList IP;
|
||||
try {
|
||||
if(IPv4) {
|
||||
//IPv4 addresses
|
||||
IP = strStartIP.split('.');
|
||||
if(IP.size() != 4)
|
||||
throw exception();
|
||||
address_v4 start((IP.at(0).toUInt() << 24) + (IP.at(1).toUInt() << 16) + (IP.at(2).toUInt() << 8) + IP.at(3).toUInt());
|
||||
IP = strEndIP.split('.');
|
||||
if(IP.size() != 4)
|
||||
throw exception();
|
||||
address_v4 last((IP.at(0).toUInt() << 24) + (IP.at(1).toUInt() << 16) + (IP.at(2).toUInt() << 8) + IP.at(3).toUInt());
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(start, last, ip_filter::blocked);
|
||||
} else {
|
||||
// IPv6, ex : 1fff:0000:0a88:85a3:0000:0000:ac1f:8001
|
||||
IP = strStartIP.split(':');
|
||||
address_v6 start = address_v6::from_string(strStartIP.remove(':', 0).toLocal8Bit().data());
|
||||
IP = strEndIP.split(':');
|
||||
address_v6 last = address_v6::from_string(strEndIP.remove(':', 0).toLocal8Bit().data());
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(start, last, ip_filter::blocked);
|
||||
}
|
||||
}catch(exception){
|
||||
qDebug("Bad line in filter file, avoided crash...");
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
void parseP2PFilterFile(QString filePath) {
|
||||
const QRegExp is_ipv4(QString::fromUtf8("^(([0-1]?[0-9]?[0-9])|(2[0-4][0-9])|(25[0-5]))(\\.(([0-1]?[0-9]?[0-9])|(2[0-4][0-9])|(25[0-5]))){3}$"), Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
QFile file(filePath);
|
||||
QStringList IP;
|
||||
if (file.exists()){
|
||||
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return;
|
||||
}
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine();
|
||||
// Ignoring empty lines
|
||||
line = line.trimmed();
|
||||
if(line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if(line.startsWith('#') || line.startsWith("//")) continue;
|
||||
// Line is not commented
|
||||
QList<QByteArray> partsList = line.split(':');
|
||||
if(partsList.size() < 2){
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
// Get IP range
|
||||
QList<QByteArray> IPs = partsList.last().split('-');
|
||||
if(IPs.size() != 2) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
QString strStartIP = IPs.at(0).trimmed();
|
||||
QString strEndIP = IPs.at(1).trimmed();
|
||||
// Check IPs format (IPv4 only)
|
||||
if(strStartIP.contains(is_ipv4) && strEndIP.contains(is_ipv4)) {
|
||||
// IPv4
|
||||
IP = strStartIP.split('.');
|
||||
address_v4 start((IP.at(0).toUInt() << 24) + (IP.at(1).toUInt() << 16) + (IP.at(2).toUInt() << 8) + IP.at(3).toUInt());
|
||||
IP = strEndIP.split('.');
|
||||
address_v4 last((IP.at(0).toUInt() << 24) + (IP.at(1).toUInt() << 16) + (IP.at(2).toUInt() << 8) + IP.at(3).toUInt());
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(start, last, ip_filter::blocked);
|
||||
} else {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
int getlineInStream(QDataStream& stream, string& name, char delim) {
|
||||
char c;
|
||||
int total_read = 0;
|
||||
int read;
|
||||
do {
|
||||
read = stream.readRawData(&c, 1);
|
||||
total_read += read;
|
||||
if(read > 0) {
|
||||
if(c != delim) {
|
||||
name += c;
|
||||
} else {
|
||||
// Delim found
|
||||
return total_read;
|
||||
}
|
||||
}
|
||||
} while(read > 0);
|
||||
return total_read;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
void parseP2BFilterFile(QString filePath) {
|
||||
QFile file(filePath);
|
||||
if (file.exists()){
|
||||
if(!file.open(QIODevice::ReadOnly)){
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return;
|
||||
}
|
||||
QDataStream stream(&file);
|
||||
// Read header
|
||||
char buf[7];
|
||||
unsigned char version;
|
||||
if(
|
||||
!stream.readRawData(buf, sizeof(buf)) ||
|
||||
memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) ||
|
||||
!stream.readRawData((char*)&version, sizeof(version))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(version==1 || version==2) {
|
||||
qDebug ("p2b version 1 or 2");
|
||||
unsigned int start, end;
|
||||
|
||||
string name;
|
||||
while(getlineInStream(stream, name, '\0') && !abort) {
|
||||
if(
|
||||
!stream.readRawData((char*)&start, sizeof(start)) ||
|
||||
!stream.readRawData((char*)&end, sizeof(end))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
address_v4 first(ntohl(start));
|
||||
address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(first, last, ip_filter::blocked);
|
||||
}
|
||||
}
|
||||
else if(version==3) {
|
||||
qDebug ("p2b version 3");
|
||||
unsigned int namecount;
|
||||
if(!stream.readRawData((char*)&namecount, sizeof(namecount))) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
namecount=ntohl(namecount);
|
||||
// Reading names although, we don't really care about them
|
||||
for(unsigned int i=0; i<namecount; i++) {
|
||||
string name;
|
||||
if(!getlineInStream(stream, name, '\0')) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
if(abort) return;
|
||||
}
|
||||
// Reading the ranges
|
||||
unsigned int rangecount;
|
||||
if(!stream.readRawData((char*)&rangecount, sizeof(rangecount))) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
rangecount=ntohl(rangecount);
|
||||
|
||||
unsigned int name, start, end;
|
||||
|
||||
for(unsigned int i=0; i<rangecount; i++) {
|
||||
if(
|
||||
!stream.readRawData((char*)&name, sizeof(name)) ||
|
||||
!stream.readRawData((char*)&start, sizeof(start)) ||
|
||||
!stream.readRawData((char*)&end, sizeof(end))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
address_v4 first(ntohl(start));
|
||||
address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
filter.add_rule(first, last, ip_filter::blocked);
|
||||
if(abort) return;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Process ip filter file
|
||||
// Supported formats:
|
||||
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
||||
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
||||
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
||||
void processFilterFile(QString _filePath){
|
||||
// First, import current filter
|
||||
filter = s->get_ip_filter();
|
||||
if(isRunning()) {
|
||||
// Already parsing a filter, abort first
|
||||
abort = true;
|
||||
wait();
|
||||
}
|
||||
abort = false;
|
||||
filePath = _filePath;
|
||||
// Run it
|
||||
start();
|
||||
}
|
||||
|
||||
static void processFilterList(session *s, QStringList IPs) {
|
||||
// First, import current filter
|
||||
ip_filter filter = s->get_ip_filter();
|
||||
foreach(const QString &ip, IPs) {
|
||||
qDebug("Manual ban of peer %s", ip.toLocal8Bit().data());
|
||||
address_v4 addr = address_v4::from_string(ip.toLocal8Bit().data());
|
||||
filter.add_rule(addr, addr, ip_filter::blocked);
|
||||
}
|
||||
s->set_ip_filter(filter);
|
||||
}
|
||||
s->set_ip_filter(filter);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
142
src/geoip.h
@@ -40,8 +40,7 @@
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
class GeoIP : public QObject {
|
||||
Q_OBJECT
|
||||
class GeoIP {
|
||||
protected:
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
static QString geoipFolder(bool embedded=false) {
|
||||
@@ -69,19 +68,13 @@ protected:
|
||||
// Create geoip folder is necessary
|
||||
QDir gfolder(geoipFolder(false));
|
||||
if(!gfolder.exists()) {
|
||||
if(!gfolder.mkpath(geoipFolder(false))) {
|
||||
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
|
||||
return;
|
||||
}
|
||||
if(!gfolder.mkpath(geoipFolder(false))) return;
|
||||
}
|
||||
// Remove destination files
|
||||
if(QFile::exists(geoipDBpath(false)))
|
||||
misc::safeRemove(geoipDBpath(false));
|
||||
QFile::remove(geoipDBpath(false));
|
||||
// Copy from executable to hard disk
|
||||
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
|
||||
if(!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
|
||||
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
|
||||
}
|
||||
QFile::copy(geoipDBpath(true), geoipDBpath(false));
|
||||
qDebug("Local Geoip database was updated");
|
||||
}
|
||||
}
|
||||
@@ -104,7 +97,7 @@ public:
|
||||
|
||||
// TODO: Support more countries
|
||||
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
static QIcon CountryISOCodeToIcon(const char* iso, QString &country_name) {
|
||||
static QIcon CountryISOCodeToIcon(char* iso) {
|
||||
switch(iso[0]) {
|
||||
case 0:
|
||||
case '-':
|
||||
@@ -112,107 +105,106 @@ public:
|
||||
//qDebug("Not returning any icon because iso is invalid: %s", iso);
|
||||
return QIcon();
|
||||
case 'A':
|
||||
if(iso[1] == 'U') { country_name = tr("Australia"); return QIcon(":/Icons/flags/australia.png"); }
|
||||
if(iso[1] == 'R') { country_name = tr("Argentina"); return QIcon(":/Icons/flags/argentina.png"); }
|
||||
if(iso[1] == 'T') { country_name = tr("Austria"); return QIcon(":/Icons/flags/austria.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("United Arab Emirates"); return QIcon(":/Icons/flags/united_arab_emirates.png"); }
|
||||
if(iso[1] == 'U') return QIcon(":/Icons/flags/australia.png");
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/argentina.png");
|
||||
if(iso[1] == 'T') return QIcon(":/Icons/flags/austria.png");
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/united_arab_emirates.png");
|
||||
break;
|
||||
case 'B':
|
||||
if(iso[1] == 'R') { country_name = tr("Brazil"); return QIcon(":/Icons/flags/brazil.png"); }
|
||||
if(iso[1] == 'G') { country_name = tr("Bulgaria"); return QIcon(":/Icons/flags/bulgaria.png"); }
|
||||
if(iso[1] == 'Y') { country_name = tr("Belarus"); return QIcon(":/Icons/flags/belarus.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("Belgium"); return QIcon(":/Icons/flags/belgium.png"); }
|
||||
if(iso[1] == 'A') { country_name = tr("Bosnia"); return QIcon(":/Icons/flags/bosnia.png"); }
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/brazil.png");
|
||||
if(iso[1] == 'G') return QIcon(":/Icons/flags/bulgaria.png");
|
||||
if(iso[1] == 'Y') return QIcon(":/Icons/flags/belarus.png");
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/belgium.png");
|
||||
if(iso[1] == 'A') return QIcon(":/Icons/flags/bosnia.png");
|
||||
break;
|
||||
case 'C':
|
||||
if(iso[1] == 'A') { country_name = tr("Canada"); return QIcon(":/Icons/flags/canada.png"); }
|
||||
if(iso[1] == 'Z') { country_name = tr("Czech Republic"); return QIcon(":/Icons/flags/czech.png"); }
|
||||
if(iso[1] == 'N') { country_name = tr("China"); return QIcon(":/Icons/flags/china.png"); }
|
||||
if(iso[1] == 'R') { country_name = tr("Costa Rica"); return QIcon(":/Icons/flags/costa_rica.png"); }
|
||||
if(iso[1] == 'H') { country_name = tr("Switzerland"); return QIcon(":/Icons/flags/suisse.png"); }
|
||||
if(iso[1] == 'A') return QIcon(":/Icons/flags/canada.png");
|
||||
if(iso[1] == 'Z') return QIcon(":/Icons/flags/czech.png");
|
||||
if(iso[1] == 'N') return QIcon(":/Icons/flags/china.png");
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/costa_rica.png");
|
||||
if(iso[1] == 'H') return QIcon(":/Icons/flags/suisse.png");
|
||||
break;
|
||||
case 'D':
|
||||
if(iso[1] == 'E') { country_name = tr("Germany"); return QIcon(":/Icons/flags/germany.png"); }
|
||||
if(iso[1] == 'K') { country_name = tr("Denmark"); return QIcon(":/Icons/flags/denmark.png"); }
|
||||
if(iso[1] == 'Z') { country_name = tr("Algeria"); return QIcon(":/Icons/flags/algeria.png"); }
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/germany.png");
|
||||
if(iso[1] == 'K') return QIcon(":/Icons/flags/denmark.png");
|
||||
if(iso[1] == 'Z') return QIcon(":/Icons/flags/algeria.png");
|
||||
break;
|
||||
case 'E':
|
||||
if(iso[1] == 'S') { country_name = tr("Spain"); return QIcon(":/Icons/flags/spain.png"); }
|
||||
if(iso[1] == 'G') { country_name = tr("Egypt"); return QIcon(":/Icons/flags/egypt.png"); }
|
||||
if(iso[1] == 'S') return QIcon(":/Icons/flags/spain.png");
|
||||
if(iso[1] == 'G') return QIcon(":/Icons/flags/egypt.png");
|
||||
break;
|
||||
case 'F':
|
||||
if(iso[1] == 'I') { country_name = tr("Finland"); return QIcon(":/Icons/flags/finland.png"); }
|
||||
if(iso[1] == 'R') { country_name = tr("France"); return QIcon(":/Icons/flags/france.png"); }
|
||||
if(iso[1] == 'I') return QIcon(":/Icons/flags/finland.png");
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/france.png");
|
||||
break;
|
||||
case 'G':
|
||||
if(iso[1] == 'B') { country_name = tr("United Kingdom"); return QIcon(":/Icons/flags/united_kingdom.png"); }
|
||||
if(iso[1] == 'R') { country_name = tr("Greece"); return QIcon(":/Icons/flags/greece.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("Georgia"); return QIcon(":/Icons/flags/georgia.png"); }
|
||||
if(iso[1] == 'B') return QIcon(":/Icons/flags/united_kingdom.png");
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/greece.png");
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/georgia.png");
|
||||
break;
|
||||
case 'H':
|
||||
if(iso[1] == 'U') { country_name = tr("Hungary"); return QIcon(":/Icons/flags/hungary.png"); }
|
||||
if(iso[1] == 'K') { country_name = tr("China"); return QIcon(":/Icons/flags/china.png"); }
|
||||
if(iso[1] == 'R') { country_name = tr("Croatia"); return QIcon(":/Icons/flags/croatia.png"); }
|
||||
if(iso[1] == 'U') return QIcon(":/Icons/flags/hungary.png");
|
||||
if(iso[1] == 'K') return QIcon(":/Icons/flags/china.png");
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/croatia.png");
|
||||
break;
|
||||
case 'I':
|
||||
if(iso[1] == 'T') { country_name = tr("Italy"); return QIcon(":/Icons/flags/italy.png"); }
|
||||
if(iso[1] == 'N') { country_name = tr("India"); return QIcon(":/Icons/flags/india.png"); }
|
||||
if(iso[1] == 'L') { country_name = tr("Israel"); return QIcon(":/Icons/flags/israel.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("Ireland"); return QIcon(":/Icons/flags/ireland.png"); }
|
||||
if(iso[1] == 'S') { country_name = tr("Iceland"); return QIcon(":/Icons/flags/iceland.png"); }
|
||||
if(iso[1] == 'D') { country_name = tr("Indonesia"); return QIcon(":/Icons/flags/indonesia.png"); }
|
||||
if(iso[1] == 'T') return QIcon(":/Icons/flags/italy.png");
|
||||
if(iso[1] == 'N') return QIcon(":/Icons/flags/india.png");
|
||||
if(iso[1] == 'L') return QIcon(":/Icons/flags/israel.png");
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/ireland.png");
|
||||
if(iso[1] == 'S') return QIcon(":/Icons/flags/iceland.png");
|
||||
if(iso[1] == 'D') return QIcon(":/Icons/flags/indonesia.png");
|
||||
break;
|
||||
case 'J':
|
||||
if(iso[1] == 'P') { country_name = tr("Japan"); return QIcon(":/Icons/flags/japan.png"); }
|
||||
if(iso[1] == 'P') return QIcon(":/Icons/flags/japan.png");
|
||||
break;
|
||||
case 'K':
|
||||
if(iso[1] == 'R') { country_name = tr("South Korea"); return QIcon(":/Icons/flags/south_korea.png"); }
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/south_korea.png");
|
||||
break;
|
||||
case 'L':
|
||||
if(iso[1] == 'U') { country_name = tr("Luxembourg"); return QIcon(":/Icons/flags/luxembourg.png"); }
|
||||
if(iso[1] == 'U') return QIcon(":/Icons/flags/luxembourg.png");
|
||||
break;
|
||||
case 'M':
|
||||
if(iso[1] == 'Y') { country_name = tr("Malaysia"); return QIcon(":/Icons/flags/malaysia.png"); }
|
||||
if(iso[1] == 'X') { country_name = tr("Mexico"); return QIcon(":/Icons/flags/mexico.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("Serbia"); return QIcon(":/Icons/flags/serbia.png"); }
|
||||
if(iso[1] == 'A') { country_name = tr("Morocco"); return QIcon(":/Icons/flags/morocco.png"); }
|
||||
if(iso[1] == 'Y') return QIcon(":/Icons/flags/malaysia.png");
|
||||
if(iso[1] == 'X') return QIcon(":/Icons/flags/mexico.png");
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/serbia.png");
|
||||
if(iso[1] == 'A') return QIcon(":/Icons/flags/morocco.png");
|
||||
break;
|
||||
case 'N':
|
||||
if(iso[1] == 'L') { country_name = tr("Netherlands"); return QIcon(":/Icons/flags/netherlands.png"); }
|
||||
if(iso[1] == 'O') { country_name = tr("Norway"); return QIcon(":/Icons/flags/norway.png"); }
|
||||
if(iso[1] == 'Z') { country_name = tr("New Zealand"); return QIcon(":/Icons/flags/newzealand.png"); }
|
||||
if(iso[1] == 'L') return QIcon(":/Icons/flags/netherlands.png");
|
||||
if(iso[1] == 'O') return QIcon(":/Icons/flags/norway.png");
|
||||
if(iso[1] == 'Z') return QIcon(":/Icons/flags/newzealand.png");
|
||||
break;
|
||||
case 'P':
|
||||
if(iso[1] == 'T') { country_name = tr("Portugal"); return QIcon(":/Icons/flags/portugal.png"); }
|
||||
if(iso[1] == 'L') { country_name = tr("Poland"); return QIcon(":/Icons/flags/poland.png"); }
|
||||
if(iso[1] == 'K') { country_name = tr("Pakistan"); return QIcon(":/Icons/flags/pakistan.png"); }
|
||||
if(iso[1] == 'H') { country_name = tr("Philippines"); return QIcon(":/Icons/flags/philippines.png"); }
|
||||
if(iso[1] == 'T') return QIcon(":/Icons/flags/portugal.png");
|
||||
if(iso[1] == 'L') return QIcon(":/Icons/flags/poland.png");
|
||||
if(iso[1] == 'K') return QIcon(":/Icons/flags/pakistan.png");
|
||||
if(iso[1] == 'H') return QIcon(":/Icons/flags/philippines.png");
|
||||
break;
|
||||
case 'R':
|
||||
if(iso[1] == 'U') { country_name = tr("Russia"); return QIcon(":/Icons/flags/russia.png"); }
|
||||
if(iso[1] == 'O') { country_name = tr("Romania"); return QIcon(":/Icons/flags/romania.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("France (Reunion Island)"); return QIcon(":/Icons/flags/france.png"); }
|
||||
if(iso[1] == 'S') { country_name = tr("Serbia"); return QIcon(":/Icons/flags/serbia.png"); }
|
||||
if(iso[1] == 'U') return QIcon(":/Icons/flags/russia.png");
|
||||
if(iso[1] == 'O') return QIcon(":/Icons/flags/romania.png");
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/france.png");
|
||||
if(iso[1] == 'S') return QIcon(":/Icons/flags/serbia.png");
|
||||
break;
|
||||
case 'S':
|
||||
if(iso[1] == 'A') { country_name = tr("Saudi Arabia"); return QIcon(":/Icons/flags/saoudi_arabia.png"); }
|
||||
if(iso[1] == 'E') { country_name = tr("Sweden"); return QIcon(":/Icons/flags/sweden.png"); }
|
||||
if(iso[1] == 'K') { country_name = tr("Slovakia"); return QIcon(":/Icons/flags/slovakia.png"); }
|
||||
if(iso[1] == 'G') { country_name = tr("Singapore"); return QIcon(":/Icons/flags/singapore.png"); }
|
||||
if(iso[1] == 'I') { country_name = tr("Slovenia"); return QIcon(":/Icons/flags/slovenia.png"); }
|
||||
if(iso[1] == 'E') return QIcon(":/Icons/flags/sweden.png");
|
||||
if(iso[1] == 'K') return QIcon(":/Icons/flags/slovakia.png");
|
||||
if(iso[1] == 'G') return QIcon(":/Icons/flags/singapore.png");
|
||||
if(iso[1] == 'I') return QIcon(":/Icons/flags/slovenia.png");
|
||||
break;
|
||||
case 'T':
|
||||
if(iso[1] == 'W') { country_name = tr("Taiwan"); return QIcon(":/Icons/flags/china.png"); }
|
||||
if(iso[1] == 'R') { country_name = tr("Turkey"); return QIcon(":/Icons/flags/turkey.png"); }
|
||||
if(iso[1] == 'H') { country_name = tr("Thailand"); return QIcon(":/Icons/flags/thailand.png"); }
|
||||
if(iso[1] == 'W') return QIcon(":/Icons/flags/china.png");
|
||||
if(iso[1] == 'R') return QIcon(":/Icons/flags/turkey.png");
|
||||
if(iso[1] == 'H') return QIcon(":/Icons/flags/thailand.png");
|
||||
break;
|
||||
case 'U':
|
||||
if(iso[1] == 'S') { country_name = tr("USA"); return QIcon(":/Icons/flags/usa.png"); }
|
||||
if(iso[1] == 'M') { country_name = tr("USA"); return QIcon(":/Icons/flags/usa.png"); }
|
||||
if(iso[1] == 'A') { country_name = tr("Ukraine"); return QIcon(":/Icons/flags/ukraine.png"); }
|
||||
if(iso[1] == 'S') return QIcon(":/Icons/flags/usa.png");
|
||||
if(iso[1] == 'M') return QIcon(":/Icons/flags/usa.png");
|
||||
if(iso[1] == 'A') return QIcon(":/Icons/flags/ukraine.png");
|
||||
break;
|
||||
case 'Z':
|
||||
if(iso[1] == 'A') { country_name = tr("South Africa"); return QIcon(":/Icons/flags/south_africa.png"); }
|
||||
if(iso[1] == 'A') return QIcon(":/Icons/flags/south_africa.png");
|
||||
break;
|
||||
}
|
||||
qDebug("Unrecognized country code: %c%c", iso[0], iso[1]);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>geoip/GeoIP.dat</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>geoip/GeoIP.dat</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
508
src/gpl.html
@@ -1,508 +0,0 @@
|
||||
<p>qBittorrent is licensed under the GNU General Public License version 2 with the
|
||||
addition of the following special exception:</p>
|
||||
<p>
|
||||
In addition, as a special exception, the copyright holders give permission to
|
||||
link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
modified versions of it that use the same license as the "OpenSSL" library),
|
||||
and distribute the linked executables. You must obey the GNU General Public
|
||||
License in all respects for all of the code used other than "OpenSSL". If you
|
||||
modify file(s), you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.</p>
|
||||
----------
|
||||
<h2>GNU General Public License, version 2</h2>
|
||||
<hr>
|
||||
|
||||
<h3>Table of Contents</h3>
|
||||
<ul>
|
||||
|
||||
<li><a name="TOC1" href="#SEC1">GNU GENERAL PUBLIC
|
||||
LICENSE<!--TRANSLATORS: Don't translate the license; copy msgid's
|
||||
verbatim!--></a>
|
||||
<ul>
|
||||
<li><a name="TOC2" href="#SEC2">Preamble</a></li>
|
||||
<li><a name="TOC3" href="#SEC3">TERMS AND CONDITIONS
|
||||
FOR COPYING, DISTRIBUTION AND MODIFICATION</a></li>
|
||||
<li><a name="TOC4" href="#SEC4">How to Apply These
|
||||
Terms to Your New Programs</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3><a name="SEC1" href="#TOC1">GNU GENERAL PUBLIC LICENSE</a></h3>
|
||||
<p>
|
||||
Version 2, June 1991
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
</pre>
|
||||
|
||||
<h3><a name="preamble"></a><a name="SEC2" href="#TOC2">Preamble</a></h3>
|
||||
|
||||
<p>
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
</p>
|
||||
|
||||
|
||||
<h3><a name="terms"></a><a name="SEC3" href="#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</a></h3>
|
||||
|
||||
|
||||
<a name="section0"></a><p>
|
||||
<strong>0.</strong>
|
||||
This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
</p>
|
||||
|
||||
<a name="section1"></a><p>
|
||||
<strong>1.</strong>
|
||||
You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
</p>
|
||||
|
||||
<a name="section2"></a><p>
|
||||
<strong>2.</strong>
|
||||
You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<strong>a)</strong>
|
||||
You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
</dd>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<strong>b)</strong>
|
||||
You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
</dd>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<strong>c)</strong>
|
||||
If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
</p>
|
||||
|
||||
<a name="section3"></a><p>
|
||||
<strong>3.</strong>
|
||||
You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
</p>
|
||||
|
||||
<!-- we use this doubled UL to get the sub-sections indented, -->
|
||||
<!-- while making the bullets as unobvious as possible. -->
|
||||
|
||||
<dl>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<strong>a)</strong>
|
||||
Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
</dd>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<strong>b)</strong>
|
||||
Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
</dd>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<strong>c)</strong>
|
||||
Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
</p>
|
||||
|
||||
<a name="section4"></a><p>
|
||||
<strong>4.</strong>
|
||||
You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
</p>
|
||||
|
||||
<a name="section5"></a><p>
|
||||
<strong>5.</strong>
|
||||
You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
</p>
|
||||
|
||||
<a name="section6"></a><p>
|
||||
<strong>6.</strong>
|
||||
Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
</p>
|
||||
|
||||
<a name="section7"></a><p>
|
||||
<strong>7.</strong>
|
||||
If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
</p>
|
||||
|
||||
<a name="section8"></a><p>
|
||||
<strong>8.</strong>
|
||||
If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
</p>
|
||||
|
||||
<a name="section9"></a><p>
|
||||
<strong>9.</strong>
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
</p>
|
||||
|
||||
<a name="section10"></a><p>
|
||||
<strong>10.</strong>
|
||||
If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
</p>
|
||||
|
||||
<a name="section11"></a><p><strong>NO WARRANTY</strong></p>
|
||||
|
||||
<p>
|
||||
<strong>11.</strong>
|
||||
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
</p>
|
||||
|
||||
<a name="section12"></a><p>
|
||||
<strong>12.</strong>
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
</p>
|
||||
|
||||
<h3>END OF TERMS AND CONDITIONS</h3>
|
||||
|
||||
<h3><a name="howto"></a><a name="SEC4" href="#TOC4">How to Apply These Terms to Your New Programs</a></h3>
|
||||
|
||||
<p>
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<var>one line to give the program's name and an idea of what it does.</var>
|
||||
Copyright (C) <var>yyyy</var> <var>name of author</var>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Gnomovision version 69, Copyright (C) <var>year</var> <var>name of author</var>
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
|
||||
type `show w'. This is free software, and you are welcome
|
||||
to redistribute it under certain conditions; type `show c'
|
||||
for details.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The hypothetical commands <samp>`show w'</samp> and <samp>`show c'</samp> should show
|
||||
the appropriate parts of the General Public License. Of course, the
|
||||
commands you use may be called something other than <samp>`show w'</samp> and
|
||||
<samp>`show c'</samp>; they could even be mouse-clicks or menu items--whatever
|
||||
suits your program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
</p>
|
||||
|
||||
|
||||
<pre>
|
||||
Yoyodyne, Inc., hereby disclaims all copyright
|
||||
interest in the program `Gnomovision'
|
||||
(which makes passes at compilers) written
|
||||
by James Hacker.
|
||||
|
||||
<var>signature of Ty Coon</var>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the
|
||||
<a href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser General Public License</a>
|
||||
instead of this License.
|
||||
</p>
|
||||
@@ -33,10 +33,12 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QCoreApplication>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include "preferences.h"
|
||||
#include "bittorrent.h"
|
||||
|
||||
class HeadlessLoader: public QObject {
|
||||
class HeadlessLoader: QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@@ -50,6 +52,20 @@ public:
|
||||
BTSession->startUpTorrents();
|
||||
// Process command line parameters
|
||||
processParams(torrentCmdLine);
|
||||
// Use a tcp server to allow only one instance of qBittorrent
|
||||
localServer = new QLocalServer();
|
||||
const QString &uid = QString::number(getuid());
|
||||
#ifdef Q_WS_X11
|
||||
if(QFile::exists(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid)) {
|
||||
// Socket was not closed cleanly
|
||||
std::cerr << "Warning: Local domain socket was not closed cleanly, deleting file..." << std::endl;
|
||||
QFile::remove(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid);
|
||||
}
|
||||
#endif
|
||||
if (!localServer->listen("qBittorrent-"+uid)) {
|
||||
std::cerr << "Couldn't create socket, single instance mode won't work..." << std::endl;
|
||||
}
|
||||
connect(localServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
|
||||
// Display some information to the user
|
||||
std::cout << std::endl << "******** " << qPrintable(tr("Information")) << " ********" << std::endl;
|
||||
std::cout << qPrintable(tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(Preferences::getWebUiPort()))) << std::endl;
|
||||
@@ -61,6 +77,7 @@ public:
|
||||
}
|
||||
|
||||
~HeadlessLoader() {
|
||||
delete localServer;
|
||||
delete BTSession;
|
||||
}
|
||||
|
||||
@@ -75,10 +92,6 @@ public slots:
|
||||
std::cout << qPrintable(msg) << std::endl;
|
||||
}
|
||||
|
||||
void processParams(const QString& params_str) {
|
||||
processParams(params_str.split(" ", QString::SkipEmptyParts));
|
||||
}
|
||||
|
||||
// As program parameters, we can get paths or urls.
|
||||
// This function parse the parameters and call
|
||||
// the right addTorrent function, considering
|
||||
@@ -86,13 +99,10 @@ public slots:
|
||||
void processParams(const QStringList& params) {
|
||||
foreach(QString param, params) {
|
||||
param = param.trimmed();
|
||||
if(param.startsWith("--")) continue;
|
||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
BTSession->downloadFromUrl(param);
|
||||
}else{
|
||||
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
param = misc::bcLinkToMagnet(param);
|
||||
}
|
||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
BTSession->addMagnetUri(param);
|
||||
} else {
|
||||
@@ -102,7 +112,26 @@ public slots:
|
||||
}
|
||||
}
|
||||
|
||||
void acceptConnection() {
|
||||
QLocalSocket *clientConnection = localServer->nextPendingConnection();
|
||||
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(readParamsOnSocket()));
|
||||
qDebug("accepted connection from another instance");
|
||||
}
|
||||
|
||||
void readParamsOnSocket() {
|
||||
QLocalSocket *clientConnection = static_cast<QLocalSocket*>(sender());
|
||||
if(clientConnection) {
|
||||
const QByteArray ¶ms = clientConnection->readAll();
|
||||
if(!params.isEmpty()) {
|
||||
processParams(QString(params).split("\n"));
|
||||
qDebug("Received parameters from another instance");
|
||||
}
|
||||
clientConnection->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QLocalServer *localServer;
|
||||
Bittorrent *BTSession;
|
||||
|
||||
};
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef HIDABLETABWIDGET_H
|
||||
#define HIDABLETABWIDGET_H
|
||||
|
||||
#include <QTabWidget>
|
||||
#include <QTabBar>
|
||||
|
||||
class HidableTabWidget : public QTabWidget {
|
||||
public:
|
||||
void showTabBar(bool show) {
|
||||
tabBar()->setVisible(show);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // HIDABLETABWIDGET_H
|
||||
@@ -109,7 +109,7 @@ QString HttpConnection::translateDocument(QString data) {
|
||||
bool found = false;
|
||||
do {
|
||||
found = false;
|
||||
QRegExp regex(QString::fromUtf8("_\\(([\\w\\s?!:\\/\\(\\),%µ&\\-\\.]+)\\)"));
|
||||
QRegExp regex(QString::fromUtf8("_\\(([\\w\\s?!:\\/\\(\\),µ\\-\\.]+)\\)"));
|
||||
i = regex.indexIn(data, i);
|
||||
if(i >= 0) {
|
||||
//qDebug("Found translatable string: %s", regex.cap(1).toUtf8().data());
|
||||
@@ -120,8 +120,6 @@ QString HttpConnection::translateDocument(QString data) {
|
||||
translation = qApp->translate(contexts[context_index].c_str(), word.toLocal8Bit().constData(), 0, QCoreApplication::UnicodeUTF8, 1);
|
||||
++context_index;
|
||||
}while(translation == word && context_index < 13);
|
||||
// Remove keyboard shortcuts
|
||||
translation = translation.replace("&", "");
|
||||
//qDebug("Translation is %s", translation.toUtf8().data());
|
||||
data = data.replace(i, regex.matchedLength(), translation);
|
||||
i += translation.length();
|
||||
@@ -133,7 +131,7 @@ QString HttpConnection::translateDocument(QString data) {
|
||||
|
||||
void HttpConnection::respond() {
|
||||
//qDebug("Respond called");
|
||||
const QString peer_ip = socket->peerAddress().toString();
|
||||
const QString &peer_ip = socket->peerAddress().toString();
|
||||
const int nb_fail = parent->NbFailedAttemptsForIp(peer_ip);
|
||||
if(nb_fail >= MAX_AUTH_FAILED_ATTEMPTS) {
|
||||
generator.setStatusLine(403, "Forbidden");
|
||||
@@ -150,18 +148,18 @@ void HttpConnection::respond() {
|
||||
write();
|
||||
return;
|
||||
}
|
||||
//qDebug("Auth: %s", qPrintable(auth.split(" ").first()));
|
||||
qDebug("Auth: %s", qPrintable(auth.split(" ").first()));
|
||||
if (QString::compare(auth.split(" ").first(), "Digest", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth.toLocal8Bit(), parser.method())) {
|
||||
// Update failed attempt counter
|
||||
parent->increaseNbFailedAttemptsForIp(peer_ip);
|
||||
qDebug("client IP: %s (%d failed attempts)", qPrintable(peer_ip), nb_fail+1);
|
||||
// Return unauthorized header
|
||||
generator.setStatusLine(401, "Unauthorized");
|
||||
generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", opaque=\""+parent->generateNonce()+"\", stale=\"false\", algorithm=\"MD5\", qop=\"auth\"");
|
||||
generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", algorithm=\"MD5\", qop=\"auth\"");
|
||||
write();
|
||||
return;
|
||||
}
|
||||
// Client successfully authenticated, reset number of failed attempts
|
||||
// Client sucessfuly authenticated, reset number of failed attempts
|
||||
parent->resetNbFailedAttemptsForIp(peer_ip);
|
||||
QString url = parser.url();
|
||||
// Favicon
|
||||
@@ -239,7 +237,6 @@ void HttpConnection::respond() {
|
||||
QFile file(url);
|
||||
if(!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qDebug("File %s was not found!", qPrintable(url));
|
||||
respondNotFound();
|
||||
return;
|
||||
}
|
||||
@@ -333,10 +330,6 @@ void HttpConnection::respondCommand(QString command)
|
||||
foreach(QString url, list){
|
||||
url = url.trimmed();
|
||||
if(!url.isEmpty()){
|
||||
if(url.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
url = misc::bcLinkToMagnet(url);
|
||||
}
|
||||
if(url.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
emit MagnetReadyToBeDownloaded(url);
|
||||
} else {
|
||||
@@ -500,16 +493,6 @@ void HttpConnection::respondCommand(QString command)
|
||||
if(h.is_valid()) h.queue_position_down();
|
||||
return;
|
||||
}
|
||||
if(command == "topPrio") {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(parser.post("hash"));
|
||||
if(h.is_valid()) h.queue_position_top();
|
||||
return;
|
||||
}
|
||||
if(command == "bottomPrio") {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(parser.post("hash"));
|
||||
if(h.is_valid()) h.queue_position_bottom();
|
||||
return;
|
||||
}
|
||||
if(command == "recheck"){
|
||||
recheckTorrent(parser.post("hash"));
|
||||
return;
|
||||
|
||||
@@ -54,7 +54,7 @@ class HttpConnection : public QObject
|
||||
|
||||
protected slots:
|
||||
void write();
|
||||
void respond();
|
||||
virtual void respond();
|
||||
void respondJson();
|
||||
void respondGenPropertiesJson(QString hash);
|
||||
void respondTrackersPropertiesJson(QString hash);
|
||||
|
||||
@@ -39,8 +39,7 @@ void HttpResponseGenerator::setMessage(const QByteArray message)
|
||||
|
||||
void HttpResponseGenerator::setMessage(const QString message)
|
||||
{
|
||||
// This must be UTF-8!
|
||||
setMessage(message.toUtf8());
|
||||
setMessage(message.QString::toLocal8Bit());
|
||||
}
|
||||
|
||||
void HttpResponseGenerator::stripMessage()
|
||||
|
||||
@@ -44,7 +44,7 @@ class HttpResponseGenerator : public QHttpResponseHeader
|
||||
void setMessage(const QString message);
|
||||
void stripMessage();
|
||||
void setContentTypeByExt(const QString ext);
|
||||
QByteArray toByteArray() const;
|
||||
virtual QByteArray toByteArray() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -177,12 +177,12 @@ void HttpServer::setAuthorization(QString _username, QString _password_ha1) {
|
||||
// Parse HTTP AUTH string
|
||||
// http://tools.ietf.org/html/rfc2617
|
||||
bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
|
||||
//qDebug("AUTH string is %s", auth.data());
|
||||
qDebug("AUTH string is %s", auth.data());
|
||||
// Get user name
|
||||
QRegExp regex_user(".*username=\"([^\"]+)\".*"); // Must be a quoted string
|
||||
if(regex_user.indexIn(auth) < 0) return false;
|
||||
QString prop_user = regex_user.cap(1);
|
||||
//qDebug("AUTH: Proposed username is %s, real username is %s", prop_user.toLocal8Bit().data(), username.data());
|
||||
qDebug("AUTH: Proposed username is %s, real username is %s", prop_user.toLocal8Bit().data(), username.data());
|
||||
if(prop_user != username) {
|
||||
// User name is invalid, we can reject already
|
||||
qDebug("AUTH-PROB: Username is invalid");
|
||||
|
||||
322
src/icons.qrc
@@ -1,184 +1,182 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/loading.png</file>
|
||||
<file>Icons/rss16.png</file>
|
||||
<file>Icons/slow48.png</file>
|
||||
<file>Icons/rss32.png</file>
|
||||
<file>Icons/3-state-checkbox.gif</file>
|
||||
<file>Icons/uparrow.png</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/downarrow.png</file>
|
||||
<file>Icons/slow_off.png</file>
|
||||
<file>Icons/sphere2.png</file>
|
||||
<file>Icons/magnet.png</file>
|
||||
<file>Icons/downarrow.png</file>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/locale.png</file>
|
||||
<file>Icons/loading.png</file>
|
||||
<file>Icons/slow.png</file>
|
||||
<file>Icons/L.gif</file>
|
||||
<file>Icons/skin/delete_perm22.png</file>
|
||||
<file>Icons/skin/seeding.png</file>
|
||||
<file>Icons/skin/splash.png</file>
|
||||
<file>Icons/skin/preview.png</file>
|
||||
<file>Icons/skin/tabs.gif</file>
|
||||
<file>Icons/skin/delete.png</file>
|
||||
<file>Icons/skin/increase.png</file>
|
||||
<file>Icons/skin/qbittorrent16.png</file>
|
||||
<file>Icons/skin/connected.png</file>
|
||||
<file>Icons/skin/url.png</file>
|
||||
<file>Icons/skin/qbittorrent22.png</file>
|
||||
<file>Icons/skin/disconnected.png</file>
|
||||
<file>Icons/skin/mascot.png</file>
|
||||
<file>Icons/skin/info.png</file>
|
||||
<file>Icons/skin/paused.png</file>
|
||||
<file>Icons/skin/slider-area.gif</file>
|
||||
<file>Icons/skin/pause22.png</file>
|
||||
<file>Icons/skin/stalledDL.png</file>
|
||||
<file>Icons/skin/play.png</file>
|
||||
<file>Icons/skin/delete_all.png</file>
|
||||
<file>Icons/skin/delete_perm.png</file>
|
||||
<file>Icons/skin/qb_question.png</file>
|
||||
<file>Icons/skin/error.png</file>
|
||||
<file>Icons/skin/settings.png</file>
|
||||
<file>Icons/skin/handle-icon-horizontal.gif</file>
|
||||
<file>Icons/skin/pause.png</file>
|
||||
<file>Icons/skin/qbittorrent32.png</file>
|
||||
<file>Icons/skin/exit.png</file>
|
||||
<file>Icons/skin/knob.gif</file>
|
||||
<file>Icons/skin/open.png</file>
|
||||
<file>Icons/skin/pause_all.png</file>
|
||||
<file>Icons/skin/filterall.png</file>
|
||||
<file>Icons/skin/uploading.png</file>
|
||||
<file>Icons/skin/queued.png</file>
|
||||
<file>Icons/skin/checking.png</file>
|
||||
<file>Icons/skin/handle-icon.gif</file>
|
||||
<file>Icons/skin/arrow-right.gif</file>
|
||||
<file>Icons/skin/filterinactive.png</file>
|
||||
<file>Icons/skin/decrease.png</file>
|
||||
<file>Icons/skin/play22.png</file>
|
||||
<file>Icons/skin/firewalled.png</file>
|
||||
<file>Icons/skin/delete22.png</file>
|
||||
<file>Icons/skin/new.png</file>
|
||||
<file>Icons/skin/downloading.png</file>
|
||||
<file>Icons/skin/play_all.png</file>
|
||||
<file>Icons/skin/toolbox-divider.gif</file>
|
||||
<file>Icons/skin/stalledUP.png</file>
|
||||
<file>Icons/skin/filteractive.png</file>
|
||||
<file>Icons/magnet.png</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/slow_off.png</file>
|
||||
<file>Icons/uparrow.png</file>
|
||||
<file>Icons/rss16.png</file>
|
||||
<file>Icons/skin/checkingUP.png</file>
|
||||
<file>Icons/skin/bg-handle-horizontal.gif</file>
|
||||
<file>Icons/skin/play.png</file>
|
||||
<file>Icons/skin/qbittorrent22.png</file>
|
||||
<file>Icons/skin/queuedDL.png</file>
|
||||
<file>Icons/skin/new.png</file>
|
||||
<file>Icons/skin/queuedUP.png</file>
|
||||
<file>Icons/skin/preview.png</file>
|
||||
<file>Icons/skin/stalled.png</file>
|
||||
<file>Icons/skin/delete.png</file>
|
||||
<file>Icons/skin/handle-icon-horizontal.gif</file>
|
||||
<file>Icons/skin/handle-icon.gif</file>
|
||||
<file>Icons/skin/knob.gif</file>
|
||||
<file>Icons/skin/url.png</file>
|
||||
<file>Icons/skin/stalledUP.png</file>
|
||||
<file>Icons/skin/delete_perm22.png</file>
|
||||
<file>Icons/skin/filteractive.png</file>
|
||||
<file>Icons/skin/connected.png</file>
|
||||
<file>Icons/skin/pausedDL.png</file>
|
||||
<file>Icons/skin/mascot.png</file>
|
||||
<file>Icons/skin/pausedUP.png</file>
|
||||
<file>Icons/skin/seeding.png</file>
|
||||
<file>Icons/skin/increase.png</file>
|
||||
<file>Icons/skin/qbittorrent32.png</file>
|
||||
<file>Icons/skin/paused.png</file>
|
||||
<file>Icons/skin/toolbox-divider.gif</file>
|
||||
<file>Icons/skin/stalledDL.png</file>
|
||||
<file>Icons/skin/qb_question.png</file>
|
||||
<file>Icons/skin/download.png</file>
|
||||
<file>Icons/flags/pakistan.png</file>
|
||||
<file>Icons/flags/argentina.png</file>
|
||||
<file>Icons/flags/netherlands.png</file>
|
||||
<file>Icons/flags/australia.png</file>
|
||||
<file>Icons/flags/finland.png</file>
|
||||
<file>Icons/flags/croatia.png</file>
|
||||
<file>Icons/flags/indonesia.png</file>
|
||||
<file>Icons/flags/greece.png</file>
|
||||
<file>Icons/flags/belarus.png</file>
|
||||
<file>Icons/flags/morocco.png</file>
|
||||
<file>Icons/flags/portugal.png</file>
|
||||
<file>Icons/flags/egypt.png</file>
|
||||
<file>Icons/flags/georgia.png</file>
|
||||
<file>Icons/flags/costa_rica.png</file>
|
||||
<file>Icons/flags/denmark.png</file>
|
||||
<file>Icons/flags/bosnia.png</file>
|
||||
<file>Icons/flags/newzealand.png</file>
|
||||
<file>Icons/skin/open.png</file>
|
||||
<file>Icons/skin/play22.png</file>
|
||||
<file>Icons/skin/qbittorrent16.png</file>
|
||||
<file>Icons/skin/slider-area.gif</file>
|
||||
<file>Icons/skin/downloading.png</file>
|
||||
<file>Icons/skin/filterinactive.png</file>
|
||||
<file>Icons/skin/pause22.png</file>
|
||||
<file>Icons/skin/pause_all.png</file>
|
||||
<file>Icons/skin/delete22.png</file>
|
||||
<file>Icons/skin/play_all.png</file>
|
||||
<file>Icons/skin/pause.png</file>
|
||||
<file>Icons/skin/firewalled.png</file>
|
||||
<file>Icons/skin/properties.png</file>
|
||||
<file>Icons/skin/info.png</file>
|
||||
<file>Icons/skin/tabs.gif</file>
|
||||
<file>Icons/skin/delete_perm.png</file>
|
||||
<file>Icons/skin/checkingDL.png</file>
|
||||
<file>Icons/skin/settings.png</file>
|
||||
<file>Icons/skin/exit.png</file>
|
||||
<file>Icons/skin/delete_all.png</file>
|
||||
<file>Icons/skin/splash.png</file>
|
||||
<file>Icons/skin/disconnected.png</file>
|
||||
<file>Icons/skin/decrease.png</file>
|
||||
<file>Icons/skin/uploading.png</file>
|
||||
<file>Icons/skin/filterall.png</file>
|
||||
<file>Icons/flags/czech.png</file>
|
||||
<file>Icons/flags/serbia.png</file>
|
||||
<file>Icons/flags/singapore.png</file>
|
||||
<file>Icons/flags/italy.png</file>
|
||||
<file>Icons/flags/brazil.png</file>
|
||||
<file>Icons/flags/iceland.png</file>
|
||||
<file>Icons/flags/china.png</file>
|
||||
<file>Icons/flags/luxembourg.png</file>
|
||||
<file>Icons/flags/newzealand.png</file>
|
||||
<file>Icons/flags/austria.png</file>
|
||||
<file>Icons/flags/indonesia.png</file>
|
||||
<file>Icons/flags/united_arab_emirates.png</file>
|
||||
<file>Icons/flags/norway.png</file>
|
||||
<file>Icons/flags/india.png</file>
|
||||
<file>Icons/flags/finland.png</file>
|
||||
<file>Icons/flags/australia.png</file>
|
||||
<file>Icons/flags/netherlands.png</file>
|
||||
<file>Icons/flags/south_africa.png</file>
|
||||
<file>Icons/flags/belarus.png</file>
|
||||
<file>Icons/flags/georgia.png</file>
|
||||
<file>Icons/flags/taiwan.png</file>
|
||||
<file>Icons/flags/south_korea.png</file>
|
||||
<file>Icons/flags/sweden.png</file>
|
||||
<file>Icons/flags/spain_catalunya.png</file>
|
||||
<file>Icons/flags/ireland.png</file>
|
||||
<file>Icons/flags/singapore.png</file>
|
||||
<file>Icons/flags/israel.png</file>
|
||||
<file>Icons/flags/belgium.png</file>
|
||||
<file>Icons/flags/usa.png</file>
|
||||
<file>Icons/flags/costa_rica.png</file>
|
||||
<file>Icons/flags/romania.png</file>
|
||||
<file>Icons/flags/suisse.png</file>
|
||||
<file>Icons/flags/croatia.png</file>
|
||||
<file>Icons/flags/mexico.png</file>
|
||||
<file>Icons/flags/denmark.png</file>
|
||||
<file>Icons/flags/hungary.png</file>
|
||||
<file>Icons/flags/slovenia.png</file>
|
||||
<file>Icons/flags/ukraine.png</file>
|
||||
<file>Icons/flags/turkey.png</file>
|
||||
<file>Icons/flags/algeria.png</file>
|
||||
<file>Icons/flags/japan.png</file>
|
||||
<file>Icons/flags/luxembourg.png</file>
|
||||
<file>Icons/flags/poland.png</file>
|
||||
<file>Icons/flags/iceland.png</file>
|
||||
<file>Icons/flags/greece.png</file>
|
||||
<file>Icons/flags/morocco.png</file>
|
||||
<file>Icons/flags/argentina.png</file>
|
||||
<file>Icons/flags/spain.png</file>
|
||||
<file>Icons/flags/saoudi_arabia.png</file>
|
||||
<file>Icons/flags/norway.png</file>
|
||||
<file>Icons/flags/portugal.png</file>
|
||||
<file>Icons/flags/russia.png</file>
|
||||
<file>Icons/flags/slovakia.png</file>
|
||||
<file>Icons/flags/philippines.png</file>
|
||||
<file>Icons/flags/thailand.png</file>
|
||||
<file>Icons/flags/israel.png</file>
|
||||
<file>Icons/flags/bulgaria.png</file>
|
||||
<file>Icons/flags/czech.png</file>
|
||||
<file>Icons/flags/usa.png</file>
|
||||
<file>Icons/flags/malaysia.png</file>
|
||||
<file>Icons/flags/belgium.png</file>
|
||||
<file>Icons/flags/south_africa.png</file>
|
||||
<file>Icons/flags/slovenia.png</file>
|
||||
<file>Icons/flags/china.png</file>
|
||||
<file>Icons/flags/germany.png</file>
|
||||
<file>Icons/flags/ukraine.png</file>
|
||||
<file>Icons/flags/india.png</file>
|
||||
<file>Icons/flags/spain_catalunya.png</file>
|
||||
<file>Icons/flags/romania.png</file>
|
||||
<file>Icons/flags/united_kingdom.png</file>
|
||||
<file>Icons/flags/united_arab_emirates.png</file>
|
||||
<file>Icons/flags/sweden.png</file>
|
||||
<file>Icons/flags/thailand.png</file>
|
||||
<file>Icons/flags/poland.png</file>
|
||||
<file>Icons/flags/germany.png</file>
|
||||
<file>Icons/flags/bulgaria.png</file>
|
||||
<file>Icons/flags/canada.png</file>
|
||||
<file>Icons/flags/mexico.png</file>
|
||||
<file>Icons/flags/hungary.png</file>
|
||||
<file>Icons/flags/brazil.png</file>
|
||||
<file>Icons/flags/france.png</file>
|
||||
<file>Icons/flags/ireland.png</file>
|
||||
<file>Icons/flags/austria.png</file>
|
||||
<file>Icons/flags/suisse.png</file>
|
||||
<file>Icons/oxygen/peer.png</file>
|
||||
<file>Icons/oxygen/unavailable.png</file>
|
||||
<file>Icons/oxygen/subscribe.png</file>
|
||||
<file>Icons/oxygen/list-remove.png</file>
|
||||
<file>Icons/oxygen/dialog-warning.png</file>
|
||||
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||
<file>Icons/oxygen/folder.png</file>
|
||||
<file>Icons/oxygen/edit-copy.png</file>
|
||||
<file>Icons/oxygen/folder-documents.png</file>
|
||||
<file>Icons/oxygen/urlseed.png</file>
|
||||
<file>Icons/oxygen/go-up.png</file>
|
||||
<file>Icons/oxygen/edit-cut.png</file>
|
||||
<file>Icons/oxygen/gear32.png</file>
|
||||
<file>Icons/oxygen/go-bottom.png</file>
|
||||
<file>Icons/oxygen/user-group-delete.png</file>
|
||||
<file>Icons/oxygen/unsubscribe.png</file>
|
||||
<file>Icons/oxygen/tab-close.png</file>
|
||||
<file>Icons/oxygen/file.png</file>
|
||||
<file>Icons/oxygen/services.png</file>
|
||||
<file>Icons/flags/slovakia.png</file>
|
||||
<file>Icons/flags/pakistan.png</file>
|
||||
<file>Icons/flags/egypt.png</file>
|
||||
<file>Icons/flags/italy.png</file>
|
||||
<file>Icons/flags/south_korea.png</file>
|
||||
<file>Icons/flags/bosnia.png</file>
|
||||
<file>Icons/flags/japan.png</file>
|
||||
<file>Icons/flags/malaysia.png</file>
|
||||
<file>Icons/flags/philippines.png</file>
|
||||
<file>Icons/oxygen/mail-queue.png</file>
|
||||
<file>Icons/oxygen/view-refresh.png</file>
|
||||
<file>Icons/oxygen/feed-subscribe.png</file>
|
||||
<file>Icons/oxygen/remove.png</file>
|
||||
<file>Icons/oxygen/chronometer.png</file>
|
||||
<file>Icons/oxygen/filter.png</file>
|
||||
<file>Icons/oxygen/run-build.png</file>
|
||||
<file>Icons/oxygen/button_ok.png</file>
|
||||
<file>Icons/oxygen/user-group-new.png</file>
|
||||
<file>Icons/oxygen/cookies.png</file>
|
||||
<file>Icons/oxygen/network-server.png</file>
|
||||
<file>Icons/oxygen/unsubscribe16.png</file>
|
||||
<file>Icons/oxygen/encrypted32.png</file>
|
||||
<file>Icons/oxygen/list-add.png</file>
|
||||
<file>Icons/oxygen/edit-paste.png</file>
|
||||
<file>Icons/oxygen/folder-remote.png</file>
|
||||
<file>Icons/oxygen/help-about.png</file>
|
||||
<file>Icons/oxygen/encrypted.png</file>
|
||||
<file>Icons/oxygen/file.png</file>
|
||||
<file>Icons/oxygen/folder-remote16.png</file>
|
||||
<file>Icons/oxygen/go-top.png</file>
|
||||
<file>Icons/oxygen/emblem-favorite.png</file>
|
||||
<file>Icons/oxygen/edit_clear.png</file>
|
||||
<file>Icons/oxygen/bug.png</file>
|
||||
<file>Icons/oxygen/gear.png</file>
|
||||
<file>Icons/oxygen/connection.png</file>
|
||||
<file>Icons/oxygen/document-new.png</file>
|
||||
<file>Icons/oxygen/browse.png</file>
|
||||
<file>Icons/oxygen/proxy.png</file>
|
||||
<file>Icons/oxygen/button_cancel.png</file>
|
||||
<file>Icons/oxygen/preferences-desktop.png</file>
|
||||
<file>Icons/oxygen/bt_settings.png</file>
|
||||
<file>Icons/oxygen/go-down.png</file>
|
||||
<file>Icons/oxygen/subscribe16.png</file>
|
||||
<file>Icons/oxygen/download.png</file>
|
||||
<file>Icons/oxygen/log.png</file>
|
||||
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||
<file>Icons/oxygen/edit-find.png</file>
|
||||
<file>Icons/oxygen/edit-clear.png</file>
|
||||
<file>Icons/oxygen/webui.png</file>
|
||||
<file>Icons/oxygen/folder-new.png</file>
|
||||
<file>Icons/oxygen/folder-remote.png</file>
|
||||
<file>Icons/oxygen/edit-paste.png</file>
|
||||
<file>Icons/oxygen/run-build.png</file>
|
||||
<file>Icons/oxygen/proxy.png</file>
|
||||
<file>Icons/oxygen/services.png</file>
|
||||
<file>Icons/oxygen/user-group-delete.png</file>
|
||||
<file>Icons/oxygen/user-group-new.png</file>
|
||||
<file>Icons/oxygen/log.png</file>
|
||||
<file>Icons/oxygen/unavailable.png</file>
|
||||
<file>Icons/oxygen/button_ok.png</file>
|
||||
<file>Icons/oxygen/button_cancel.png</file>
|
||||
<file>Icons/oxygen/edit-clear.png</file>
|
||||
<file>Icons/oxygen/filter.png</file>
|
||||
<file>Icons/oxygen/encrypted.png</file>
|
||||
<file>Icons/oxygen/edit_clear.png</file>
|
||||
<file>Icons/oxygen/download.png</file>
|
||||
<file>Icons/oxygen/gear32.png</file>
|
||||
<file>Icons/oxygen/gear.png</file>
|
||||
<file>Icons/oxygen/remove.png</file>
|
||||
<file>Icons/oxygen/dialog-warning.png</file>
|
||||
<file>Icons/oxygen/peer.png</file>
|
||||
<file>Icons/oxygen/browse.png</file>
|
||||
<file>Icons/oxygen/unsubscribe16.png</file>
|
||||
<file>Icons/oxygen/subscribe.png</file>
|
||||
<file>Icons/oxygen/edit-copy.png</file>
|
||||
<file>Icons/oxygen/chronometer.png</file>
|
||||
<file>Icons/oxygen/bt_settings.png</file>
|
||||
<file>Icons/oxygen/document-new.png</file>
|
||||
<file>Icons/oxygen/preferences-desktop.png</file>
|
||||
<file>Icons/oxygen/tab-close.png</file>
|
||||
<file>Icons/oxygen/wallet.png</file>
|
||||
<file>Icons/oxygen/webui.png</file>
|
||||
<file>Icons/oxygen/list-remove.png</file>
|
||||
<file>Icons/oxygen/connection.png</file>
|
||||
<file>Icons/oxygen/bug.png</file>
|
||||
<file>Icons/oxygen/help-about.png</file>
|
||||
<file>Icons/oxygen/list-add.png</file>
|
||||
<file>Icons/oxygen/network-server.png</file>
|
||||
<file>Icons/oxygen/folder.png</file>
|
||||
<file>Icons/oxygen/urlseed.png</file>
|
||||
<file>Icons/oxygen/folder-documents.png</file>
|
||||
<file>Icons/oxygen/edit-cut.png</file>
|
||||
<file>Icons/oxygen/unsubscribe.png</file>
|
||||
<file>Icons/oxygen/feed-subscribe.png</file>
|
||||
<file>Icons/oxygen/subscribe16.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -47,7 +47,7 @@ namespace json {
|
||||
case QVariant::LongLong:
|
||||
case QVariant::UInt:
|
||||
case QVariant::ULongLong:
|
||||
//case QMetaType::Float:
|
||||
case QMetaType::Float:
|
||||
return v.value<QString>();
|
||||
case QVariant::StringList:
|
||||
case QVariant::List: {
|
||||
@@ -109,7 +109,6 @@ namespace json {
|
||||
}
|
||||
|
||||
QVariantMap fromJson(QString json) {
|
||||
qDebug("JSON is %s", qPrintable(json));
|
||||
QVariantMap m;
|
||||
if(json.startsWith("{") && json.endsWith("}")) {
|
||||
json.chop(1);
|
||||
@@ -132,7 +131,6 @@ namespace json {
|
||||
tmp += c;
|
||||
}
|
||||
}
|
||||
if(!tmp.isEmpty()) couples << tmp;
|
||||
foreach(QString couple, couples) {
|
||||
QStringList parts = couple.split(":");
|
||||
if(parts.size() != 2) continue;
|
||||
@@ -146,7 +144,7 @@ namespace json {
|
||||
if(value_str.startsWith("[") && value_str.endsWith("]")) {
|
||||
value_str.chop(1);
|
||||
value_str.replace(0, 1, "");
|
||||
QStringList list_elems = value_str.split(",", QString::SkipEmptyParts);
|
||||
QStringList list_elems = value_str.split(",");
|
||||
QVariantList varlist;
|
||||
foreach(QString list_val, list_elems) {
|
||||
if(list_val.startsWith("\"") && list_val.endsWith("\"")) {
|
||||
|
||||
48
src/lang.qrc
@@ -1,34 +1,32 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>lang/qbittorrent_nl.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_ru.qm</file>
|
||||
<file>lang/qbittorrent_zh_TW.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_sk.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_zh_TW.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_en.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_ru.qm</file>
|
||||
<file>lang/qbittorrent_nl.qm</file>
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_cs.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_el.qm</file>
|
||||
<file>lang/qbittorrent_ca.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_sr.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_cs.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_ar.qm</file>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_en.qm</file>
|
||||
<file>lang/qbittorrent_hr.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||