Compare commits
244 Commits
release-3.
...
release-3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb5174bfa2 | ||
|
|
9138156968 | ||
|
|
8a0b1fe0be | ||
|
|
3bbe304856 | ||
|
|
0356172a1d | ||
|
|
80f3b19356 | ||
|
|
39a569b438 | ||
|
|
edaa7e85a7 | ||
|
|
f9f7a8cbf2 | ||
|
|
7aef9828c9 | ||
|
|
18ad972936 | ||
|
|
8b5c275934 | ||
|
|
59765954b8 | ||
|
|
f5fff855bb | ||
|
|
26c713851e | ||
|
|
f9b64c4e73 | ||
|
|
edf6c30cd8 | ||
|
|
83860afa60 | ||
|
|
4b7362aa6b | ||
|
|
dd0537d8d2 | ||
|
|
3c50cc1d2c | ||
|
|
78fdb68457 | ||
|
|
bb1bd34ec0 | ||
|
|
1841834c89 | ||
|
|
30b70a99f1 | ||
|
|
f0f2e93e4d | ||
|
|
5852c5e318 | ||
|
|
b38827bb8e | ||
|
|
240046f720 | ||
|
|
78b1194da1 | ||
|
|
c1a66dad51 | ||
|
|
4a10d246c2 | ||
|
|
125ab378a4 | ||
|
|
4cd8a36b40 | ||
|
|
364df2e18c | ||
|
|
f8f2476aa5 | ||
|
|
d685c9739b | ||
|
|
6fdfcf38f1 | ||
|
|
7c85866881 | ||
|
|
37673cd86f | ||
|
|
a4a38d633c | ||
|
|
93bdc81e3c | ||
|
|
827d5a22fb | ||
|
|
34e56eade8 | ||
|
|
4a23e7da37 | ||
|
|
f577a26fe2 | ||
|
|
3f176d8265 | ||
|
|
cbc001e059 | ||
|
|
a66ed05ecd | ||
|
|
ec347d8dbe | ||
|
|
f0acafb853 | ||
|
|
1a12e891ec | ||
|
|
88ba8e2ceb | ||
|
|
2e403277f3 | ||
|
|
89349f60b0 | ||
|
|
0604d3729a | ||
|
|
cf16e3b8a1 | ||
|
|
dcb3496651 | ||
|
|
9d10da3ed2 | ||
|
|
0524deb496 | ||
|
|
787ae43d54 | ||
|
|
67bb2cc150 | ||
|
|
51995c80d1 | ||
|
|
5f43741b09 | ||
|
|
3328d8efd2 | ||
|
|
a54a9e5487 | ||
|
|
0181ca70f4 | ||
|
|
ff665af3f7 | ||
|
|
9275cdc5bf | ||
|
|
b7c3bdd443 | ||
|
|
5fd08f8664 | ||
|
|
84a4d323c7 | ||
|
|
8efb13bfaf | ||
|
|
0187b55610 | ||
|
|
2f606b2728 | ||
|
|
025f75beca | ||
|
|
4711cafd20 | ||
|
|
8d12ca9477 | ||
|
|
67b90bfb51 | ||
|
|
ab05c0c326 | ||
|
|
c5ea453438 | ||
|
|
4f041c16e1 | ||
|
|
28cfee7bd3 | ||
|
|
6272287fbb | ||
|
|
e7a1542902 | ||
|
|
5e371d8195 | ||
|
|
6bb189ea13 | ||
|
|
8496f31e39 | ||
|
|
08f634f748 | ||
|
|
2b5dc5c4a6 | ||
|
|
0a2f0aefb3 | ||
|
|
66e137b8ee | ||
|
|
f9be39545b | ||
|
|
789b8046a2 | ||
|
|
129bf497c8 | ||
|
|
a6d7693d62 | ||
|
|
4e9fbc4da5 | ||
|
|
23f6ff4673 | ||
|
|
3c0dfa6444 | ||
|
|
694311b2bd | ||
|
|
b77626897f | ||
|
|
b8081feac1 | ||
|
|
8b805f4518 | ||
|
|
8bb4f021f1 | ||
|
|
97c79050dc | ||
|
|
ac62a708de | ||
|
|
8d9789f51b | ||
|
|
559d0228fd | ||
|
|
1296e7b891 | ||
|
|
0333e23710 | ||
|
|
7320a80caa | ||
|
|
0579bfc069 | ||
|
|
d20d04299e | ||
|
|
50b2009e9c | ||
|
|
721d29edda | ||
|
|
bc9cae199b | ||
|
|
c38b250667 | ||
|
|
101b2f3ad2 | ||
|
|
9c4f798d93 | ||
|
|
249ff21738 | ||
|
|
f1149097b6 | ||
|
|
111b0df307 | ||
|
|
8041af72cd | ||
|
|
4be6d0b30f | ||
|
|
8c757969f2 | ||
|
|
ae6a82f814 | ||
|
|
eed3f0559a | ||
|
|
c7884e7621 | ||
|
|
2946ab7e7a | ||
|
|
ddb8e4d21a | ||
|
|
00d4f6141f | ||
|
|
7971a25c2a | ||
|
|
ab2411930a | ||
|
|
93f972bfca | ||
|
|
db638844d0 | ||
|
|
ba99eddc91 | ||
|
|
92428cee5d | ||
|
|
2c7d836925 | ||
|
|
7703dcf626 | ||
|
|
157520c4fc | ||
|
|
5bc728fa33 | ||
|
|
35fdc43b3f | ||
|
|
ae6ea29f2f | ||
|
|
4eac2cab31 | ||
|
|
87f4f57f8e | ||
|
|
a6e250fa43 | ||
|
|
b118079379 | ||
|
|
cb2d39f2a7 | ||
|
|
4cf549ff25 | ||
|
|
b5c6342dca | ||
|
|
46ec556921 | ||
|
|
33ae1a7bee | ||
|
|
87a3a67668 | ||
|
|
055b1e0163 | ||
|
|
2bd5ea2c68 | ||
|
|
1479a74198 | ||
|
|
9a0d25284c | ||
|
|
284e836992 | ||
|
|
43f5b31843 | ||
|
|
cada6cfc88 | ||
|
|
99f157927f | ||
|
|
664664394c | ||
|
|
a790901691 | ||
|
|
fdc70eaa62 | ||
|
|
b05a23e1ab | ||
|
|
9f6a0882e2 | ||
|
|
b351b21e55 | ||
|
|
ef22f06e92 | ||
|
|
8ea7426bc1 | ||
|
|
79e7e1727f | ||
|
|
98c33dd77c | ||
|
|
9c6504f6dd | ||
|
|
76c350bdcb | ||
|
|
106dcfd00e | ||
|
|
668c8cb0e2 | ||
|
|
3159bdf4dd | ||
|
|
97d2c0d187 | ||
|
|
0041ee3636 | ||
|
|
1ed523bec3 | ||
|
|
b131a6e9df | ||
|
|
56d9d370e9 | ||
|
|
a6efc4d92d | ||
|
|
a77db6e822 | ||
|
|
95a558941e | ||
|
|
867d69d0f2 | ||
|
|
a6d381da38 | ||
|
|
f0eb708b07 | ||
|
|
1d70698bd0 | ||
|
|
79871c8e21 | ||
|
|
25d5524213 | ||
|
|
8d21b73434 | ||
|
|
2ef01a314c | ||
|
|
a8b4aca5e6 | ||
|
|
67e7315eae | ||
|
|
a25a15d1c6 | ||
|
|
086588eeed | ||
|
|
44fa308681 | ||
|
|
6188287094 | ||
|
|
17d10afd65 | ||
|
|
89bd0e4397 | ||
|
|
1c1917f885 | ||
|
|
642377bd65 | ||
|
|
bb4668c071 | ||
|
|
689316db09 | ||
|
|
ad0c008a3e | ||
|
|
09e3698b37 | ||
|
|
6450ebfc6c | ||
|
|
e9f38ebcfd | ||
|
|
4dba31f534 | ||
|
|
04c1aad0dd | ||
|
|
6763f3ac33 | ||
|
|
afca704db0 | ||
|
|
eaec8fcddd | ||
|
|
f86fd52d6f | ||
|
|
f3f175570c | ||
|
|
729c80f910 | ||
|
|
fcaca558a0 | ||
|
|
983df9113e | ||
|
|
acf9874252 | ||
|
|
d7cf6bb11b | ||
|
|
558ea53cc2 | ||
|
|
87a6478430 | ||
|
|
cea673b267 | ||
|
|
4a5ab93c62 | ||
|
|
4c86fc8973 | ||
|
|
1c485ffb07 | ||
|
|
f283734f13 | ||
|
|
dca4ff0649 | ||
|
|
1975f2269e | ||
|
|
6fac9b42da | ||
|
|
dabae4c914 | ||
|
|
b1e9b4493d | ||
|
|
2fa207e728 | ||
|
|
7adcd909e7 | ||
|
|
50805fc2b5 | ||
|
|
3a1b7b6159 | ||
|
|
498b7c2436 | ||
|
|
4f17364305 | ||
|
|
9ebc115719 | ||
|
|
a6fa8c3a8e | ||
|
|
8187366c89 | ||
|
|
366ad01120 | ||
|
|
4da05e5914 | ||
|
|
3fb19b6a28 |
@@ -9,8 +9,8 @@ environment:
|
|||||||
REPO_DIR: &REPO_DIR c:\qbittorrent
|
REPO_DIR: &REPO_DIR c:\qbittorrent
|
||||||
CACHE_DIR: &CACHE_DIR c:\qbt_cache
|
CACHE_DIR: &CACHE_DIR c:\qbt_cache
|
||||||
|
|
||||||
QBT_VER_URL: http://builds.shiki.hu/appveyor/version
|
QBT_VER_URL: https://builds.shiki.hu/appveyor/version
|
||||||
QBT_LIB_URL: http://builds.shiki.hu/appveyor/qbt_libraries.7z
|
QBT_LIB_URL: https://builds.shiki.hu/appveyor/qbt_libraries.7z
|
||||||
|
|
||||||
# project directory
|
# project directory
|
||||||
clone_folder: *REPO_DIR
|
clone_folder: *REPO_DIR
|
||||||
14
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
**Please provide the following information**
|
||||||
|
|
||||||
|
### qBittorrent version and Operating System:
|
||||||
|
|
||||||
|
### If on linux, libtorrent and Qt version:
|
||||||
|
|
||||||
|
### What is the problem:
|
||||||
|
|
||||||
|
### What is the expected behavior:
|
||||||
|
|
||||||
|
### Steps to reproduce:
|
||||||
|
|
||||||
|
### Extra info(if any):
|
||||||
|
|
||||||
43
.travis.yml
@@ -3,7 +3,7 @@ language: cpp
|
|||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
osx_image: xcode7
|
osx_image: xcode7.3
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -17,6 +17,12 @@ env:
|
|||||||
global:
|
global:
|
||||||
- secure: "OI9CUjj4lTb0HwwIZU5PbECU3hLlAL6KC8KsbwohG8/O3j5fLcnmDsK4Ad9us5cC39sS11Jcd1kDP2qRcCuST/glVNhLkcjKkiQerOfd5nQ/qL4JYfz/1mfP5mdpz9jHKzpLUIG+TXkbSTjP6VVmsb5KPT+3pKEdRFZB+Pu9+J8="
|
- secure: "OI9CUjj4lTb0HwwIZU5PbECU3hLlAL6KC8KsbwohG8/O3j5fLcnmDsK4Ad9us5cC39sS11Jcd1kDP2qRcCuST/glVNhLkcjKkiQerOfd5nQ/qL4JYfz/1mfP5mdpz9jHKzpLUIG+TXkbSTjP6VVmsb5KPT+3pKEdRFZB+Pu9+J8="
|
||||||
- coverity_branch: coverity_scan
|
- coverity_branch: coverity_scan
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- os: osx
|
||||||
|
env: lt_branch=RC_1_0 qt=4 gui=true
|
||||||
|
- os: osx
|
||||||
|
env: lt_branch=RC_1_0 qt=4 gui=false
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
except:
|
except:
|
||||||
@@ -30,7 +36,10 @@ notifications:
|
|||||||
|
|
||||||
# container-based builds
|
# container-based builds
|
||||||
#sudo: false
|
#sudo: false
|
||||||
cache: ccache
|
cache:
|
||||||
|
ccache: true
|
||||||
|
directories:
|
||||||
|
- $HOME/hombebrew_cache
|
||||||
|
|
||||||
# opt-in Ubuntu Trusty
|
# opt-in Ubuntu Trusty
|
||||||
sudo: required
|
sudo: required
|
||||||
@@ -117,16 +126,40 @@ install:
|
|||||||
fi
|
fi
|
||||||
- |
|
- |
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||||
|
wget https://builds.shiki.hu/homebrew/version ;
|
||||||
|
if ! cmp --quiet "version" "$HOME/hombebrew_cache/version" ; then
|
||||||
|
echo "Cached files are different from server. Downloading new ones." ;
|
||||||
|
# First delete old files
|
||||||
|
rm -r "$HOME/hombebrew_cache" ;
|
||||||
|
mkdir "$HOME/hombebrew_cache";
|
||||||
|
cp "version" $HOME/hombebrew_cache ;
|
||||||
|
cd "$HOME/hombebrew_cache" ;
|
||||||
|
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar.rb ;
|
||||||
|
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar-1.0.10.el_capitan.bottle.tar.gz ;
|
||||||
|
wget https://builds.shiki.hu/homebrew/qt5.rb ;
|
||||||
|
wget https://builds.shiki.hu/homebrew/qt5-5.7.1_1.el_capitan.bottle.tar.gz ;
|
||||||
|
fi
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
brew update > /dev/null ;
|
brew update > /dev/null ;
|
||||||
brew install colormake ccache ;
|
brew install colormake ccache ;
|
||||||
brew outdated "pkg-config" || brew upgrade "pkg-config" ;
|
brew outdated "pkg-config" || brew upgrade "pkg-config" ;
|
||||||
# libtorrent-rasterbar 1.0.9
|
# Copy custom libtorrent bottle to homebrew's cache so it can find and install it
|
||||||
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/477d5060fa093883204d70323965375353e03084/Formula/libtorrent-rasterbar.rb ;
|
# Also install our custom libtorrent formula by passing the local path to it
|
||||||
|
# These 2 files are restored from Travis' cache.
|
||||||
|
cp "$HOME/hombebrew_cache/libtorrent-rasterbar-1.0.10.el_capitan.bottle.tar.gz" "$(brew --cache)" ;
|
||||||
|
brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb" ;
|
||||||
|
|
||||||
# Qt
|
# Qt
|
||||||
if [ "$qt" = 4 ]; then brew install qt && ln -s /usr/local/Cellar/qt/4.8.7_2/plugins /usr/local ; fi ;
|
if [ "$qt" = 4 ]; then brew install qt && ln -s /usr/local/Cellar/qt/4.8.7_2/plugins /usr/local ; fi ;
|
||||||
if [ "$qt" = 5 ]; then brew install qt5 && brew link --force qt5 && ln -s /usr/local/Cellar/qt5/5.6.0/plugins /usr/local ; fi ;
|
if [ "$qt" = 5 ]; then
|
||||||
|
# Copy custom qt5 bottle to homebrew's cache so it can find and install it
|
||||||
|
# Also install our custom qt5 formula by passing the local path to it
|
||||||
|
# These 2 files are restored from Travis' cache.
|
||||||
|
cp "$HOME/hombebrew_cache/qt5-5.7.1_1.el_capitan.bottle.tar.gz" "$(brew --cache)" ;
|
||||||
|
brew install "$HOME/hombebrew_cache/qt5.rb" ;
|
||||||
|
brew link --force qt5 ;
|
||||||
|
fi
|
||||||
|
|
||||||
# ccache
|
# ccache
|
||||||
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
|
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
|
||||||
|
|||||||
87
5B7CC9A2.asc
@@ -26,28 +26,67 @@ HiShCTSSDBJqFmhfjrCo0nISKnzyxgO/rY9vFlwXsKkTyL7s53ONkjwK34WmGnya
|
|||||||
tXdjBWShzAiTfF5hephfBSszmoBG2C8Jcu6P5n4buBY4RCsEa+6jE0R1vCtmpVwx
|
tXdjBWShzAiTfF5hephfBSszmoBG2C8Jcu6P5n4buBY4RCsEa+6jE0R1vCtmpVwx
|
||||||
WrXOeN2kGYMpAkPK1L69Le0FofgUDKlaFMv7KRl4R367xNRukYrsKwVlontJ+Y72
|
WrXOeN2kGYMpAkPK1L69Le0FofgUDKlaFMv7KRl4R367xNRukYrsKwVlontJ+Y72
|
||||||
X5t1BeRn8VSp0IzhssNXM8a4bTE8lvs889DOS2vgWEHIi0iyIesJYWPs4AKUw4rG
|
X5t1BeRn8VSp0IzhssNXM8a4bTE8lvs889DOS2vgWEHIi0iyIesJYWPs4AKUw4rG
|
||||||
EDwWxtTS0a7Rfx3DxLkCDQRXDSCMARAAqMIVJizEJp205c546IN75xeYiFszNXcs
|
EDwWxtTS0a7Rfx3DxLRWc2xlZGdlaGFtbWVyOTk5IChVc2VkIGZvciBzaWduaW5n
|
||||||
3768IY8bOoWj+rTwt2wIwtL/3O5K2dG79CSt2H5o6BPKmq43tOO60YW3Yk3m9BB/
|
IGdpdCBjb21taXRzL3RhZ3MvZXRjLikgPGhhbW1lcmVkOTk5QHFiaXR0b3JyZW50
|
||||||
gnAVqk0QOPr5O8+yeBzdElU8CZh6y6zZMWugSkNmTDm6jZzPhgNjcjrit/dl9+0D
|
Lm9yZz6JAh8EMAEIAAkFAlhie1ICHQAACgkQbkotAlt8yaILIhAAp25o1BbUG2Zk
|
||||||
GqJQcqoD8WzEWNcWrMHVz9cDewnLSVkwR758mZMaIiL7R10MZ++tNrC0j69UINqx
|
At3cSrTFnZSCA7nEygbSUv1Uek33JZfY0Apw5qEM8lQCMZk+mhdrSQCYUJcQlruN
|
||||||
+9z1r1J07+NNnxqSTxVRcbjPYtM9E+tUiVFS2HPWN9ShVDkBAEdoWh90qzRaMiFl
|
zJcJf4CH+VGE23xkI3Kf0nGp9Cjn/q6b1hLIPe5rimvw5pTAejFtebcYY/ZJIB8Z
|
||||||
2NGNGOD1iHx/xr06RMeGEEXt2vhSlhfMW2YQW+UD2jzlFbARf53v39MUKKscGuIp
|
H1ebuzfqBZ/9k7eYTarZ/ZsgG8YptB0RXBQWOMaSEKwdeo2m7HXHgK3blQiqbuJJ
|
||||||
BhxGw3JCq4l6qLW/bDkgnoXlOhZDmhQm6OpsjAyk9IEdd3ponSc7yYD3mUkJKR9e
|
uyPbid01Wus4AVN47/FKgDNswPs8irYZsu5yakgpi2KLycGDtSiN5XFHI4xbC0zM
|
||||||
TaALD5t6TQGyNHakb4UfoXtE2RR78cbPlLIwag7eQ8GsNA+dfjowmOZdojx3ROsH
|
srR7Cz0/fC+klhGcuxbw0V0It7UUIitgCcTPHXkukUU8i2+AGMyKa1HjchsXDdLg
|
||||||
ZdGQwb0YFLjuKAusA3TY+lCfbS6kzE2iI2DuaW+3dICcLrYuibbVb0CBNHyD+8KE
|
DIs6KIurp2ve7znKOz7h1aX8cOBmB/QYeYAx9jRRkePMIRT8V1lRwfvJlJxx1+G3
|
||||||
tczdur/wm0lhqyVJkGyZKZT8C2cPxywKgy1Rn6F8Yfmj0Lna3nvtaZu0ZUS4/8Li
|
e2gJLjqTN8a08KHHjdY/S0ZFERxSlmOym2uf/y6di1ipDPxo8xvDuS5kDbdZLC0t
|
||||||
t5PcOso1lSmYBuD6yq+GEAMCnUmn1Pm8eZRMlxxQuTPvyJKQrRDhbtAAr472MSno
|
XijlsH8ONK27KNuWhucG8zHzKQvnPw2qN06SZq4FjbSmAkkuYs56heLEXMzFr75k
|
||||||
JKlS4SfaUF0AEQEAAYkCHwQYAQgACQUCVw0gjAIbDAAKCRBuSi0CW3zJomZDD/9I
|
SE8rUoQQ+ABG9gU46GEvKlZxqSwXgGnb1X6K7h8svjMh/NlAU358p8Sra4Ru5tz4
|
||||||
Jmzd5hiEzntlp84pyIJcfyIRe4KImvldAy6T02OSIbF1HzCNnwmqIPob6MOdMZ+K
|
jUu9MoVEw5Lbjcrsnp6/4Kk1Q2ckBNt43nv8/+C7NsC3xi6BrOInuaKHZ4QsTuzJ
|
||||||
NwMK0htRkrRr/zM034+lBiWKZt+tVYHu49ioTYXEjAc5qDJE09Sq7HceQnhgE48f
|
m1/A4zlKRnUi6T98DXfIYnNuV9NSmAWJAjkEEwEIACMFAlhiemMCGwMHCwkIBwMC
|
||||||
1n54XGT5G2w5gw+/a8Qn1SceE44VwXafL3E1gKaOrrsb1UH/AJhp+W4VMu+7bLXu
|
AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBuSi0CW3zJor6yD/9N2U0INx0nYpGkmvah
|
||||||
7h1tN6v2PhvCYvBt3zyy8Q8xfJ2x7/D1lbF8ATJAiZ/km9x5bRm7OGRliVYaUe1n
|
yVG/vw2S6hhKK+03AN+RrtddNRg4aBf/gmOvRWQhAmFnXOBA7fO09wgcljaV5tVb
|
||||||
yR42fZOj3CBmAR0+lZLgjriqdMXrs+qlBbrmAhkn0XPQXAeaPifKoKIGDAUWIsqD
|
MYyYZvHhK0o2/sli2p/M5N8ZxchRHypjxUSEyG9ZQ06QG5DVhh4HtM8nIN+UcwTV
|
||||||
HqM7imMGT+MR9APfSw8M4enOJWL+HnKpVBEARCEDpaFpJ3u7QRucFybpEhvIymoN
|
C5QjyoWZvHf+tNroyFeh7zT+w4kX1VxgynTQr5LGdYsrVA3CFyT3zsBWV3dMae23
|
||||||
ftyw+urId2Eg2K33NypeZo3M1K2LC65f2Ta7f/sZcIDUTbgW+m334fgVl1KptDA5
|
22CHOirsBBLwairHUsWW+BdThT3MkKYpTEV0jkH4OyAXhJYcS5IjjtKQ8UpZE9dw
|
||||||
DX3U9lTci7mi4uPuAFtbWrB1di4jYrxXYuzFm5g4xTb0Hw3kYIB6WXF+I7i0JaGO
|
f4saJ0TnXNe7goPRZtH7UjPwfVbtYK4y8QklWUTRxgoBxNwSC5X7Flg+3xXxE/VU
|
||||||
THxPC5X5lIAZrYrkxh+1n1Y1CY+TC8JcTzwORJIbFFm9tD/BHXa4849k4DVvFYCZ
|
U4cehyRkH64i7MJDoFkqh5JtjkgIz+kuTTXb7xR0Wf+JXrGMybZTR8xth2TEMC20
|
||||||
khq+/56FKZfoVByhB+x+2GaMlsBm1uPniO4lAakFPpIi0kaap4UVayQ/7ak+Bhsc
|
1FT5L5+0vH1WRzL7bhlaU3EXyCnoH8sDvMEClZbibbew+rf7fC3tFU41ohUT0HDl
|
||||||
AIHZUy6NtgZkuvW3xdpwp07LYo2ilhMI8RnzmtoRmg==
|
zlyfVjRvBHWMTgfpWKBV2m/qP941xTJ9VHxOlAB02XKUZYwFt07CpH+yjMOCOzA4
|
||||||
=tDGM
|
cTPBD3mGRuft0V0BJ8bA5bcTly/GBciRX0Y5oIeHZGgq2czb0sywSYT6mPoQMFNM
|
||||||
|
B+Cwr4pm90r1DMMfW518onF2itwyN/Id0FsWDhsLJHKluBJw52C3OnxCuToVutTm
|
||||||
|
xntqpPVv62LaeVeWQqxIieTJErRQc2xlZGdlaGFtbWVyXzk5OSAoVXNlZCBmb3Ig
|
||||||
|
c2lnbmluZyBnaXQgY29tbWl0cy90YWdzL2V0YykgPGhhbW1lcmVkOTk5QGdtYWls
|
||||||
|
LmNvbT6JAjkEEwEIACMFAlhifeICGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIX
|
||||||
|
gAAKCRBuSi0CW3zJolcCD/9xPBNEkFtnhTW89th0TFZnB5oykCQjyefquvQs8KWT
|
||||||
|
C92/1VizHi4ZxDehHWP9IKVWT3ZJthj5ZXBSedyl1tHnwkyrUYBW9roQwtDWPncK
|
||||||
|
pXl/HsE6p3q6EIus+g6YJo4UvYachJFAZATZp1WDBPIswziHGzaL0tndFWZuVM8V
|
||||||
|
QD0tfPQsS1qCDVv6+B1JWZDnA1JzdSG/uzPhL95q/ff6JmNbfSAVedK2PyqYshnC
|
||||||
|
KWBx6Yna/0ColBuDFho8+bDuHPQcM35xyjPosVD7moXQiY4yMAJ+VzwEBaCFleI0
|
||||||
|
RBWw8/+qyoFqfIKwdq8G+7I9LjWpBiN2+uQBZ+OAvsMWyRShLopxt3JluPTtL6xb
|
||||||
|
Ca6dglOdlaOS/A6FK7u05k/8kQMDS5Jq2/rpfTPRl1/weCaJZgfRIBosk1Mon/pR
|
||||||
|
p1zd0abM4t7BcGQpwSkKAmqlKCrWf886EFQT0CJTBo8q7pzgpVraWWPVsmAOdkfU
|
||||||
|
YcKBgz1A2uMSAxypkSzaDZkIVj6I7gwiGk7IMYx1OK7Ev46h/x4Z7kgT0y3DYYOq
|
||||||
|
ggVEKQ+15Krn7bZ35s8vbZdfnVKPSXdCC8jkIMBmGmRX6cgZZ3OXZlrrHht5icgJ
|
||||||
|
5Z2d1M4JUoEZVUr2xNZkkaMk01NAIpGgKvIS6yHuj6vE4GMJ+A/qEW6J60/3YHRe
|
||||||
|
0bkCDQRXDSCMARAAqMIVJizEJp205c546IN75xeYiFszNXcs3768IY8bOoWj+rTw
|
||||||
|
t2wIwtL/3O5K2dG79CSt2H5o6BPKmq43tOO60YW3Yk3m9BB/gnAVqk0QOPr5O8+y
|
||||||
|
eBzdElU8CZh6y6zZMWugSkNmTDm6jZzPhgNjcjrit/dl9+0DGqJQcqoD8WzEWNcW
|
||||||
|
rMHVz9cDewnLSVkwR758mZMaIiL7R10MZ++tNrC0j69UINqx+9z1r1J07+NNnxqS
|
||||||
|
TxVRcbjPYtM9E+tUiVFS2HPWN9ShVDkBAEdoWh90qzRaMiFl2NGNGOD1iHx/xr06
|
||||||
|
RMeGEEXt2vhSlhfMW2YQW+UD2jzlFbARf53v39MUKKscGuIpBhxGw3JCq4l6qLW/
|
||||||
|
bDkgnoXlOhZDmhQm6OpsjAyk9IEdd3ponSc7yYD3mUkJKR9eTaALD5t6TQGyNHak
|
||||||
|
b4UfoXtE2RR78cbPlLIwag7eQ8GsNA+dfjowmOZdojx3ROsHZdGQwb0YFLjuKAus
|
||||||
|
A3TY+lCfbS6kzE2iI2DuaW+3dICcLrYuibbVb0CBNHyD+8KEtczdur/wm0lhqyVJ
|
||||||
|
kGyZKZT8C2cPxywKgy1Rn6F8Yfmj0Lna3nvtaZu0ZUS4/8Lit5PcOso1lSmYBuD6
|
||||||
|
yq+GEAMCnUmn1Pm8eZRMlxxQuTPvyJKQrRDhbtAAr472MSnoJKlS4SfaUF0AEQEA
|
||||||
|
AYkCHwQYAQgACQUCVw0gjAIbDAAKCRBuSi0CW3zJomZDD/9IJmzd5hiEzntlp84p
|
||||||
|
yIJcfyIRe4KImvldAy6T02OSIbF1HzCNnwmqIPob6MOdMZ+KNwMK0htRkrRr/zM0
|
||||||
|
34+lBiWKZt+tVYHu49ioTYXEjAc5qDJE09Sq7HceQnhgE48f1n54XGT5G2w5gw+/
|
||||||
|
a8Qn1SceE44VwXafL3E1gKaOrrsb1UH/AJhp+W4VMu+7bLXu7h1tN6v2PhvCYvBt
|
||||||
|
3zyy8Q8xfJ2x7/D1lbF8ATJAiZ/km9x5bRm7OGRliVYaUe1nyR42fZOj3CBmAR0+
|
||||||
|
lZLgjriqdMXrs+qlBbrmAhkn0XPQXAeaPifKoKIGDAUWIsqDHqM7imMGT+MR9APf
|
||||||
|
Sw8M4enOJWL+HnKpVBEARCEDpaFpJ3u7QRucFybpEhvIymoNftyw+urId2Eg2K33
|
||||||
|
NypeZo3M1K2LC65f2Ta7f/sZcIDUTbgW+m334fgVl1KptDA5DX3U9lTci7mi4uPu
|
||||||
|
AFtbWrB1di4jYrxXYuzFm5g4xTb0Hw3kYIB6WXF+I7i0JaGOTHxPC5X5lIAZrYrk
|
||||||
|
xh+1n1Y1CY+TC8JcTzwORJIbFFm9tD/BHXa4849k4DVvFYCZkhq+/56FKZfoVByh
|
||||||
|
B+x+2GaMlsBm1uPniO4lAakFPpIi0kaap4UVayQ/7ak+BhscAIHZUy6NtgZkuvW3
|
||||||
|
xdpwp07LYo2ilhMI8RnzmtoRmg==
|
||||||
|
=UBeB
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
cmake_policy(VERSION 3.5)
|
cmake_policy(VERSION 3.5)
|
||||||
|
|
||||||
project(qBittorrent VERSION 3.4.0.0)
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
|
||||||
|
include(FunctionReadVersion)
|
||||||
|
|
||||||
set(VER_MAJOR ${qBittorrent_VERSION_MAJOR})
|
read_version("${CMAKE_CURRENT_SOURCE_DIR}/version.pri" VER_MAJOR VER_MINOR VER_BUGFIX VER_BUILD VER_STATUS)
|
||||||
set(VER_MINOR ${qBittorrent_VERSION_MINOR})
|
# message(STATUS "Project version is: ${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}.${VER_BUILD} (${VER_STATUS})")
|
||||||
set(VER_BUGFIX ${qBittorrent_VERSION_PATCH})
|
|
||||||
set(VER_BUILD ${qBittorrent_VERSION_TWEAK})
|
project(qBittorrent VERSION ${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}.${VER_BUILD})
|
||||||
set(VER_STATUS "alpha") # Should be empty for stable releases!
|
|
||||||
|
|
||||||
# Don't touch the rest part
|
|
||||||
set(PROJECT_VERSION "${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}")
|
set(PROJECT_VERSION "${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}")
|
||||||
|
|
||||||
if (NOT VER_BUILD EQUAL 0)
|
if (NOT VER_BUILD EQUAL 0)
|
||||||
@@ -28,7 +27,6 @@ add_definitions(-DVERSION_BUILD=${VER_BUILD})
|
|||||||
# } else {
|
# } else {
|
||||||
add_definitions(-DVERSION="v${PROJECT_VERSION}")
|
add_definitions(-DVERSION="v${PROJECT_VERSION}")
|
||||||
# }
|
# }
|
||||||
list(APPEND CMAKE_MODULE_PATH ${qBittorrent_SOURCE_DIR}/cmake/Modules)
|
|
||||||
|
|
||||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og")
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og")
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
|
|||||||
127
Changelog
@@ -1,3 +1,130 @@
|
|||||||
|
* Fri Mar 03 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.11
|
||||||
|
- FEATURE: Always show progress and remaining bytes for unselected files. (sledgehammer999)
|
||||||
|
- FEATURE: Allow to change priority for unselected files through the combobox like it is done via the context menu. (sledgehammer999)
|
||||||
|
- FEATURE: Remove settings to exchange trackers. It wasn't used by non-libtorrent clients. Also it has a privacy risk and you might be DDoSing someone. (sledgehammer999)
|
||||||
|
- FEATURE: Put temp files in .qBittorrent directory. Closes #4462. (Chocobo1)
|
||||||
|
- FEATURE: Use the numbers from tracker scrape response. Closes #5048, #6117. (Chocobo1)
|
||||||
|
- FEATURE: Implement category filter widget. Show categories in tree mode when subcategories are enabled. (glassez)
|
||||||
|
- FEATURE: Allow to toggle columns in searchtab (thalieht)
|
||||||
|
- FEATURE: PeerList: allow to hide zero values for the "uploaded" and "downloaded" columns (thalieht)
|
||||||
|
- FEATURE: Display more information in tracker tab (ngosang)
|
||||||
|
- FEATURE: Use Ctrl+F to search torrents. Closes #5797. (Tim Delaney)
|
||||||
|
- FEATURE: Transferlist: add hotkeys for double click and recheck selected torrents (thalieht)
|
||||||
|
- FEATURE: Add hotkey for execution log tab, Trackerlist, Peerlist etc (thalieht)
|
||||||
|
- FEATURE: Seperate seeds from peers for DHT, PeX and LSD (thalieht)
|
||||||
|
- BUGFIX: Do not remove added files unconditionally. Closes #6248 (Eugene Shalygin)
|
||||||
|
- BUGFIX: Ignore mouse wheel events in Advanced Settings. Closes #866. (Chocobo1)
|
||||||
|
- BUGFIX: Add queue repair code. It should fix missing torrents after restarting. (Eugene Shalygin, nxd4)
|
||||||
|
- BUGFIX: Fetch torrent status when generating final fastresume data. It should fix missing torrents after restarting. (Eugene Shalygin)
|
||||||
|
- BUGFIX: Fix queue overload for add torrent at session start. It should fix missing torrents after restarting. (falco)
|
||||||
|
- BUGFIX: After files relocate, don't remove the old folder even if it is empty. (Chocobo1)
|
||||||
|
- BUGFIX: Fix finding 'English' item in language dropdown menu when an unrecognized locale is requested. Closes #6109. (sledgehammer999)
|
||||||
|
- BUGIFX: Speedlimitdlg: raise slider default value to 10000. Closes #6150. (Chocobo1)
|
||||||
|
- BUGFIX: TransferListWidget: keep columns width even if they are hidden on qBittorrent startup (unless something goes wrong) (thalieht)
|
||||||
|
- BUGFIX: fix index overflow for torrents with invalid meta data or empty progress (Falco)
|
||||||
|
- BUGFIX: Immediately update torrent_status after manipulating super seeding mode. Partially fixes #6072. (sledgehammer999)
|
||||||
|
- BUGFIX: Use case-insensitive comparsion for torrent content window. Closes #6327. (Chocobo1)
|
||||||
|
- BUGFIX: Fixed sort order for datetime columns with empty values (closes #2988) (Vladimir Sinenko)
|
||||||
|
- BUGFIX: Disable proxy in WebUI HTTP server. Closes #6349. (Eugene Shalygin)
|
||||||
|
- COSMETIC: Use a disabled progressbar's palette for unselected files. (sledgehammer999)
|
||||||
|
- COSMETIC: Support fallback when selecting theme icons (Eugene Shalygin)
|
||||||
|
- COSMETIC: Do not resize SVG icons (Eugene Shalygin)
|
||||||
|
- COSMETIC: Align text to the right in columns that handle numbers for PeerList and SearchTab (thalieht)
|
||||||
|
- COSMETIC: Increased number of digits after the decimal point for Gibibytes and above (thalieht)
|
||||||
|
- COSMETIC: Use non-breaking spaces between numbers and units (thalieht)
|
||||||
|
- WEBUI: Fix proxy type bug (Oke Atime)
|
||||||
|
- WEBUI: Use the correct value for KEY_TORRENT_NUM_COMPLETE/KEY_TORRENT_NUM_INCOMPLETE (Chocobo1)
|
||||||
|
- WEBUI: Make torrents table scrollable horizontally (buinsky)
|
||||||
|
- WEBUI: Make torrent peers table scrollable horizontally (buinsky)
|
||||||
|
- WEBUI: Add tooltips to dynamic table header (buinsky)
|
||||||
|
- WEBUI: Implement dynamic table columns resizing, reordering and hiding (buinsky)
|
||||||
|
- WEBUI: Add some missing columns to dynamic tables (buinsky)
|
||||||
|
- WEBUI: Make too tall menus scrollable (buinksy)
|
||||||
|
- WEBUI: Prevent text wrapping in menus (buinsky)
|
||||||
|
- WEBUI: Add a vertical separator between columns (buinsky)
|
||||||
|
- WEBUI: Implement resizable progress bar in "Done" column (buinsky)
|
||||||
|
- WEBUI: Fix scrollbar covers menu item with long text (buinsky)
|
||||||
|
- WEBUI: Remove 300px limit of column width (buinsky)
|
||||||
|
- WEBUI: Avoid lags in firefox on resizing progress column (buinsky)
|
||||||
|
- WEBUI: Fix category in torrent upload. Closes #6260 (ngosang)
|
||||||
|
- WEBUI: Turn off port forwarding of WebUI by default for GUI users (Chocobo1)
|
||||||
|
- WEBUI: Exclude insecure ciphers. Fixes security issues reported by @beardog108 privately. (Chocobo1)
|
||||||
|
- WEBUI: Avoid clickjacking attacks. Fixes security issues reported by @beardog108 privately. (ngosang)
|
||||||
|
- WEBUI: Add X-XSS-Protection, X-Content-Type-Options, CSP header. Fixes security issues reported by @beardog108 privately. (Chocobo1)
|
||||||
|
- WEBUI: Escape various values that might contain injected html. Fixes security issues reported by @beardog108 privately. (Chocobo1)
|
||||||
|
- WEBUI: Bump API_VERSION to 12.
|
||||||
|
- SEARCH: Update extratorrent plugin. Closes #6261 (ngosang)
|
||||||
|
- SEARCH: SearchTab: can now save sorting column changes (thalieht)
|
||||||
|
- SEARCH: Use case-insensitive sort for Name column in Search tab. Closes #407. (Chocobo1)
|
||||||
|
- RSS: Fix tab order in RSS downloader. Closes #6164. (Tim Delaney)
|
||||||
|
- RSS: Move old RSS items to separate config file. Closes #6167. (Tim Delaney)
|
||||||
|
- RSS: Episode filter code refactoring (Tim Delaney)
|
||||||
|
- RSS: Allow resetting rule to no category. Closes #5539. (Tim Delaney)
|
||||||
|
- RSS: Save rule on enable/disable even if not selected. Closes #6163. (Tim Delaney)
|
||||||
|
- RSS: Allow | in RSS must contain. Closes #6171. (Tim Delaney)
|
||||||
|
- RSS: RSS use red text to indicate invalid filter. Closes #6165. (Tim Delaney)
|
||||||
|
- RSS: Allow episode zero (special) and leading zeroes in RSS episode filter. (Tim Delaney)
|
||||||
|
- RSS: RSS parse torrent episodes like 1x01 as well as S01E01. Closes #2749. (Tim Delaney)
|
||||||
|
- RSS: RSS allow infinite range to extend beyond current season. Closes #800, #3876, #6170. (Tim Delaney)
|
||||||
|
- RSS: Improve UI responsiveness during RSS downloading. Closes #873, #1089, #1235, #5423. (Tim Delaney)
|
||||||
|
- RSS: Show name of feed list and sort rules in editor. Closes #3782, #6281. (Tim Delaney)
|
||||||
|
- RSS: Fix regex matching. Closes #6337. (Tim Delaney)
|
||||||
|
- MACOS: Fix qbittorrent-nox build (Oke Atime)
|
||||||
|
- LINUX: fixes default indicator name (Bilal Elmoussaoui)
|
||||||
|
- OTHER: Workaround problem with moc from Qt4 and #if (Eugene Shalygin)
|
||||||
|
- OTHER: Print warning to the user if stacktrace contains no function names (Eugene Shalygin)
|
||||||
|
- OTHER: Various cmake fixes (Eugene Shalygin)
|
||||||
|
- OTHER: Fix finding qmake in configure when cross-compiling (Zach Bacon)
|
||||||
|
|
||||||
|
* Sat Dec 17 2016 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.10
|
||||||
|
- BUGFIX: Fix share ratio limiting. Broken by commit 259b5e51c49b744. Closes #6039 #6048. (sledgehammer999)
|
||||||
|
- BUGFIX: Case insensitive sort for client column. Closes #6054. (Oke Atime)
|
||||||
|
- BUGFIX: Make resume/pause menu items clickable. Closes #6040. (Oke Atime)
|
||||||
|
- WINDOWS: Make the updater to look for the x64 installer if running x64 version. (sledgehammer999)
|
||||||
|
|
||||||
|
* Wed Dec 14 2016 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.9
|
||||||
|
- BUGFIX: Fix slider for per torrent speed limits when no global speed limit has been set. Closes #6046. (sledgehammer999)
|
||||||
|
- BUGFIX: Fix GUI for proxy settings. Closes #6045. (sledgehammer999)
|
||||||
|
- OSX: Correctly migrate settings/rss/usage stats in macOS. Closes #6041. (sledgehammer999)
|
||||||
|
|
||||||
|
* Wed Dec 14 2016 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.8
|
||||||
|
- FEATURE: Start using new libtorrent 1.1.x APIs (needs at least 1.1.2). Still unofficial support. (glassez, sledgehammer999)
|
||||||
|
- FEATURE: Add a new DHT bootstrap node run by libtorrent author arvidn. (sledgehammer999)
|
||||||
|
- FEATURE: Option to disable tracker's favicon download. (sledgehammer999)
|
||||||
|
- FEATURE: Shift + scroll = horizontal scroll. Closes #5980. Only for TransferListWidget, PeerListWidget. (Chocobo1)
|
||||||
|
- BUGFIX: Actually set new path as default when checkBox is enabled in Add New Torrent dialog. (erikssm)
|
||||||
|
- BUGFIX: Properly fix the handling of default save path store/load. (sledgehammer999)
|
||||||
|
- BUGFIX: Fix crash when restoring from tray. Closes #5854. (Chocobo1)
|
||||||
|
- BUGFIX: Export torrents added only after the setting was enabled. (sledgehammer999)
|
||||||
|
- BUGFIX: Delete old rss favicon before assigning new one. (sledgehammer999)
|
||||||
|
- BUGFIX: Don't revert save path value in the Dialog when metadata are received. Closes #5482. (sledgehammer999)
|
||||||
|
- BUGFIX: Don't ever stop seeding forced torrents. Closes #5784. (sledgehammer999)
|
||||||
|
- BUGFIX: Fix potential crash in TransferList widget. Closes #5873. (Chocobo1)
|
||||||
|
- BUGFIX: Sort torrent names case insensitively. (Yez Ezey)
|
||||||
|
- BUGFIX: Fix mistake in getting values for sorting in TransferList widget. (Anton Lashkov)
|
||||||
|
- BUGFIX: Fix memory leaks. (dzmat, Chocobo1)
|
||||||
|
- WEBUI: Fix webui port overflow. (thalieht)
|
||||||
|
- WEBUI: Changed meaning of the value of the 'dl_limit', 'up_limit', 'alt_dl_limit' and 'alt_up_limit' tokens. The value is expressed in bytes and not in KiB. (sledgehammer999)
|
||||||
|
- WEBUI: Don't request client SSL certificate. Closes #3883. (borouhin)
|
||||||
|
- WEBUI: Bump API_VERSION and API_VERSION_MIN to 11.
|
||||||
|
- SEARCH: Fixed extratorrent search not working Closes #5736 #5753. (Yez Ezey)
|
||||||
|
- SEARCH: Update Demonoid plugin. (ngosang)
|
||||||
|
- SEARCH: Remove TorrentReactor plugin. (ngosang)
|
||||||
|
- SEARCH: Fix python auto install, deletion of installer and use 3.5.x series for Vista+. Closes #5871. (sledgehammer999)
|
||||||
|
- SEARCH: Set /usr/local/bin before default PATH on macOS. closes #5639 #5571. This enables finding newer python installs. (Yez Ezey)
|
||||||
|
- COSMETIC: Log: set embedded Tracker [OFF] msg type as info. (thalieht)
|
||||||
|
- COSMETIC: Remove (mostly) useless log warnings about tracker's favicon. (sledgehammer999)
|
||||||
|
- COSMETIC: Change RSS view layout to horizontal. Closes #5920. (Chocobo1)
|
||||||
|
- OSX: Fix crash on exit using Qt4. (Yez Ezey)
|
||||||
|
- OSX: Change QSettings to IniFormat on macOS. Closes #5770 #5808. (Yez Ezey)
|
||||||
|
- LINUX: Workaround a Qt5 bug which results in a flood of network interface change singals. (Eugene Shalygin)
|
||||||
|
- OTHER: Turkish translation for installer. (Burak Yavuz)
|
||||||
|
- OTHER: Update portugueseBR for installer. (DaRKSoM)
|
||||||
|
- OTHER: Update portuguese for installer. (EdwardLinux)
|
||||||
|
- OTHER: Add --disable-qt-dbus to configure if $host_os is macOS. (Yez Ezey)
|
||||||
|
- OTHER: New translations: Icelandic, Latvian, Malay, Occitan, Uzbek.
|
||||||
|
- OTHER: A whole lot of code refactoring by various people.
|
||||||
|
|
||||||
* Sun Sep 11 2016 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.7
|
* Sun Sep 11 2016 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.7
|
||||||
- FEATURE: Delete torrent+files with Shift+Delete (pieniacy)
|
- FEATURE: Delete torrent+files with Shift+Delete (pieniacy)
|
||||||
- BUGFIX: Fix 6-hour speedplot point push rate. Close #5545 (Daniel Segesdi)
|
- BUGFIX: Fix 6-hour speedplot point push rate. Close #5545 (Daniel Segesdi)
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
find_package(PkgConfig QUIET)
|
find_package(PkgConfig QUIET)
|
||||||
|
|
||||||
|
macro(_detect_boost_components _outComponets librariesList)
|
||||||
|
string(REGEX MATCHALL "boost_[a-z_]+[-a-z]*" _boost_libraries "${librariesList}")
|
||||||
|
string(REGEX REPLACE "boost_([a-z_]+)[-a-z]*" "\\1" ${_outComponets} "${_boost_libraries}")
|
||||||
|
endmacro()
|
||||||
|
|
||||||
if(PKG_CONFIG_FOUND)
|
if(PKG_CONFIG_FOUND)
|
||||||
pkg_check_modules(PC_LIBTORRENT_RASTERBAR QUIET libtorrent-rasterbar)
|
pkg_check_modules(PC_LIBTORRENT_RASTERBAR QUIET libtorrent-rasterbar)
|
||||||
endif()
|
endif()
|
||||||
@@ -62,13 +67,33 @@ endif()
|
|||||||
set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
set(LibtorrentRasterbar_INCLUDE_DIRS ${LibtorrentRasterbar_INCLUDE_DIR})
|
set(LibtorrentRasterbar_INCLUDE_DIRS ${LibtorrentRasterbar_INCLUDE_DIR})
|
||||||
|
|
||||||
if(NOT Boost_SYSTEM_FOUND OR NOT Boost_CHRONO_FOUND OR NOT Boost_RANDOM_FOUND)
|
# Without pkg-config, we can't possibly figure out the correct boost dependencies
|
||||||
find_package(Boost REQUIRED COMPONENTS date_time system chrono random thread)
|
if (LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES)
|
||||||
set(LibtorrentRasterbar_LIBRARIES
|
set(_boost_components "${LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES}")
|
||||||
${LibtorrentRasterbar_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
else(LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES)
|
||||||
set(LibtorrentRasterbar_INCLUDE_DIRS
|
if(PC_LIBTORRENT_RASTERBAR_FOUND)
|
||||||
${LibtorrentRasterbar_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
|
_detect_boost_components(_boost_components "${PC_LIBTORRENT_RASTERBAR_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
# all possible boost dependencies
|
||||||
|
set(_boost_components
|
||||||
|
date_time
|
||||||
|
system
|
||||||
|
chrono
|
||||||
|
random
|
||||||
|
thread
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
endif(LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES)
|
||||||
|
|
||||||
|
list(SORT _boost_components)
|
||||||
|
message(STATUS "Libtorrent Boost dependencies: ${_boost_components}")
|
||||||
|
find_package(Boost REQUIRED COMPONENTS ${_boost_components})
|
||||||
|
set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
foreach(_boost_cmpnt IN LISTS _boost_components)
|
||||||
|
list(APPEND LibtorrentRasterbar_LIBRARIES "Boost::${_boost_cmpnt}")
|
||||||
|
endforeach(_boost_cmpnt)
|
||||||
|
|
||||||
|
set(LibtorrentRasterbar_INCLUDE_DIRS ${LibtorrentRasterbar_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
list(FIND LibtorrentRasterbar_DEFINITIONS -DTORRENT_USE_OPENSSL LibtorrentRasterbar_ENCRYPTION_INDEX)
|
list(FIND LibtorrentRasterbar_DEFINITIONS -DTORRENT_USE_OPENSSL LibtorrentRasterbar_ENCRYPTION_INDEX)
|
||||||
if(LibtorrentRasterbar_ENCRYPTION_INDEX GREATER -1)
|
if(LibtorrentRasterbar_ENCRYPTION_INDEX GREATER -1)
|
||||||
@@ -83,10 +108,7 @@ include(FindPackageHandleStandardArgs)
|
|||||||
# if all listed variables are TRUE
|
# if all listed variables are TRUE
|
||||||
find_package_handle_standard_args(LibtorrentRasterbar DEFAULT_MSG
|
find_package_handle_standard_args(LibtorrentRasterbar DEFAULT_MSG
|
||||||
LibtorrentRasterbar_LIBRARY
|
LibtorrentRasterbar_LIBRARY
|
||||||
LibtorrentRasterbar_INCLUDE_DIR
|
LibtorrentRasterbar_INCLUDE_DIR)
|
||||||
Boost_SYSTEM_FOUND
|
|
||||||
Boost_CHRONO_FOUND
|
|
||||||
Boost_RANDOM_FOUND)
|
|
||||||
|
|
||||||
mark_as_advanced(LibtorrentRasterbar_INCLUDE_DIR LibtorrentRasterbar_LIBRARY
|
mark_as_advanced(LibtorrentRasterbar_INCLUDE_DIR LibtorrentRasterbar_LIBRARY
|
||||||
LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES
|
LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES
|
||||||
|
|||||||
28
cmake/Modules/FunctionReadVersion.cmake
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# function for parsing version variables that are set in version.pri file
|
||||||
|
# the version identifiers there are defined as follows:
|
||||||
|
# VER_MAJOR = 3
|
||||||
|
# VER_MINOR = 4
|
||||||
|
# VER_BUGFIX = 0
|
||||||
|
# VER_BUILD = 0
|
||||||
|
# VER_STATUS = alpha
|
||||||
|
|
||||||
|
function(read_version priFile outMajor outMinor outBugfix outBuild outStatus)
|
||||||
|
file(STRINGS ${priFile} _priFileContents REGEX "^VER_.+")
|
||||||
|
# message(STATUS "version.pri version contents: ${_priFileContents}")
|
||||||
|
# the _priFileContents variable contains something like the following:
|
||||||
|
# VER_MAJOR = 3;VER_MINOR = 4;VER_BUGFIX = 0;VER_BUILD = 0;VER_STATUS = alpha # Should be empty for stable releases!
|
||||||
|
set(_regex "VER_MAJOR += +([0-9]+);VER_MINOR += +([0-9]+);VER_BUGFIX += +([0-9]+);VER_BUILD += +([0-9]+);VER_STATUS += +([0-9A-Za-z]+)?")
|
||||||
|
# note quotes around _regex, they are needed because the variable contains semicolons
|
||||||
|
string(REGEX MATCH "${_regex}" _tmp "${_priFileContents}")
|
||||||
|
if (NOT _tmp)
|
||||||
|
message(FATAL_ERROR "Could not detect project version number from ${priFile}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# message(STATUS "Matched version string: ${_tmp}")
|
||||||
|
|
||||||
|
set(${outMajor} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||||
|
set(${outMinor} ${CMAKE_MATCH_2} PARENT_SCOPE)
|
||||||
|
set(${outBugfix} ${CMAKE_MATCH_3} PARENT_SCOPE)
|
||||||
|
set(${outBuild} ${CMAKE_MATCH_4} PARENT_SCOPE)
|
||||||
|
set(${outStatus} ${CMAKE_MATCH_5} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
@@ -5,11 +5,23 @@
|
|||||||
macro (target_link_qt_components target)
|
macro (target_link_qt_components target)
|
||||||
if (QT4_FOUND)
|
if (QT4_FOUND)
|
||||||
foreach(_cmp ${ARGN})
|
foreach(_cmp ${ARGN})
|
||||||
|
if ("${_cmp}" STREQUAL "PRIVATE" OR
|
||||||
|
"${_cmp}" STREQUAL "PUBLIC" OR
|
||||||
|
"${_cmp}" STREQUAL "INTERFACE")
|
||||||
|
list(APPEND _QT_CMPNTS "${_cmp}")
|
||||||
|
else()
|
||||||
list(APPEND _QT_CMPNTS "Qt4::Qt${_cmp}")
|
list(APPEND _QT_CMPNTS "Qt4::Qt${_cmp}")
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
else (QT4_FOUND)
|
else (QT4_FOUND)
|
||||||
foreach(_cmp ${ARGN})
|
foreach(_cmp ${ARGN})
|
||||||
|
if ("${_cmp}" STREQUAL "PRIVATE" OR
|
||||||
|
"${_cmp}" STREQUAL "PUBLIC" OR
|
||||||
|
"${_cmp}" STREQUAL "INTERFACE")
|
||||||
|
list(APPEND _QT_CMPNTS "${_cmp}")
|
||||||
|
else()
|
||||||
list(APPEND _QT_CMPNTS "Qt5::${_cmp}")
|
list(APPEND _QT_CMPNTS "Qt5::${_cmp}")
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endif (QT4_FOUND)
|
endif (QT4_FOUND)
|
||||||
target_link_libraries(${target} ${_QT_CMPNTS})
|
target_link_libraries(${target} ${_QT_CMPNTS})
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ set(LibtorrentRasterbar_CUSTOM_DEFINITIONS
|
|||||||
-DBOOST_EXCEPTION_DISABLE
|
-DBOOST_EXCEPTION_DISABLE
|
||||||
-DBOOST_SYSTEM_STATIC_LINK=1
|
-DBOOST_SYSTEM_STATIC_LINK=1
|
||||||
-DTORRENT_USE_OPENSSL
|
-DTORRENT_USE_OPENSSL
|
||||||
-DUNICODE
|
-D__USE_W32_SOCKETS
|
||||||
|
-D_FILE_OFFSET_BITS=64)
|
||||||
|
|
||||||
|
add_definitions(-DUNICODE
|
||||||
-D_UNICODE
|
-D_UNICODE
|
||||||
-DWIN32
|
-DWIN32
|
||||||
-D_WIN32
|
-D_WIN32
|
||||||
@@ -18,9 +21,7 @@ set(LibtorrentRasterbar_CUSTOM_DEFINITIONS
|
|||||||
-D_WIN32_IE=0x0500
|
-D_WIN32_IE=0x0500
|
||||||
-D_CRT_SECURE_NO_DEPRECATE
|
-D_CRT_SECURE_NO_DEPRECATE
|
||||||
-D_SCL_SECURE_NO_DEPRECATE
|
-D_SCL_SECURE_NO_DEPRECATE
|
||||||
-D__USE_W32_SOCKETS
|
)
|
||||||
-D_FILE_OFFSET_BITS=64)
|
|
||||||
|
|
||||||
# and boost
|
# and boost
|
||||||
set(Boost_USE_STATIC_LIBS True)
|
set(Boost_USE_STATIC_LIBS True)
|
||||||
# set(Boost_USE_STATIC_RUNTIME True)
|
# set(Boost_USE_STATIC_RUNTIME True)
|
||||||
@@ -29,16 +30,17 @@ set(Boost_USE_STATIC_LIBS True)
|
|||||||
# with usual unix subdirectories (bin, lib, include)
|
# with usual unix subdirectories (bin, lib, include)
|
||||||
# if so, we just need to set CMAKE_SYSTEM_PREFIX_PATH
|
# if so, we just need to set CMAKE_SYSTEM_PREFIX_PATH
|
||||||
# If it is not the case, individual paths need to be specified manually (see below)
|
# If it is not the case, individual paths need to be specified manually (see below)
|
||||||
set(COMMON_INSTALL_PREFIX "c:/usr")
|
set(COMMON_INSTALL_PREFIX "c:/usr" CACHE PATH "Prefix used to install all the required libraries")
|
||||||
list(APPEND CMAKE_SYSTEM_PREFIX_PATH "${COMMON_INSTALL_PREFIX}")
|
list(APPEND CMAKE_SYSTEM_PREFIX_PATH "${COMMON_INSTALL_PREFIX}")
|
||||||
|
|
||||||
# If two version of Qt are installed, separate prefixes are needed most likely
|
# If two version of Qt are installed, separate prefixes are needed most likely
|
||||||
set(QT4_INSTALL_PREFIX "${COMMON_INSTALL_PREFIX}/lib/qt4")
|
set(QT4_INSTALL_PREFIX "${COMMON_INSTALL_PREFIX}/lib/qt4" CACHE PATH "Prefix where Qt4 is installed")
|
||||||
set(QT5_INSTALL_PREFIX "${COMMON_INSTALL_PREFIX}/lib/qt5")
|
set(QT5_INSTALL_PREFIX "${COMMON_INSTALL_PREFIX}/lib/qt5" CACHE PATH "Prefix where Qt5 is installed")
|
||||||
|
|
||||||
# it is safe to set Qt dirs even if their files are directly in the prefix
|
# it is safe to set Qt dirs even if their files are directly in the prefix
|
||||||
# Qt4
|
# Qt4
|
||||||
if(NOT QT5)
|
if(NOT QT5)
|
||||||
|
# for qt 4 we need qmake, Qt5 provides cmake config files
|
||||||
LIST(APPEND CMAKE_PROGRAM_PATH "${QT4_INSTALL_PREFIX}/bin/")
|
LIST(APPEND CMAKE_PROGRAM_PATH "${QT4_INSTALL_PREFIX}/bin/")
|
||||||
endif(NOT QT5)
|
endif(NOT QT5)
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@
|
|||||||
|
|
||||||
EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@
|
EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@
|
||||||
EXTERNAL_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS
|
EXTERNAL_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS
|
||||||
|
# added /usr/local/include due to Qt 5.7.0 bug on macOS
|
||||||
|
macx: EXTERNAL_INCLUDES += "/usr/local/include"
|
||||||
INCLUDEPATH += $$EXTERNAL_INCLUDES
|
INCLUDEPATH += $$EXTERNAL_INCLUDES
|
||||||
|
|
||||||
EXTERNAL_LIBS = @LDFLAGS@ @LIBS@
|
EXTERNAL_LIBS = @LDFLAGS@ @LIBS@
|
||||||
|
|||||||
98
configure
vendored
@@ -4257,6 +4257,17 @@ else
|
|||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OS is macOS" >&5
|
||||||
|
$as_echo_n "checking whether OS is macOS... " >&6; }
|
||||||
|
if expr "$host_os" : ".*darwin.*" > /dev/null; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
enable_qt_dbus=no
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
fi
|
||||||
|
|
||||||
# Require 0.23 pkg-config
|
# Require 0.23 pkg-config
|
||||||
|
|
||||||
|
|
||||||
@@ -4493,53 +4504,17 @@ fi
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
as_ac_File=`$as_echo "ac_cv_file_$QT_QMAKE/qmake" | $as_tr_sh`
|
if test -f "$QT_QMAKE/qmake"; then :
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $QT_QMAKE/qmake" >&5
|
|
||||||
$as_echo_n "checking for $QT_QMAKE/qmake... " >&6; }
|
|
||||||
if eval \${$as_ac_File+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
test "$cross_compiling" = yes &&
|
|
||||||
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
|
|
||||||
if test -r "$QT_QMAKE/qmake"; then
|
|
||||||
eval "$as_ac_File=yes"
|
|
||||||
else
|
|
||||||
eval "$as_ac_File=no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
eval ac_res=\$$as_ac_File
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
|
||||||
$as_echo "$ac_res" >&6; }
|
|
||||||
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
|
|
||||||
QT_QMAKE="$QT_QMAKE/qmake"
|
QT_QMAKE="$QT_QMAKE/qmake"
|
||||||
else
|
else
|
||||||
as_ac_File=`$as_echo "ac_cv_file_$QT_QMAKE/qmake-qt5" | $as_tr_sh`
|
if test -f "$QT_QMAKE/qmake-qt5"; then :
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $QT_QMAKE/qmake-qt5" >&5
|
|
||||||
$as_echo_n "checking for $QT_QMAKE/qmake-qt5... " >&6; }
|
|
||||||
if eval \${$as_ac_File+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
test "$cross_compiling" = yes &&
|
|
||||||
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
|
|
||||||
if test -r "$QT_QMAKE/qmake-qt5"; then
|
|
||||||
eval "$as_ac_File=yes"
|
|
||||||
else
|
|
||||||
eval "$as_ac_File=no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
eval ac_res=\$$as_ac_File
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
|
||||||
$as_echo "$ac_res" >&6; }
|
|
||||||
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
|
|
||||||
QT_QMAKE="$QT_QMAKE/qmake-qt5"
|
QT_QMAKE="$QT_QMAKE/qmake-qt5"
|
||||||
else
|
else
|
||||||
QT_QMAKE=""
|
QT_QMAKE=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt5 qmake >= 5.2.0" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt5 qmake >= 5.2.0" >&5
|
||||||
$as_echo_n "checking for Qt5 qmake >= 5.2.0... " >&6; }
|
$as_echo_n "checking for Qt5 qmake >= 5.2.0... " >&6; }
|
||||||
if test "x$QT_QMAKE" != "x"; then :
|
if test "x$QT_QMAKE" != "x"; then :
|
||||||
@@ -4610,53 +4585,17 @@ fi
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
as_ac_File=`$as_echo "ac_cv_file_$QT_QMAKE/qmake" | $as_tr_sh`
|
if test -f "$QT_QMAKE/qmake"; then :
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $QT_QMAKE/qmake" >&5
|
|
||||||
$as_echo_n "checking for $QT_QMAKE/qmake... " >&6; }
|
|
||||||
if eval \${$as_ac_File+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
test "$cross_compiling" = yes &&
|
|
||||||
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
|
|
||||||
if test -r "$QT_QMAKE/qmake"; then
|
|
||||||
eval "$as_ac_File=yes"
|
|
||||||
else
|
|
||||||
eval "$as_ac_File=no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
eval ac_res=\$$as_ac_File
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
|
||||||
$as_echo "$ac_res" >&6; }
|
|
||||||
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
|
|
||||||
QT_QMAKE="$QT_QMAKE/qmake"
|
QT_QMAKE="$QT_QMAKE/qmake"
|
||||||
else
|
else
|
||||||
as_ac_File=`$as_echo "ac_cv_file_$QT_QMAKE/qmake-qt4" | $as_tr_sh`
|
if test -f "$QT_QMAKE/qmake-qt4"; then :
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $QT_QMAKE/qmake-qt4" >&5
|
|
||||||
$as_echo_n "checking for $QT_QMAKE/qmake-qt4... " >&6; }
|
|
||||||
if eval \${$as_ac_File+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
test "$cross_compiling" = yes &&
|
|
||||||
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
|
|
||||||
if test -r "$QT_QMAKE/qmake-qt4"; then
|
|
||||||
eval "$as_ac_File=yes"
|
|
||||||
else
|
|
||||||
eval "$as_ac_File=no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
eval ac_res=\$$as_ac_File
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
|
||||||
$as_echo "$ac_res" >&6; }
|
|
||||||
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
|
|
||||||
QT_QMAKE="$QT_QMAKE/qmake-qt4"
|
QT_QMAKE="$QT_QMAKE/qmake-qt4"
|
||||||
else
|
else
|
||||||
QT_QMAKE=""
|
QT_QMAKE=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt4 qmake >= 4.8.0" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt4 qmake >= 4.8.0" >&5
|
||||||
$as_echo_n "checking for Qt4 qmake >= 4.8.0... " >&6; }
|
$as_echo_n "checking for Qt4 qmake >= 4.8.0... " >&6; }
|
||||||
if test "x$QT_QMAKE" != "x"; then :
|
if test "x$QT_QMAKE" != "x"; then :
|
||||||
@@ -5033,8 +4972,8 @@ fi
|
|||||||
if test "x$BOOST_CPPFLAGS" = "x"; then :
|
if test "x$BOOST_CPPFLAGS" = "x"; then :
|
||||||
as_fn_error $? "Could not find Boost" "$LINENO" 5
|
as_fn_error $? "Could not find Boost" "$LINENO" 5
|
||||||
else
|
else
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLGAS: $BOOST_CPPFLAGS" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLAGS: $BOOST_CPPFLAGS" >&5
|
||||||
$as_echo "$as_me: Boost CPPFLGAS: $BOOST_CPPFLAGS" >&6;}
|
$as_echo "$as_me: Boost CPPFLAGS: $BOOST_CPPFLAGS" >&6;}
|
||||||
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
||||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
||||||
fi
|
fi
|
||||||
@@ -5083,6 +5022,7 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex
|
|||||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||||
|
|
||||||
CXXFLAGS_SAVE=$CXXFLAGS
|
CXXFLAGS_SAVE=$CXXFLAGS
|
||||||
|
CXXFLAGS=
|
||||||
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
@@ -5090,7 +5030,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
|||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
{
|
{
|
||||||
boost::system::system_category
|
boost::system::error_category *a = 0;
|
||||||
;
|
;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ AS_IF([expr "$host_os" : ".*freebsd.*" > /dev/null],
|
|||||||
LIBS="-lexecinfo $LIBS"],
|
LIBS="-lexecinfo $LIBS"],
|
||||||
[AC_MSG_RESULT([no])])
|
[AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether OS is macOS])
|
||||||
|
AS_IF([expr "$host_os" : ".*darwin.*" > /dev/null],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
enable_qt_dbus=no],
|
||||||
|
[AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
# Require 0.23 pkg-config
|
# Require 0.23 pkg-config
|
||||||
PKG_PROG_PKG_CONFIG([0.23])
|
PKG_PROG_PKG_CONFIG([0.23])
|
||||||
AS_IF([test "x$PKG_CONFIG" = "x"],
|
AS_IF([test "x$PKG_CONFIG" = "x"],
|
||||||
@@ -156,7 +162,7 @@ AX_BOOST_BASE([1.35])
|
|||||||
# how to test for a set vs unset variable.
|
# how to test for a set vs unset variable.
|
||||||
AS_IF([test "x$BOOST_CPPFLAGS" = "x"],
|
AS_IF([test "x$BOOST_CPPFLAGS" = "x"],
|
||||||
[AC_MSG_ERROR([Could not find Boost])],
|
[AC_MSG_ERROR([Could not find Boost])],
|
||||||
[AC_MSG_NOTICE([Boost CPPFLGAS: $BOOST_CPPFLAGS])
|
[AC_MSG_NOTICE([Boost CPPFLAGS: $BOOST_CPPFLAGS])
|
||||||
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
||||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"])
|
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"])
|
||||||
|
|
||||||
|
|||||||
8
dist/mac/Info.plist
vendored
@@ -37,7 +37,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>qBittorrent</string>
|
<string>@EXECUTABLE@</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>qbittorrent_mac.icns</string>
|
<string>qbittorrent_mac.icns</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
@@ -45,11 +45,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.3.7</string>
|
<string>3.3.11</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>qBit</string>
|
<string>qBit</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>qbittorrent</string>
|
<string>@EXECUTABLE@</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>org.qbittorrent</string>
|
<string>org.qbittorrent</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<key>NSAppleScriptEnabled</key>
|
<key>NSAppleScriptEnabled</key>
|
||||||
<string>YES</string>
|
<string>YES</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2006-2016 The qBittorrent project</string>
|
<string>Copyright © 2006-2017 The qBittorrent project</string>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
BIN
dist/unix/menuicons/128x128/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
dist/unix/menuicons/16x16/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 893 B |
BIN
dist/unix/menuicons/192x192/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
dist/unix/menuicons/22x22/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
dist/unix/menuicons/24x24/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
dist/unix/menuicons/32x32/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
dist/unix/menuicons/36x36/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
dist/unix/menuicons/48x48/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
dist/unix/menuicons/64x64/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
dist/unix/menuicons/72x72/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
dist/unix/menuicons/96x96/status/qbittorrent-tray.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
9
dist/windows/README.txt
vendored
@@ -16,17 +16,13 @@ TRANSLATORS:
|
|||||||
PACKAGERS:
|
PACKAGERS:
|
||||||
|
|
||||||
You will need NSIS and upx to make the installer. You need a unicode version of NSIS.
|
You will need NSIS and upx to make the installer. You need a unicode version of NSIS.
|
||||||
I tested with NSIS 3.0a0.
|
I tested with NSIS 3.0 (final).
|
||||||
|
|
||||||
1. Open the options.nsi file in an editor and change line that contains
|
1. Open the options.nsi file in an editor and change line that contains
|
||||||
"!define PROG_VERSION "3.0.3"" to the version of qbittorrent you just built.
|
"!define PROG_VERSION "3.0.3"" to the version of qbittorrent you just built.
|
||||||
2. Extract the plugins found in the folder "nsis plugins" into your
|
2. Extract the plugins found in the folder "nsis plugins" into your
|
||||||
NSIS's unicode Plugin directory(usually C:\Program Files\NSIS\Plugins\x86-unicode).
|
NSIS's unicode Plugin directory(usually C:\Program Files\NSIS\Plugins\x86-unicode).
|
||||||
Only the *.dll files are needed. Don't use the .dll from UAC.zip, use the one from "UAC Unicode.zip".
|
Only the *.dll files are needed. Use the unicode version of the dlls.
|
||||||
NOTE: To build the unicode version of UAC with MSVC2008 you need:
|
|
||||||
a) the sources from UAC.zip
|
|
||||||
b) apply the util.cpp.diff from "UAC Unicode.zip" to util.cpp
|
|
||||||
c) in a msvc command prompt issue: cl.exe /O1s /GS- /GR- /EHs-c- /Zl /LD /DUNICODE RunAs.cpp uac.cpp util.cpp /link kernel32.lib user32.lib shell32.lib advapi32.lib ole32.lib /DLL /MANIFEST:NO /OUT:uac.dll
|
|
||||||
3. The script you need to compile is "qbittorrent.nsi". It includes all other necessary scripts.
|
3. The script you need to compile is "qbittorrent.nsi". It includes all other necessary scripts.
|
||||||
4. The script expects the following file tree:
|
4. The script expects the following file tree:
|
||||||
|
|
||||||
@@ -53,6 +49,7 @@ qbittorrent.exe
|
|||||||
qbittorrent.nsi
|
qbittorrent.nsi
|
||||||
qt.conf
|
qt.conf
|
||||||
translations.nsi
|
translations.nsi
|
||||||
|
UAC.nsh
|
||||||
uninstaller.nsi
|
uninstaller.nsi
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
dist/windows/UAC.nsh
vendored
@@ -228,6 +228,8 @@ pop $_LOGICLIB_TEMP
|
|||||||
!undef _UAC_ParseDefineFlags_orin_this
|
!undef _UAC_ParseDefineFlags_orin_this
|
||||||
!ifdef _UAC_ParseDefineFlags_orin_f1
|
!ifdef _UAC_ParseDefineFlags_orin_f1
|
||||||
!undef _UAC_ParseDefineFlags_orin_f1
|
!undef _UAC_ParseDefineFlags_orin_f1
|
||||||
|
!endif
|
||||||
|
!ifdef _UAC_ParseDefineFlags_orin_f2
|
||||||
!undef _UAC_ParseDefineFlags_orin_f2
|
!undef _UAC_ParseDefineFlags_orin_f2
|
||||||
!endif
|
!endif
|
||||||
!macroend
|
!macroend
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ LangString inst_firewallinfo ${LANG_PORTUGUESE} "Adicionando regra à firewall d
|
|||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_PORTUGUESE} "O qBittorrent está a ser executado. Feche a aplicação antes de instalar esta versão."
|
LangString inst_warning ${LANG_PORTUGUESE} "O qBittorrent está a ser executado. Feche a aplicação antes de instalar esta versão."
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||||
LangString inst_uninstall_question ${LANG_PORTUGUESE} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
LangString inst_uninstall_question ${LANG_PORTUGUESE} "Uma antiga instalação foi encontrada.Essa mesma será desinstalada sem apagar as definições do usuário."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_PORTUGUESE} "A desinstalar versão anterior."
|
LangString inst_unist ${LANG_PORTUGUESE} "A desinstalar versão anterior."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ LangString inst_firewallinfo ${LANG_PORTUGUESEBR} "Adicionando regra no firewall
|
|||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_PORTUGUESEBR} "qBittorrent está rodando. Por favor feche a aplicação antes de instalar."
|
LangString inst_warning ${LANG_PORTUGUESEBR} "qBittorrent está rodando. Por favor feche a aplicação antes de instalar."
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||||
LangString inst_uninstall_question ${LANG_PORTUGUESEBR} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
LangString inst_uninstall_question ${LANG_PORTUGUESEBR} "Uma instalação anterior foi detectada. Ela será desistalada sem deletar as configurações de usuário."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_PORTUGUESEBR} "Desinstalando versão anterior."
|
LangString inst_unist ${LANG_PORTUGUESEBR} "Desinstalando versão anterior."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
|
|||||||
44
dist/windows/installer-translations/turkish.nsi
vendored
@@ -1,51 +1,51 @@
|
|||||||
;Installer strings
|
;Installer strings
|
||||||
|
|
||||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||||
LangString inst_qbt_req ${LANG_TURKISH} "qBittorrent (required)"
|
LangString inst_qbt_req ${LANG_TURKISH} "qBittorrent (zorunlu)"
|
||||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||||
LangString inst_dekstop ${LANG_TURKISH} "Create Desktop Shortcut"
|
LangString inst_dekstop ${LANG_TURKISH} "Masaüstü Kısayolu oluştur"
|
||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_TURKISH} "Create Start Menu Shortcut"
|
LangString inst_startmenu ${LANG_TURKISH} "Başlangıç Menüsü Kısayolu oluştur"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_TURKISH} "Open .torrent files with qBittorrent"
|
LangString inst_torrent ${LANG_TURKISH} ".torrent dosyalarını qBittorrent ile aç"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
LangString inst_magnet ${LANG_TURKISH} "Open magnet links with qBittorrent"
|
LangString inst_magnet ${LANG_TURKISH} "Magnet bağlantılarını qBittorrent ile aç"
|
||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_TURKISH} "Add Windows Firewall rule"
|
LangString inst_firewall ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralı ekle"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_TURKISH} "Adding Windows Firewall rule"
|
LangString inst_firewallinfo ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralı ekleniyor"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_TURKISH} "qBittorrent is running. Please close the application before installing."
|
LangString inst_warning ${LANG_TURKISH} "qBittorrent çalışıyor. Lütfen yüklemeden önce uygulamayı kapatın."
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||||
LangString inst_uninstall_question ${LANG_TURKISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
LangString inst_uninstall_question ${LANG_TURKISH} "Önceki bir kurulum algılandı. Kullanıcı ayarları silinmeden kaldırılacaktır."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_TURKISH} "Uninstalling previous version."
|
LangString inst_unist ${LANG_TURKISH} "Önceki sürüm kaldırılıyor."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_TURKISH} "Launch qBittorrent."
|
LangString launch_qbt ${LANG_TURKISH} "qBittorrent'i çalıştır."
|
||||||
|
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
|
|
||||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||||
LangString remove_files ${LANG_TURKISH} "Remove files"
|
LangString remove_files ${LANG_TURKISH} "Dosyaları kaldır"
|
||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_TURKISH} "Remove shortcuts"
|
LangString remove_shortcuts ${LANG_TURKISH} "Kısayolları kaldır"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_TURKISH} "Remove file associations"
|
LangString remove_associations ${LANG_TURKISH} "Dosya ilişkilendirmelerini kaldır"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_TURKISH} "Remove registry keys"
|
LangString remove_registry ${LANG_TURKISH} "Kayıt defteri anahtarlarını kaldır"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
LangString remove_conf ${LANG_TURKISH} "Remove configuration files"
|
LangString remove_conf ${LANG_TURKISH} "Yapılandırma dosyalarını kaldır"
|
||||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||||
LangString remove_firewall ${LANG_TURKISH} "Remove Windows Firewall rule"
|
LangString remove_firewall ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralını kaldır"
|
||||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||||
LangString remove_firewallinfo ${LANG_TURKISH} "Removing Windows Firewall rule"
|
LangString remove_firewallinfo ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralı kaldırılıyor"
|
||||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||||
LangString remove_cache ${LANG_TURKISH} "Remove torrents and cached data"
|
LangString remove_cache ${LANG_TURKISH} "Torrentleri ve önbelleklenen verileri kaldır"
|
||||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||||
LangString uninst_warning ${LANG_TURKISH} "qBittorrent is running. Please close the application before uninstalling."
|
LangString uninst_warning ${LANG_TURKISH} "qBittorrent çalışıyor. Lütfen kaldırmadan önce uygulamayı kapatın."
|
||||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||||
LangString uninst_tor_warn ${LANG_TURKISH} "Not removing .torrent association. It is associated with:"
|
LangString uninst_tor_warn ${LANG_TURKISH} ".torrent ilişkilendirmesi kaldırılmıyor. Şununla ilişkilendirildi:"
|
||||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||||
LangString uninst_mag_warn ${LANG_TURKISH} "Not removing magnet association. It is associated with:"
|
LangString uninst_mag_warn ${LANG_TURKISH} "Magnet ilişkilendirmesi kaldırılmıyor. Şununla ilişkilendirildi:"
|
||||||
|
|||||||
BIN
dist/windows/nsis plugins/UAC Unicode.zip
vendored
BIN
dist/windows/nsis plugins/UAC.zip
vendored
4
dist/windows/options.nsi
vendored
@@ -19,7 +19,7 @@ XPStyle on
|
|||||||
!define CSIDL_APPDATA '0x1A' ;Application Data path
|
!define CSIDL_APPDATA '0x1A' ;Application Data path
|
||||||
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
||||||
|
|
||||||
!define PROG_VERSION "3.3.7"
|
!define PROG_VERSION "3.3.11"
|
||||||
!define MUI_FINISHPAGE_RUN
|
!define MUI_FINISHPAGE_RUN
|
||||||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
||||||
!define MUI_FINISHPAGE_RUN_TEXT $(launch_qbt)
|
!define MUI_FINISHPAGE_RUN_TEXT $(launch_qbt)
|
||||||
@@ -33,7 +33,7 @@ OutFile "qbittorrent_${PROG_VERSION}_setup.exe"
|
|||||||
;Installer Version Information
|
;Installer Version Information
|
||||||
VIAddVersionKey "ProductName" "qBittorrent"
|
VIAddVersionKey "ProductName" "qBittorrent"
|
||||||
VIAddVersionKey "CompanyName" "The qBittorrent project"
|
VIAddVersionKey "CompanyName" "The qBittorrent project"
|
||||||
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2016 The qBittorrent project"
|
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2017 The qBittorrent project"
|
||||||
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
||||||
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
# and this notice are preserved. This file is offered as-is, without any
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
# warranty.
|
# warranty.
|
||||||
|
|
||||||
#serial 17
|
#serial 18
|
||||||
|
|
||||||
AC_DEFUN([AX_BOOST_SYSTEM],
|
AC_DEFUN([AX_BOOST_SYSTEM],
|
||||||
[
|
[
|
||||||
@@ -68,9 +68,10 @@ AC_DEFUN([AX_BOOST_SYSTEM],
|
|||||||
ax_cv_boost_system,
|
ax_cv_boost_system,
|
||||||
[AC_LANG_PUSH([C++])
|
[AC_LANG_PUSH([C++])
|
||||||
CXXFLAGS_SAVE=$CXXFLAGS
|
CXXFLAGS_SAVE=$CXXFLAGS
|
||||||
|
CXXFLAGS=
|
||||||
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
|
||||||
[[boost::system::system_category]])],
|
[[boost::system::error_category *a = 0;]])],
|
||||||
ax_cv_boost_system=yes, ax_cv_boost_system=no)
|
ax_cv_boost_system=yes, ax_cv_boost_system=no)
|
||||||
CXXFLAGS=$CXXFLAGS_SAVE
|
CXXFLAGS=$CXXFLAGS_SAVE
|
||||||
AC_LANG_POP([C++])
|
AC_LANG_POP([C++])
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ AC_DEFUN([FIND_QT4],
|
|||||||
[QT_QMAKE=`AS_DIRNAME(["$QT_QMAKE"])`])
|
[QT_QMAKE=`AS_DIRNAME(["$QT_QMAKE"])`])
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_CHECK_FILE([$QT_QMAKE/qmake],
|
AS_IF([test -f "$QT_QMAKE/qmake"],
|
||||||
[QT_QMAKE="$QT_QMAKE/qmake"],
|
[QT_QMAKE="$QT_QMAKE/qmake"],
|
||||||
[AC_CHECK_FILE([$QT_QMAKE/qmake-qt4],
|
[AS_IF([test -f "$QT_QMAKE/qmake-qt4"],
|
||||||
[QT_QMAKE="$QT_QMAKE/qmake-qt4"],
|
[QT_QMAKE="$QT_QMAKE/qmake-qt4"],
|
||||||
[QT_QMAKE=""])
|
[QT_QMAKE=""])
|
||||||
])
|
])
|
||||||
@@ -36,9 +36,9 @@ AC_DEFUN([FIND_QT5],
|
|||||||
[host_bins])
|
[host_bins])
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_CHECK_FILE([$QT_QMAKE/qmake],
|
AS_IF([test -f "$QT_QMAKE/qmake"],
|
||||||
[QT_QMAKE="$QT_QMAKE/qmake"],
|
[QT_QMAKE="$QT_QMAKE/qmake"],
|
||||||
[AC_CHECK_FILE([$QT_QMAKE/qmake-qt5],
|
[AS_IF([test -f "$QT_QMAKE/qmake-qt5"],
|
||||||
[QT_QMAKE="$QT_QMAKE/qmake-qt5"],
|
[QT_QMAKE="$QT_QMAKE/qmake-qt5"],
|
||||||
[QT_QMAKE=""])
|
[QT_QMAKE=""])
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -161,10 +161,15 @@ endif (GUI AND WIN32)
|
|||||||
target_link_libraries(${QBT_TARGET_NAME} ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)
|
target_link_libraries(${QBT_TARGET_NAME} ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(qbt_BUNDLE_NAME "${CMAKE_PROJECT_NAME}")
|
set(qbt_BUNDLE_NAME "${QBT_TARGET_NAME}")
|
||||||
|
|
||||||
|
# substitute @EXECUTABLE@ in dist/mac/Info.plist
|
||||||
|
set(EXECUTABLE ${qbt_BUNDLE_NAME})
|
||||||
|
configure_file(${qBittorrent_SOURCE_DIR}/dist/mac/Info.plist ${qBittorrent_BINARY_DIR}/dist/mac/Info.plist @ONLY)
|
||||||
|
|
||||||
set_target_properties(${QBT_TARGET_NAME} PROPERTIES
|
set_target_properties(${QBT_TARGET_NAME} PROPERTIES
|
||||||
MACOSX_BUNDLE_BUNDLE_NAME "${qbt_BUNDLE_NAME}"
|
MACOSX_BUNDLE_BUNDLE_NAME "${qbt_BUNDLE_NAME}"
|
||||||
MACOSX_BUNDLE_INFO_PLIST ${qBittorrent_SOURCE_DIR}/dist/mac/Info.plist
|
MACOSX_BUNDLE_INFO_PLIST ${qBittorrent_BINARY_DIR}/dist/mac/Info.plist
|
||||||
)
|
)
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
#include "base/net/smtp.h"
|
#include "base/net/smtp.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
#include "base/net/geoipmanager.h"
|
#include "base/net/geoipmanager.h"
|
||||||
|
#include "base/net/proxyconfigurationmanager.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ void Application::runExternalProgram(BitTorrent::TorrentHandle *const torrent) c
|
|||||||
#elif defined(Q_OS_WIN) // test cmd: `echo "%F" > "c:\ab ba.txt"`
|
#elif defined(Q_OS_WIN) // test cmd: `echo "%F" > "c:\ab ba.txt"`
|
||||||
program.prepend(QLatin1String("\"")).append(QLatin1String("\""));
|
program.prepend(QLatin1String("\"")).append(QLatin1String("\""));
|
||||||
program.prepend(Utils::Misc::windowsSystemPath() + QLatin1String("\\cmd.exe /C "));
|
program.prepend(Utils::Misc::windowsSystemPath() + QLatin1String("\\cmd.exe /C "));
|
||||||
const uint cmdMaxLength = 32768; // max length (incl. terminate char) for `lpCommandLine` in `CreateProcessW()`
|
const int cmdMaxLength = 32768; // max length (incl. terminate char) for `lpCommandLine` in `CreateProcessW()`
|
||||||
if ((program.size() + 1) > cmdMaxLength) {
|
if ((program.size() + 1) > cmdMaxLength) {
|
||||||
logger->addMessage(tr("Torrent: %1, run external program command too long (length > %2), execution failed.").arg(torrent->name()).arg(cmdMaxLength), Log::CRITICAL);
|
logger->addMessage(tr("Torrent: %1, run external program command too long (length > %2), execution failed.").arg(torrent->name()).arg(cmdMaxLength), Log::CRITICAL);
|
||||||
return;
|
return;
|
||||||
@@ -395,6 +396,7 @@ void Application::processParams(const QStringList ¶ms)
|
|||||||
|
|
||||||
int Application::exec(const QStringList ¶ms)
|
int Application::exec(const QStringList ¶ms)
|
||||||
{
|
{
|
||||||
|
Net::ProxyConfigurationManager::initInstance();
|
||||||
Net::DownloadManager::initInstance();
|
Net::DownloadManager::initInstance();
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
IconProvider::initInstance();
|
IconProvider::initInstance();
|
||||||
@@ -509,36 +511,27 @@ void Application::initializeTranslation()
|
|||||||
{
|
{
|
||||||
Preferences* const pref = Preferences::instance();
|
Preferences* const pref = Preferences::instance();
|
||||||
// Load translation
|
// Load translation
|
||||||
QString locale = pref->getLocale();
|
QString localeStr = pref->getLocale();
|
||||||
|
QLocale::setDefault(QLocale(localeStr));
|
||||||
|
|
||||||
if (locale.isEmpty()) {
|
if (
|
||||||
locale = QLocale::system().name();
|
|
||||||
pref->setLocale(locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_qtTranslator.load(
|
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
QString::fromUtf8("qtbase_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) ||
|
m_qtTranslator.load(QString::fromUtf8("qtbase_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) ||
|
||||||
m_qtTranslator.load(
|
|
||||||
#endif
|
#endif
|
||||||
QString::fromUtf8("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
|
m_qtTranslator.load(QString::fromUtf8("qt_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||||
qDebug("Qt %s locale recognized, using translation.", qPrintable(locale));
|
qDebug("Qt %s locale recognized, using translation.", qPrintable(localeStr));
|
||||||
}
|
else
|
||||||
else {
|
qDebug("Qt %s locale unrecognized, using default (en).", qPrintable(localeStr));
|
||||||
qDebug("Qt %s locale unrecognized, using default (en).", qPrintable(locale));
|
|
||||||
}
|
|
||||||
installTranslator(&m_qtTranslator);
|
installTranslator(&m_qtTranslator);
|
||||||
|
|
||||||
if (m_translator.load(QString::fromUtf8(":/lang/qbittorrent_") + locale)) {
|
if (m_translator.load(QString::fromUtf8(":/lang/qbittorrent_") + localeStr))
|
||||||
qDebug("%s locale recognized, using translation.", qPrintable(locale));
|
qDebug("%s locale recognized, using translation.", qPrintable(localeStr));
|
||||||
}
|
else
|
||||||
else {
|
qDebug("%s locale unrecognized, using default (en).", qPrintable(localeStr));
|
||||||
qDebug("%s locale unrecognized, using default (en).", qPrintable(locale));
|
|
||||||
}
|
|
||||||
installTranslator(&m_translator);
|
installTranslator(&m_translator);
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
if (locale.startsWith("ar") || locale.startsWith("he")) {
|
if (localeStr.startsWith("ar") || localeStr.startsWith("he")) {
|
||||||
qDebug("Right to Left mode");
|
qDebug("Right to Left mode");
|
||||||
setLayoutDirection(Qt::RightToLeft);
|
setLayoutDirection(Qt::RightToLeft);
|
||||||
}
|
}
|
||||||
@@ -621,11 +614,13 @@ void Application::cleanup()
|
|||||||
Net::GeoIPManager::freeInstance();
|
Net::GeoIPManager::freeInstance();
|
||||||
#endif
|
#endif
|
||||||
Net::DownloadManager::freeInstance();
|
Net::DownloadManager::freeInstance();
|
||||||
|
Net::ProxyConfigurationManager::freeInstance();
|
||||||
Preferences::freeInstance();
|
Preferences::freeInstance();
|
||||||
SettingsStorage::freeInstance();
|
SettingsStorage::freeInstance();
|
||||||
delete m_fileLogger;
|
delete m_fileLogger;
|
||||||
Logger::freeInstance();
|
Logger::freeInstance();
|
||||||
IconProvider::freeInstance();
|
IconProvider::freeInstance();
|
||||||
|
Utils::Fs::removeDirRecursive(Utils::Fs::tempPath());
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|||||||
@@ -135,6 +135,16 @@ int main(int argc, char *argv[])
|
|||||||
// We must save it here because QApplication constructor may change it
|
// We must save it here because QApplication constructor may change it
|
||||||
bool isOneArg = (argc == 2);
|
bool isOneArg = (argc == 2);
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// On macOS 10.12 Sierra, Apple changed the behaviour of CFPreferencesSetValue() https://bugreports.qt.io/browse/QTBUG-56344
|
||||||
|
// Due to this, we have to move from native plist to IniFormat
|
||||||
|
macMigratePlists();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
migrateRSS();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create Application
|
// Create Application
|
||||||
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
||||||
QScopedPointer<Application> app(new Application(appId, argc, argv));
|
QScopedPointer<Application> app(new Application(appId, argc, argv));
|
||||||
@@ -230,6 +240,17 @@ int main(int argc, char *argv[])
|
|||||||
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
|
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
{
|
||||||
|
// Since Apple made difficult for users to set PATH, we set here for convenience.
|
||||||
|
// Users are supposed to install Homebrew Python for search function.
|
||||||
|
// For more info see issue #5571.
|
||||||
|
QByteArray path = "/usr/local/bin:";
|
||||||
|
path += qgetenv("PATH");
|
||||||
|
qputenv("PATH", path.constData());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
if (!upgrade()) return EXIT_FAILURE;
|
if (!upgrade()) return EXIT_FAILURE;
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -33,30 +33,30 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames
|
|||||||
size_t funcnamesize = 256;
|
size_t funcnamesize = 256;
|
||||||
char *funcname = (char *)malloc(funcnamesize);
|
char *funcname = (char *)malloc(funcnamesize);
|
||||||
|
|
||||||
|
int functionNamesFound = 0;
|
||||||
// iterate over the returned symbol lines. skip the first, it is the
|
// iterate over the returned symbol lines. skip the first, it is the
|
||||||
// address of this function.
|
// address of this function.
|
||||||
for (int i = 2; i < addrlen; i++)
|
for (int i = 2; i < addrlen; i++) {
|
||||||
{
|
|
||||||
char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
|
char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
|
||||||
|
|
||||||
// find parentheses and +address offset surrounding the mangled name:
|
// find parentheses and +address offset surrounding the mangled name:
|
||||||
// ./module(function+0x15c) [0x8048a6d]
|
// ./module(function+0x15c) [0x8048a6d]
|
||||||
// fprintf(out, "%s TT\n", symbollist[i]);
|
// fprintf(out, "%s TT\n", symbollist[i]);
|
||||||
for (char *p = symbollist[i]; *p; ++p)
|
for (char *p = symbollist[i]; *p; ++p) {
|
||||||
{
|
if (*p == '(') {
|
||||||
if (*p == '(')
|
|
||||||
begin_name = p;
|
begin_name = p;
|
||||||
else if (*p == '+')
|
}
|
||||||
|
else if (*p == '+') {
|
||||||
begin_offset = p;
|
begin_offset = p;
|
||||||
else if (*p == ')' && begin_offset) {
|
}
|
||||||
|
else if ((*p == ')') && begin_offset) {
|
||||||
end_offset = p;
|
end_offset = p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (begin_name && begin_offset && end_offset
|
if (begin_name && begin_offset && end_offset
|
||||||
&& begin_name < begin_offset)
|
&& (begin_name < begin_offset)) {
|
||||||
{
|
|
||||||
*begin_name++ = '\0';
|
*begin_name++ = '\0';
|
||||||
*begin_offset++ = '\0';
|
*begin_offset++ = '\0';
|
||||||
*end_offset = '\0';
|
*end_offset = '\0';
|
||||||
@@ -79,14 +79,22 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames
|
|||||||
fprintf(out, " %s : %s()+%s %s\n",
|
fprintf(out, " %s : %s()+%s %s\n",
|
||||||
symbollist[i], begin_name, begin_offset, ++end_offset);
|
symbollist[i], begin_name, begin_offset, ++end_offset);
|
||||||
}
|
}
|
||||||
|
++functionNamesFound;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// couldn't parse the line? print the whole line.
|
// couldn't parse the line? print the whole line.
|
||||||
fprintf(out, " %s\n", symbollist[i]);
|
fprintf(out, " %s\n", symbollist[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!functionNamesFound) {
|
||||||
|
fprintf(out, "There were no function names found in the stack trace\n."
|
||||||
|
"Seems like debug symbols are not installed, and the stack trace is useless.\n");
|
||||||
|
}
|
||||||
|
if (functionNamesFound < addrlen - 2) {
|
||||||
|
fprintf(out, "Consider installing debug symbols for packages containing files with empty"
|
||||||
|
" function names (i.e. empty braces \"()\") to make your stack trace more useful\n");
|
||||||
|
}
|
||||||
free(funcname);
|
free(funcname);
|
||||||
free(symbollist);
|
free(symbollist);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,24 +29,31 @@
|
|||||||
#ifndef UPGRADE_H
|
#ifndef UPGRADE_H
|
||||||
#define UPGRADE_H
|
#define UPGRADE_H
|
||||||
|
|
||||||
#include <libtorrent/lazy_entry.hpp>
|
#include <libtorrent/version.hpp>
|
||||||
#include <libtorrent/entry.hpp>
|
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||||
|
#include <libtorrent/bdecode.hpp>
|
||||||
|
#endif
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
|
#include <libtorrent/entry.hpp>
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
|
#include <libtorrent/lazy_entry.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QRegExp>
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#endif
|
#endif
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "base/qinisettings.h"
|
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
|
#include "base/qinisettings.h"
|
||||||
|
|
||||||
bool userAcceptsUpgrade()
|
bool userAcceptsUpgrade()
|
||||||
{
|
{
|
||||||
@@ -86,10 +93,16 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent =
|
|||||||
QByteArray data = file1.readAll();
|
QByteArray data = file1.readAll();
|
||||||
file1.close();
|
file1.close();
|
||||||
|
|
||||||
libtorrent::lazy_entry fastOld;
|
|
||||||
libtorrent::error_code ec;
|
libtorrent::error_code ec;
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
|
libtorrent::lazy_entry fastOld;
|
||||||
libtorrent::lazy_bdecode(data.constData(), data.constData() + data.size(), fastOld, ec);
|
libtorrent::lazy_bdecode(data.constData(), data.constData() + data.size(), fastOld, ec);
|
||||||
if (ec || (fastOld.type() != libtorrent::lazy_entry::dict_t)) return false;
|
if (ec || (fastOld.type() != libtorrent::lazy_entry::dict_t)) return false;
|
||||||
|
#else
|
||||||
|
libtorrent::bdecode_node fastOld;
|
||||||
|
libtorrent::bdecode(data.constData(), data.constData() + data.size(), fastOld, ec);
|
||||||
|
if (ec || (fastOld.type() != libtorrent::bdecode_node::dict_t)) return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
libtorrent::entry fastNew;
|
libtorrent::entry fastNew;
|
||||||
fastNew = fastOld;
|
fastNew = fastOld;
|
||||||
@@ -143,7 +156,12 @@ bool upgrade(bool ask = true)
|
|||||||
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
||||||
// ****************************************************************************************
|
// ****************************************************************************************
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// native .plist
|
||||||
|
QSettings *oldResumeSettings = new QSettings("qBittorrent", "qBittorrent-resume");
|
||||||
|
#else
|
||||||
QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume");
|
QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume");
|
||||||
|
#endif
|
||||||
QString oldResumeFilename = oldResumeSettings->fileName();
|
QString oldResumeFilename = oldResumeSettings->fileName();
|
||||||
QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash();
|
QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash();
|
||||||
delete oldResumeSettings;
|
delete oldResumeSettings;
|
||||||
@@ -210,4 +228,50 @@ bool upgrade(bool ask = true)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
void migratePlistToIni(const QString &application)
|
||||||
|
{
|
||||||
|
QIniSettings iniFile("qBittorrent", application);
|
||||||
|
if (!iniFile.allKeys().isEmpty()) return; // We copy the contents of plist, only if inifile does not exist(is empty).
|
||||||
|
|
||||||
|
QSettings *plistFile = new QSettings("qBittorrent", application);
|
||||||
|
plistFile->setFallbacksEnabled(false);
|
||||||
|
const QStringList plist = plistFile->allKeys();
|
||||||
|
if (!plist.isEmpty()) {
|
||||||
|
foreach (const QString &key, plist)
|
||||||
|
iniFile.setValue(key, plistFile->value(key));
|
||||||
|
plistFile->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString plistPath = plistFile->fileName();
|
||||||
|
delete plistFile;
|
||||||
|
Utils::Fs::forceRemove(plistPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void macMigratePlists()
|
||||||
|
{
|
||||||
|
migratePlistToIni("qBittorrent-data");
|
||||||
|
migratePlistToIni("qBittorrent-rss");
|
||||||
|
migratePlistToIni("qBittorrent");
|
||||||
|
}
|
||||||
|
#endif // Q_OS_MAC
|
||||||
|
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
void migrateRSS()
|
||||||
|
{
|
||||||
|
// Copy old feed items to new file if needed
|
||||||
|
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss-feeds");
|
||||||
|
if (!qBTRSS.allKeys().isEmpty()) return; // We move the contents of RSS old_items only if inifile does not exist (is empty).
|
||||||
|
|
||||||
|
QIniSettings qBTRSSLegacy("qBittorrent", "qBittorrent-rss");
|
||||||
|
QHash<QString, QVariant> allOldItems = qBTRSSLegacy.value("old_items", QHash<QString, QVariant>()).toHash();
|
||||||
|
|
||||||
|
if (!allOldItems.empty()) {
|
||||||
|
qDebug("Moving %d old items for feeds to qBittorrent-rss-feeds", allOldItems.size());
|
||||||
|
qBTRSS.setValue("old_items", allOldItems);
|
||||||
|
qBTRSSLegacy.remove("old_items");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // UPGRADE_H
|
#endif // UPGRADE_H
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ net/downloadmanager.h
|
|||||||
net/geoipmanager.h
|
net/geoipmanager.h
|
||||||
net/portforwarder.h
|
net/portforwarder.h
|
||||||
net/private/geoipdatabase.h
|
net/private/geoipdatabase.h
|
||||||
|
net/proxyconfigurationmanager.h
|
||||||
net/reverseresolution.h
|
net/reverseresolution.h
|
||||||
net/smtp.h
|
net/smtp.h
|
||||||
rss/private/rssparser.h
|
rss/private/rssparser.h
|
||||||
@@ -88,6 +89,7 @@ net/downloadmanager.cpp
|
|||||||
net/geoipmanager.cpp
|
net/geoipmanager.cpp
|
||||||
net/portforwarder.cpp
|
net/portforwarder.cpp
|
||||||
net/private/geoipdatabase.cpp
|
net/private/geoipdatabase.cpp
|
||||||
|
net/proxyconfigurationmanager.cpp
|
||||||
net/reverseresolution.cpp
|
net/reverseresolution.cpp
|
||||||
net/smtp.cpp
|
net/smtp.cpp
|
||||||
rss/private/rssparser.cpp
|
rss/private/rssparser.cpp
|
||||||
@@ -115,24 +117,24 @@ tristatebool.cpp
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(qbt_base STATIC ${QBT_BASE_HEADERS} ${QBT_BASE_SOURCES})
|
add_library(qbt_base STATIC ${QBT_BASE_HEADERS} ${QBT_BASE_SOURCES})
|
||||||
target_link_libraries(qbt_base ZLIB::ZLIB LibtorrentRasterbar::LibTorrent)
|
target_link_libraries(qbt_base PRIVATE ZLIB::ZLIB PUBLIC LibtorrentRasterbar::LibTorrent)
|
||||||
target_link_qt_components(qbt_base Core Network Xml)
|
target_link_qt_components(qbt_base PUBLIC Core Network Xml)
|
||||||
if (QT4_FOUND)
|
if (QT4_FOUND)
|
||||||
if (GUI)
|
if (GUI)
|
||||||
target_link_libraries(qbt_base Qt4::QtGui)
|
target_link_libraries(qbt_base PUBLIC Qt4::QtGui)
|
||||||
endif (GUI)
|
endif (GUI)
|
||||||
else (QT4_FOUND)
|
else (QT4_FOUND)
|
||||||
if (GUI)
|
if (GUI)
|
||||||
target_link_libraries(qbt_base Qt5::Gui Qt5::Widgets)
|
target_link_libraries(qbt_base PUBLIC Qt5::Gui Qt5::Widgets)
|
||||||
endif (GUI)
|
endif (GUI)
|
||||||
endif (QT4_FOUND)
|
endif (QT4_FOUND)
|
||||||
|
|
||||||
if (DBUS)
|
if (DBUS)
|
||||||
target_link_qt_components(qbt_base DBus)
|
target_link_qt_components(qbt_base PRIVATE DBus)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
find_library(IOKit_LIBRARY IOKit)
|
find_library(IOKit_LIBRARY IOKit)
|
||||||
find_library(Carbon_LIBRARY Carbon)
|
find_library(Carbon_LIBRARY Carbon)
|
||||||
target_link_libraries(qbt_base ${Carbon_LIBRARY} ${IOKit_LIBRARY})
|
target_link_libraries(qbt_base PRIVATE ${Carbon_LIBRARY} ${IOKit_LIBRARY})
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ HEADERS += \
|
|||||||
$$PWD/qinisettings.h \
|
$$PWD/qinisettings.h \
|
||||||
$$PWD/logger.h \
|
$$PWD/logger.h \
|
||||||
$$PWD/settingsstorage.h \
|
$$PWD/settingsstorage.h \
|
||||||
|
$$PWD/settingvalue.h \
|
||||||
$$PWD/preferences.h \
|
$$PWD/preferences.h \
|
||||||
$$PWD/indexrange.h \
|
$$PWD/indexrange.h \
|
||||||
$$PWD/iconprovider.h \
|
$$PWD/iconprovider.h \
|
||||||
@@ -20,6 +21,7 @@ HEADERS += \
|
|||||||
$$PWD/net/downloadhandler.h \
|
$$PWD/net/downloadhandler.h \
|
||||||
$$PWD/net/geoipmanager.h \
|
$$PWD/net/geoipmanager.h \
|
||||||
$$PWD/net/portforwarder.h \
|
$$PWD/net/portforwarder.h \
|
||||||
|
$$PWD/net/proxyconfigurationmanager.h \
|
||||||
$$PWD/net/reverseresolution.h \
|
$$PWD/net/reverseresolution.h \
|
||||||
$$PWD/net/smtp.h \
|
$$PWD/net/smtp.h \
|
||||||
$$PWD/net/private/geoipdatabase.h \
|
$$PWD/net/private/geoipdatabase.h \
|
||||||
@@ -74,6 +76,7 @@ SOURCES += \
|
|||||||
$$PWD/net/downloadhandler.cpp \
|
$$PWD/net/downloadhandler.cpp \
|
||||||
$$PWD/net/geoipmanager.cpp \
|
$$PWD/net/geoipmanager.cpp \
|
||||||
$$PWD/net/portforwarder.cpp \
|
$$PWD/net/portforwarder.cpp \
|
||||||
|
$$PWD/net/proxyconfigurationmanager.cpp \
|
||||||
$$PWD/net/reverseresolution.cpp \
|
$$PWD/net/reverseresolution.cpp \
|
||||||
$$PWD/net/smtp.cpp \
|
$$PWD/net/smtp.cpp \
|
||||||
$$PWD/net/private/geoipdatabase.cpp \
|
$$PWD/net/private/geoipdatabase.cpp \
|
||||||
|
|||||||
@@ -31,13 +31,13 @@
|
|||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "bandwidthscheduler.h"
|
#include "bandwidthscheduler.h"
|
||||||
|
|
||||||
BandwidthScheduler::BandwidthScheduler(QObject *parent)
|
BandwidthScheduler::BandwidthScheduler(QObject *parent)
|
||||||
: QTimer(parent)
|
: QTimer(parent)
|
||||||
{
|
{
|
||||||
Q_ASSERT(Preferences::instance()->isSchedulerEnabled());
|
|
||||||
// Single shot, we call start() again manually
|
// Single shot, we call start() again manually
|
||||||
setSingleShot(true);
|
setSingleShot(true);
|
||||||
// Connect Signals/Slots
|
// Connect Signals/Slots
|
||||||
@@ -47,8 +47,7 @@ BandwidthScheduler::BandwidthScheduler(QObject *parent)
|
|||||||
void BandwidthScheduler::start()
|
void BandwidthScheduler::start()
|
||||||
{
|
{
|
||||||
const Preferences* const pref = Preferences::instance();
|
const Preferences* const pref = Preferences::instance();
|
||||||
Q_ASSERT(pref->isSchedulerEnabled());
|
bool alt_bw_enabled = BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled();
|
||||||
bool alt_bw_enabled = pref->isAltBandwidthEnabled();
|
|
||||||
|
|
||||||
QTime start = pref->getSchedulerStartTime();
|
QTime start = pref->getSchedulerStartTime();
|
||||||
QTime end = pref->getSchedulerEndTime();
|
QTime end = pref->getSchedulerEndTime();
|
||||||
|
|||||||
@@ -55,10 +55,10 @@ FilterParserThread::~FilterParserThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser for eMule ip filter in DAT format
|
// Parser for eMule ip filter in DAT format
|
||||||
int FilterParserThread::parseDATFilterFile(QString m_filePath, libt::ip_filter &filter)
|
int FilterParserThread::parseDATFilterFile(QString filePath, libt::ip_filter &filter)
|
||||||
{
|
{
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
QFile file(m_filePath);
|
QFile file(filePath);
|
||||||
if (!file.exists()) return ruleCount;
|
if (!file.exists()) return ruleCount;
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
@@ -149,10 +149,10 @@ int FilterParserThread::parseDATFilterFile(QString m_filePath, libt::ip_filter &
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser for PeerGuardian ip filter in p2p format
|
// Parser for PeerGuardian ip filter in p2p format
|
||||||
int FilterParserThread::parseP2PFilterFile(QString m_filePath, libt::ip_filter &filter)
|
int FilterParserThread::parseP2PFilterFile(QString filePath, libt::ip_filter &filter)
|
||||||
{
|
{
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
QFile file(m_filePath);
|
QFile file(filePath);
|
||||||
if (!file.exists()) return ruleCount;
|
if (!file.exists()) return ruleCount;
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
@@ -257,10 +257,10 @@ int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser for PeerGuardian ip filter in p2p format
|
// Parser for PeerGuardian ip filter in p2p format
|
||||||
int FilterParserThread::parseP2BFilterFile(QString m_filePath, libt::ip_filter &filter)
|
int FilterParserThread::parseP2BFilterFile(QString filePath, libt::ip_filter &filter)
|
||||||
{
|
{
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
QFile file(m_filePath);
|
QFile file(filePath);
|
||||||
if (!file.exists()) return ruleCount;
|
if (!file.exists()) return ruleCount;
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
@@ -369,7 +369,7 @@ int FilterParserThread::parseP2BFilterFile(QString m_filePath, libt::ip_filter &
|
|||||||
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
||||||
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
||||||
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
||||||
void FilterParserThread::processFilterFile(QString _filePath)
|
void FilterParserThread::processFilterFile(QString filePath)
|
||||||
{
|
{
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
// Already parsing a filter, m_abort first
|
// Already parsing a filter, m_abort first
|
||||||
@@ -378,27 +378,11 @@ void FilterParserThread::processFilterFile(QString _filePath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_abort = false;
|
m_abort = false;
|
||||||
m_filePath = _filePath;
|
m_filePath = filePath;
|
||||||
// Run it
|
// Run it
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilterParserThread::processFilterList(libt::session *s, const QStringList &IPs)
|
|
||||||
{
|
|
||||||
// First, import current filter
|
|
||||||
libt::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;
|
|
||||||
libt::address addr = libt::address::from_string(ip.toLocal8Bit().constData(), ec);
|
|
||||||
Q_ASSERT(!ec);
|
|
||||||
if (!ec)
|
|
||||||
filter.add_rule(addr, addr, libt::ip_filter::blocked);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->set_ip_filter(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FilterParserThread::cleanupIPAddress(QString _ip)
|
QString FilterParserThread::cleanupIPAddress(QString _ip)
|
||||||
{
|
{
|
||||||
_ip = _ip.trimmed();
|
_ip = _ip.trimmed();
|
||||||
|
|||||||
@@ -49,13 +49,7 @@ class FilterParserThread : public QThread
|
|||||||
public:
|
public:
|
||||||
FilterParserThread(libtorrent::session *s, QObject *parent = 0);
|
FilterParserThread(libtorrent::session *s, QObject *parent = 0);
|
||||||
~FilterParserThread();
|
~FilterParserThread();
|
||||||
|
void processFilterFile(QString filePath);
|
||||||
int parseDATFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
|
||||||
int parseP2PFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
|
||||||
int getlineInStream(QDataStream &stream, std::string &name, char delim);
|
|
||||||
int parseP2BFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
|
||||||
void processFilterFile(QString _filePath);
|
|
||||||
static void processFilterList(libtorrent::session *s, const QStringList &IPs);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void IPFilterParsed(int ruleCount);
|
void IPFilterParsed(int ruleCount);
|
||||||
@@ -66,6 +60,11 @@ protected:
|
|||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int parseDATFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
||||||
|
int parseP2PFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
||||||
|
int getlineInStream(QDataStream &stream, std::string &name, char delim);
|
||||||
|
int parseP2BFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
||||||
|
|
||||||
libtorrent::session *m_session;
|
libtorrent::session *m_session;
|
||||||
bool m_abort;
|
bool m_abort;
|
||||||
QString m_filePath;
|
QString m_filePath;
|
||||||
|
|||||||
@@ -30,17 +30,23 @@
|
|||||||
#ifndef BITTORRENT_SESSION_H
|
#ifndef BITTORRENT_SESSION_H
|
||||||
#define BITTORRENT_SESSION_H
|
#define BITTORRENT_SESSION_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QPointer>
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
#include <QVector>
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QWaitCondition>
|
#endif
|
||||||
#include <QNetworkConfigurationManager>
|
#include <QNetworkConfigurationManager>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
|
||||||
#include <libtorrent/version.hpp>
|
#include "base/settingvalue.h"
|
||||||
|
|
||||||
#include "base/tristatebool.h"
|
#include "base/tristatebool.h"
|
||||||
#include "base/types.h"
|
#include "base/types.h"
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
@@ -52,19 +58,12 @@ namespace libtorrent
|
|||||||
class entry;
|
class entry;
|
||||||
struct add_torrent_params;
|
struct add_torrent_params;
|
||||||
struct pe_settings;
|
struct pe_settings;
|
||||||
struct session_settings;
|
|
||||||
struct session_status;
|
|
||||||
|
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
struct proxy_settings;
|
struct session_settings;
|
||||||
#else
|
#else
|
||||||
namespace aux
|
struct settings_pack;
|
||||||
{
|
|
||||||
struct proxy_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef aux::proxy_settings proxy_settings;
|
|
||||||
#endif
|
#endif
|
||||||
|
struct session_status;
|
||||||
|
|
||||||
class alert;
|
class alert;
|
||||||
struct torrent_alert;
|
struct torrent_alert;
|
||||||
@@ -111,7 +110,6 @@ class FilterParserThread;
|
|||||||
class BandwidthScheduler;
|
class BandwidthScheduler;
|
||||||
class Statistics;
|
class Statistics;
|
||||||
class ResumeDataSavingManager;
|
class ResumeDataSavingManager;
|
||||||
class SettingsStorage;
|
|
||||||
|
|
||||||
enum MaxRatioAction
|
enum MaxRatioAction
|
||||||
{
|
{
|
||||||
@@ -172,13 +170,6 @@ namespace BitTorrent
|
|||||||
static void freeInstance();
|
static void freeInstance();
|
||||||
static Session *instance();
|
static Session *instance();
|
||||||
|
|
||||||
bool isDHTEnabled() const;
|
|
||||||
bool isLSDEnabled() const;
|
|
||||||
bool isPexEnabled() const;
|
|
||||||
bool isQueueingEnabled() const;
|
|
||||||
qreal globalMaxRatio() const;
|
|
||||||
bool isAppendExtensionEnabled() const;
|
|
||||||
|
|
||||||
QString defaultSavePath() const;
|
QString defaultSavePath() const;
|
||||||
void setDefaultSavePath(QString path);
|
void setDefaultSavePath(QString path);
|
||||||
QString tempPath() const;
|
QString tempPath() const;
|
||||||
@@ -219,8 +210,122 @@ namespace BitTorrent
|
|||||||
bool isDisableAutoTMMWhenCategorySavePathChanged() const;
|
bool isDisableAutoTMMWhenCategorySavePathChanged() const;
|
||||||
void setDisableAutoTMMWhenCategorySavePathChanged(bool value);
|
void setDisableAutoTMMWhenCategorySavePathChanged(bool value);
|
||||||
|
|
||||||
|
qreal globalMaxRatio() const;
|
||||||
|
void setGlobalMaxRatio(qreal ratio);
|
||||||
|
bool isDHTEnabled() const;
|
||||||
|
void setDHTEnabled(bool enabled);
|
||||||
|
bool isLSDEnabled() const;
|
||||||
|
void setLSDEnabled(bool enabled);
|
||||||
|
bool isPeXEnabled() const;
|
||||||
|
void setPeXEnabled(bool enabled);
|
||||||
bool isAddTorrentPaused() const;
|
bool isAddTorrentPaused() const;
|
||||||
void setAddTorrentPaused(bool value);
|
void setAddTorrentPaused(bool value);
|
||||||
|
bool isTrackerEnabled() const;
|
||||||
|
void setTrackerEnabled(bool enabled);
|
||||||
|
bool isAppendExtensionEnabled() const;
|
||||||
|
void setAppendExtensionEnabled(bool enabled);
|
||||||
|
uint refreshInterval() const;
|
||||||
|
void setRefreshInterval(uint value);
|
||||||
|
bool isPreallocationEnabled() const;
|
||||||
|
void setPreallocationEnabled(bool enabled);
|
||||||
|
QString torrentExportDirectory() const;
|
||||||
|
void setTorrentExportDirectory(QString path);
|
||||||
|
QString finishedTorrentExportDirectory() const;
|
||||||
|
void setFinishedTorrentExportDirectory(QString path);
|
||||||
|
|
||||||
|
int globalDownloadSpeedLimit() const;
|
||||||
|
void setGlobalDownloadSpeedLimit(int limit);
|
||||||
|
int globalUploadSpeedLimit() const;
|
||||||
|
void setGlobalUploadSpeedLimit(int limit);
|
||||||
|
int altGlobalDownloadSpeedLimit() const;
|
||||||
|
void setAltGlobalDownloadSpeedLimit(int limit);
|
||||||
|
int altGlobalUploadSpeedLimit() const;
|
||||||
|
void setAltGlobalUploadSpeedLimit(int limit);
|
||||||
|
int downloadSpeedLimit() const;
|
||||||
|
void setDownloadSpeedLimit(int limit);
|
||||||
|
int uploadSpeedLimit() const;
|
||||||
|
void setUploadSpeedLimit(int limit);
|
||||||
|
bool isAltGlobalSpeedLimitEnabled() const;
|
||||||
|
void setAltGlobalSpeedLimitEnabled(bool enabled);
|
||||||
|
bool isBandwidthSchedulerEnabled() const;
|
||||||
|
void setBandwidthSchedulerEnabled(bool enabled);
|
||||||
|
|
||||||
|
uint saveResumeDataInterval() const;
|
||||||
|
void setSaveResumeDataInterval(uint value);
|
||||||
|
int port() const;
|
||||||
|
void setPort(int port);
|
||||||
|
bool useRandomPort() const;
|
||||||
|
void setUseRandomPort(bool value);
|
||||||
|
QString networkInterface() const;
|
||||||
|
void setNetworkInterface(const QString &interface);
|
||||||
|
QString networkInterfaceName() const;
|
||||||
|
void setNetworkInterfaceName(const QString &name);
|
||||||
|
QString networkInterfaceAddress() const;
|
||||||
|
void setNetworkInterfaceAddress(const QString &address);
|
||||||
|
bool isIPv6Enabled() const;
|
||||||
|
void setIPv6Enabled(bool enabled);
|
||||||
|
int encryption() const;
|
||||||
|
void setEncryption(int state);
|
||||||
|
bool isForceProxyEnabled() const;
|
||||||
|
void setForceProxyEnabled(bool enabled);
|
||||||
|
bool isProxyPeerConnectionsEnabled() const;
|
||||||
|
void setProxyPeerConnectionsEnabled(bool enabled);
|
||||||
|
bool isAddTrackersEnabled() const;
|
||||||
|
void setAddTrackersEnabled(bool enabled);
|
||||||
|
QString additionalTrackers() const;
|
||||||
|
void setAdditionalTrackers(const QString &trackers);
|
||||||
|
bool isIPFilteringEnabled() const;
|
||||||
|
void setIPFilteringEnabled(bool enabled);
|
||||||
|
QString IPFilterFile() const;
|
||||||
|
void setIPFilterFile(QString path);
|
||||||
|
bool announceToAllTrackers() const;
|
||||||
|
void setAnnounceToAllTrackers(bool val);
|
||||||
|
uint diskCacheSize() const;
|
||||||
|
void setDiskCacheSize(uint size);
|
||||||
|
uint diskCacheTTL() const;
|
||||||
|
void setDiskCacheTTL(uint ttl);
|
||||||
|
bool useOSCache() const;
|
||||||
|
void setUseOSCache(bool use);
|
||||||
|
bool isAnonymousModeEnabled() const;
|
||||||
|
void setAnonymousModeEnabled(bool enabled);
|
||||||
|
bool isQueueingSystemEnabled() const;
|
||||||
|
void setQueueingSystemEnabled(bool enabled);
|
||||||
|
bool ignoreSlowTorrentsForQueueing() const;
|
||||||
|
void setIgnoreSlowTorrentsForQueueing(bool ignore);
|
||||||
|
uint outgoingPortsMin() const;
|
||||||
|
void setOutgoingPortsMin(uint min);
|
||||||
|
uint outgoingPortsMax() const;
|
||||||
|
void setOutgoingPortsMax(uint max);
|
||||||
|
bool ignoreLimitsOnLAN() const;
|
||||||
|
void setIgnoreLimitsOnLAN(bool ignore);
|
||||||
|
bool includeOverheadInLimits() const;
|
||||||
|
void setIncludeOverheadInLimits(bool include);
|
||||||
|
QString announceIP() const;
|
||||||
|
void setAnnounceIP(const QString &ip);
|
||||||
|
bool isSuperSeedingEnabled() const;
|
||||||
|
void setSuperSeedingEnabled(bool enabled);
|
||||||
|
int maxConnections() const;
|
||||||
|
void setMaxConnections(int max);
|
||||||
|
int maxHalfOpenConnections() const;
|
||||||
|
void setMaxHalfOpenConnections(int max);
|
||||||
|
int maxConnectionsPerTorrent() const;
|
||||||
|
void setMaxConnectionsPerTorrent(int max);
|
||||||
|
int maxUploads() const;
|
||||||
|
void setMaxUploads(int max);
|
||||||
|
int maxUploadsPerTorrent() const;
|
||||||
|
void setMaxUploadsPerTorrent(int max);
|
||||||
|
int maxActiveDownloads() const;
|
||||||
|
void setMaxActiveDownloads(int max);
|
||||||
|
int maxActiveUploads() const;
|
||||||
|
void setMaxActiveUploads(int max);
|
||||||
|
int maxActiveTorrents() const;
|
||||||
|
void setMaxActiveTorrents(int max);
|
||||||
|
bool isUTPEnabled() const;
|
||||||
|
void setUTPEnabled(bool enabled);
|
||||||
|
bool isUTPRateLimited() const;
|
||||||
|
void setUTPRateLimited(bool limited);
|
||||||
|
bool isTrackerFilteringEnabled() const;
|
||||||
|
void setTrackerFilteringEnabled(bool enabled);
|
||||||
|
|
||||||
TorrentHandle *findTorrent(const InfoHash &hash) const;
|
TorrentHandle *findTorrent(const InfoHash &hash) const;
|
||||||
QHash<InfoHash, TorrentHandle *> torrents() const;
|
QHash<InfoHash, TorrentHandle *> torrents() const;
|
||||||
@@ -231,19 +336,11 @@ namespace BitTorrent
|
|||||||
CacheStatus cacheStatus() const;
|
CacheStatus cacheStatus() const;
|
||||||
quint64 getAlltimeDL() const;
|
quint64 getAlltimeDL() const;
|
||||||
quint64 getAlltimeUL() const;
|
quint64 getAlltimeUL() const;
|
||||||
int downloadRateLimit() const;
|
|
||||||
int uploadRateLimit() const;
|
|
||||||
bool isListening() const;
|
bool isListening() const;
|
||||||
|
|
||||||
MaxRatioAction maxRatioAction() const;
|
MaxRatioAction maxRatioAction() const;
|
||||||
void setMaxRatioAction(MaxRatioAction act);
|
void setMaxRatioAction(MaxRatioAction act);
|
||||||
|
|
||||||
void changeSpeedLimitMode(bool alternative);
|
|
||||||
void setDownloadRateLimit(int rate);
|
|
||||||
void setUploadRateLimit(int rate);
|
|
||||||
void setGlobalMaxRatio(qreal ratio);
|
|
||||||
void enableIPFilter(const QString &filterPath, bool force = false);
|
|
||||||
void disableIPFilter();
|
|
||||||
void banIP(const QString &ip);
|
void banIP(const QString &ip);
|
||||||
|
|
||||||
bool isKnownTorrent(const InfoHash &hash) const;
|
bool isKnownTorrent(const InfoHash &hash) const;
|
||||||
@@ -304,7 +401,7 @@ namespace BitTorrent
|
|||||||
void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent);
|
void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent);
|
||||||
void recursiveTorrentDownloadPossible(BitTorrent::TorrentHandle *const torrent);
|
void recursiveTorrentDownloadPossible(BitTorrent::TorrentHandle *const torrent);
|
||||||
void speedLimitModeChanged(bool alternative);
|
void speedLimitModeChanged(bool alternative);
|
||||||
void ipFilterParsed(bool error, int ruleCount);
|
void IPFilterParsed(bool error, int ruleCount);
|
||||||
void trackersAdded(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
void trackersAdded(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
||||||
void trackersRemoved(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
void trackersRemoved(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
||||||
void trackersChanged(BitTorrent::TorrentHandle *const torrent);
|
void trackersChanged(BitTorrent::TorrentHandle *const torrent);
|
||||||
@@ -316,7 +413,7 @@ namespace BitTorrent
|
|||||||
void subcategoriesSupportChanged();
|
void subcategoriesSupportChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void configure();
|
void configureDeferred();
|
||||||
void readAlerts();
|
void readAlerts();
|
||||||
void refresh();
|
void refresh();
|
||||||
void processBigRatios();
|
void processBigRatios();
|
||||||
@@ -341,20 +438,24 @@ namespace BitTorrent
|
|||||||
void initResumeFolder();
|
void initResumeFolder();
|
||||||
|
|
||||||
// Session configuration
|
// Session configuration
|
||||||
void setSessionSettings();
|
Q_INVOKABLE void configure();
|
||||||
void setProxySettings(libtorrent::proxy_settings proxySettings);
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
void adjustLimits();
|
void configure(libtorrent::session_settings &sessionSettings);
|
||||||
void adjustLimits(libtorrent::session_settings &sessionSettings);
|
void adjustLimits(libtorrent::session_settings &sessionSettings);
|
||||||
|
#else
|
||||||
|
void configure(libtorrent::settings_pack &settingsPack);
|
||||||
|
void adjustLimits(libtorrent::settings_pack &settingsPack);
|
||||||
|
#endif
|
||||||
|
void adjustLimits();
|
||||||
|
void processBannedIPs();
|
||||||
const QStringList getListeningIPs();
|
const QStringList getListeningIPs();
|
||||||
void setListeningPort();
|
void configureListeningInterface();
|
||||||
void preAllocateAllFiles(bool b);
|
|
||||||
void setMaxConnectionsPerTorrent(int max);
|
|
||||||
void setMaxUploadsPerTorrent(int max);
|
|
||||||
void enableLSD(bool enable);
|
|
||||||
void enableDHT(bool enable);
|
|
||||||
void changeSpeedLimitMode_impl(bool alternative);
|
void changeSpeedLimitMode_impl(bool alternative);
|
||||||
|
void enableTracker(bool enable);
|
||||||
void setAppendExtension(bool append);
|
void enableBandwidthScheduler();
|
||||||
|
void populateAdditionalTrackers();
|
||||||
|
void enableIPFilter();
|
||||||
|
void disableIPFilter();
|
||||||
|
|
||||||
void startUpTorrents();
|
void startUpTorrents();
|
||||||
bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri,
|
bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri,
|
||||||
@@ -364,7 +465,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
void updateRatioTimer();
|
void updateRatioTimer();
|
||||||
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
||||||
void saveTorrentResumeData(TorrentHandle *const torrent);
|
void saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave = false);
|
||||||
|
|
||||||
void handleAlert(libtorrent::alert *a);
|
void handleAlert(libtorrent::alert *a);
|
||||||
void dispatchTorrentAlert(libtorrent::alert *a);
|
void dispatchTorrentAlert(libtorrent::alert *a);
|
||||||
@@ -389,35 +490,97 @@ namespace BitTorrent
|
|||||||
void saveResumeData();
|
void saveResumeData();
|
||||||
|
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
void dispatchAlerts(std::auto_ptr<libtorrent::alert> alertPtr);
|
void dispatchAlerts(libtorrent::alert *alertPtr);
|
||||||
#endif
|
#endif
|
||||||
void getPendingAlerts(std::vector<libtorrent::alert *> &out, ulong time = 0);
|
void getPendingAlerts(std::vector<libtorrent::alert *> &out, ulong time = 0);
|
||||||
|
|
||||||
SettingsStorage *m_settings;
|
|
||||||
|
|
||||||
// BitTorrent
|
// BitTorrent
|
||||||
libtorrent::session *m_nativeSession;
|
libtorrent::session *m_nativeSession;
|
||||||
|
|
||||||
bool m_LSDEnabled;
|
bool m_deferredConfigureScheduled;
|
||||||
bool m_DHTEnabled;
|
bool m_IPFilteringChanged;
|
||||||
bool m_PeXEnabled;
|
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||||
bool m_queueingEnabled;
|
bool m_listenInterfaceChanged; // optimization
|
||||||
bool m_torrentExportEnabled;
|
#endif
|
||||||
bool m_finishedTorrentExportEnabled;
|
CachedSettingValue<bool> m_isDHTEnabled;
|
||||||
bool m_preAllocateAll;
|
CachedSettingValue<bool> m_isLSDEnabled;
|
||||||
qreal m_globalMaxRatio;
|
CachedSettingValue<bool> m_isPeXEnabled;
|
||||||
|
CachedSettingValue<bool> m_isIPFilteringEnabled;
|
||||||
|
CachedSettingValue<bool> m_isTrackerFilteringEnabled;
|
||||||
|
CachedSettingValue<QString> m_IPFilterFile;
|
||||||
|
CachedSettingValue<bool> m_announceToAllTrackers;
|
||||||
|
CachedSettingValue<uint> m_diskCacheSize;
|
||||||
|
CachedSettingValue<uint> m_diskCacheTTL;
|
||||||
|
CachedSettingValue<bool> m_useOSCache;
|
||||||
|
CachedSettingValue<bool> m_isAnonymousModeEnabled;
|
||||||
|
CachedSettingValue<bool> m_isQueueingEnabled;
|
||||||
|
CachedSettingValue<int> m_maxActiveDownloads;
|
||||||
|
CachedSettingValue<int> m_maxActiveUploads;
|
||||||
|
CachedSettingValue<int> m_maxActiveTorrents;
|
||||||
|
CachedSettingValue<bool> m_ignoreSlowTorrentsForQueueing;
|
||||||
|
CachedSettingValue<uint> m_outgoingPortsMin;
|
||||||
|
CachedSettingValue<uint> m_outgoingPortsMax;
|
||||||
|
CachedSettingValue<bool> m_ignoreLimitsOnLAN;
|
||||||
|
CachedSettingValue<bool> m_includeOverheadInLimits;
|
||||||
|
CachedSettingValue<QString> m_announceIP;
|
||||||
|
CachedSettingValue<bool> m_isSuperSeedingEnabled;
|
||||||
|
CachedSettingValue<int> m_maxConnections;
|
||||||
|
CachedSettingValue<int> m_maxHalfOpenConnections;
|
||||||
|
CachedSettingValue<int> m_maxUploads;
|
||||||
|
CachedSettingValue<int> m_maxConnectionsPerTorrent;
|
||||||
|
CachedSettingValue<int> m_maxUploadsPerTorrent;
|
||||||
|
CachedSettingValue<bool> m_isUTPEnabled;
|
||||||
|
CachedSettingValue<bool> m_isUTPRateLimited;
|
||||||
|
CachedSettingValue<bool> m_isAddTrackersEnabled;
|
||||||
|
CachedSettingValue<QString> m_additionalTrackers;
|
||||||
|
CachedSettingValue<qreal> m_globalMaxRatio;
|
||||||
|
CachedSettingValue<bool> m_isAddTorrentPaused;
|
||||||
|
CachedSettingValue<bool> m_isAppendExtensionEnabled;
|
||||||
|
CachedSettingValue<uint> m_refreshInterval;
|
||||||
|
CachedSettingValue<bool> m_isPreallocationEnabled;
|
||||||
|
CachedSettingValue<QString> m_torrentExportDirectory;
|
||||||
|
CachedSettingValue<QString> m_finishedTorrentExportDirectory;
|
||||||
|
CachedSettingValue<int> m_globalDownloadSpeedLimit;
|
||||||
|
CachedSettingValue<int> m_globalUploadSpeedLimit;
|
||||||
|
CachedSettingValue<int> m_altGlobalDownloadSpeedLimit;
|
||||||
|
CachedSettingValue<int> m_altGlobalUploadSpeedLimit;
|
||||||
|
CachedSettingValue<bool> m_isAltGlobalSpeedLimitEnabled;
|
||||||
|
CachedSettingValue<bool> m_isBandwidthSchedulerEnabled;
|
||||||
|
CachedSettingValue<uint> m_saveResumeDataInterval;
|
||||||
|
CachedSettingValue<int> m_port;
|
||||||
|
CachedSettingValue<bool> m_useRandomPort;
|
||||||
|
CachedSettingValue<QString> m_networkInterface;
|
||||||
|
CachedSettingValue<QString> m_networkInterfaceName;
|
||||||
|
CachedSettingValue<QString> m_networkInterfaceAddress;
|
||||||
|
CachedSettingValue<bool> m_isIPv6Enabled;
|
||||||
|
CachedSettingValue<int> m_encryption;
|
||||||
|
CachedSettingValue<bool> m_isForceProxyEnabled;
|
||||||
|
CachedSettingValue<bool> m_isProxyPeerConnectionsEnabled;
|
||||||
|
CachedSettingValue<QVariantMap> m_storedCategories;
|
||||||
|
CachedSettingValue<int> m_maxRatioAction;
|
||||||
|
CachedSettingValue<QString> m_defaultSavePath;
|
||||||
|
CachedSettingValue<QString> m_tempPath;
|
||||||
|
CachedSettingValue<bool> m_isSubcategoriesEnabled;
|
||||||
|
CachedSettingValue<bool> m_isTempPathEnabled;
|
||||||
|
CachedSettingValue<bool> m_isAutoTMMDisabledByDefault;
|
||||||
|
CachedSettingValue<bool> m_isDisableAutoTMMWhenCategoryChanged;
|
||||||
|
CachedSettingValue<bool> m_isDisableAutoTMMWhenDefaultSavePathChanged;
|
||||||
|
CachedSettingValue<bool> m_isDisableAutoTMMWhenCategorySavePathChanged;
|
||||||
|
CachedSettingValue<bool> m_isTrackerEnabled;
|
||||||
|
CachedSettingValue<QStringList> m_bannedIPs;
|
||||||
|
|
||||||
|
// Order is important. This needs to be declared after its CachedSettingsValue
|
||||||
|
// counterpart, because it uses it for initialization in the constructor
|
||||||
|
// initialization list.
|
||||||
|
const bool m_wasPexEnabled;
|
||||||
|
|
||||||
int m_numResumeData;
|
int m_numResumeData;
|
||||||
int m_extraLimit;
|
int m_extraLimit;
|
||||||
bool m_appendExtension;
|
QList<BitTorrent::TrackerEntry> m_additionalTrackerList;
|
||||||
uint m_refreshInterval;
|
|
||||||
MaxRatioAction m_maxRatioAction;
|
|
||||||
QList<BitTorrent::TrackerEntry> m_additionalTrackers;
|
|
||||||
QString m_defaultSavePath;
|
|
||||||
QString m_tempPath;
|
|
||||||
QString m_filterPath;
|
|
||||||
QString m_resumeFolderPath;
|
QString m_resumeFolderPath;
|
||||||
QFile m_resumeFolderLock;
|
QFile m_resumeFolderLock;
|
||||||
QHash<InfoHash, QString> m_savePathsToRemove;
|
QHash<InfoHash, QString> m_savePathsToRemove;
|
||||||
|
bool m_useProxy;
|
||||||
|
|
||||||
QTimer *m_refreshTimer;
|
QTimer *m_refreshTimer;
|
||||||
QTimer *m_bigRatioTimer;
|
QTimer *m_bigRatioTimer;
|
||||||
@@ -447,6 +610,8 @@ namespace BitTorrent
|
|||||||
|
|
||||||
QNetworkConfigurationManager m_networkManager;
|
QNetworkConfigurationManager m_networkManager;
|
||||||
|
|
||||||
|
mutable QReadWriteLock m_lock;
|
||||||
|
|
||||||
static Session *m_instance;
|
static Session *m_instance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
@@ -192,6 +194,31 @@ const qreal TorrentHandle::NO_RATIO_LIMIT = -1.;
|
|||||||
|
|
||||||
const qreal TorrentHandle::MAX_RATIO = 9999.;
|
const qreal TorrentHandle::MAX_RATIO = 9999.;
|
||||||
|
|
||||||
|
// The new libtorrent::create_torrent constructor appeared after 1.0.11 in RC_1_0
|
||||||
|
// and after 1.1.1 in RC_1_1. Since it fixed an ABI incompatibility with previous versions
|
||||||
|
// distros might choose to backport it onto 1.0.11 and 1.1.1 respectively.
|
||||||
|
// So we need a way to detect its presence without relying solely on the LIBTORRENT_VERSION_NUM.
|
||||||
|
// Relevant links:
|
||||||
|
// 1. https://github.com/arvidn/libtorrent/issues/1696
|
||||||
|
// 2. https://github.com/qbittorrent/qBittorrent/issues/6406
|
||||||
|
// The following can be removed after one or two libtorrent releases on each branch.
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// new constructor is available
|
||||||
|
template<typename T, typename std::enable_if<std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0>
|
||||||
|
T makeTorrentCreator(const libtorrent::torrent_info & ti)
|
||||||
|
{
|
||||||
|
return T(ti, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// new constructor isn't available
|
||||||
|
template<typename T, typename std::enable_if<!std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0>
|
||||||
|
T makeTorrentCreator(const libtorrent::torrent_info & ti)
|
||||||
|
{
|
||||||
|
return T(ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
|
TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
|
||||||
const AddTorrentData &data)
|
const AddTorrentData &data)
|
||||||
: QObject(session)
|
: QObject(session)
|
||||||
@@ -485,8 +512,11 @@ bool TorrentHandle::needSaveResumeData() const
|
|||||||
SAFE_RETURN(bool, need_save_resume_data, false);
|
SAFE_RETURN(bool, need_save_resume_data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentHandle::saveResumeData()
|
void TorrentHandle::saveResumeData(bool updateStatus)
|
||||||
{
|
{
|
||||||
|
if (updateStatus) // to update queue_position, see discussion in PR #6154
|
||||||
|
this->updateStatus();
|
||||||
|
|
||||||
SAFE_CALL(save_resume_data);
|
SAFE_CALL(save_resume_data);
|
||||||
m_needSaveResumeData = false;
|
m_needSaveResumeData = false;
|
||||||
}
|
}
|
||||||
@@ -752,7 +782,7 @@ void TorrentHandle::updateState()
|
|||||||
m_state = isSeed() ? TorrentState::PausedUploading : TorrentState::PausedDownloading;
|
m_state = isSeed() ? TorrentState::PausedUploading : TorrentState::PausedDownloading;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_session->isQueueingEnabled() && isQueued() && !isChecking()) {
|
if (m_session->isQueueingSystemEnabled() && isQueued() && !isChecking()) {
|
||||||
m_state = isSeed() ? TorrentState::QueuedUploading : TorrentState::QueuedDownloading;
|
m_state = isSeed() ? TorrentState::QueuedUploading : TorrentState::QueuedDownloading;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -915,26 +945,29 @@ int TorrentHandle::leechsCount() const
|
|||||||
|
|
||||||
int TorrentHandle::totalSeedsCount() const
|
int TorrentHandle::totalSeedsCount() const
|
||||||
{
|
{
|
||||||
return m_nativeStatus.list_seeds;
|
return (m_nativeStatus.num_complete > 0) ? m_nativeStatus.num_complete : m_nativeStatus.list_seeds;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentHandle::totalPeersCount() const
|
int TorrentHandle::totalPeersCount() const
|
||||||
{
|
{
|
||||||
return m_nativeStatus.list_peers;
|
int peers = m_nativeStatus.num_complete + m_nativeStatus.num_incomplete;
|
||||||
|
return (peers > 0) ? peers : m_nativeStatus.list_peers;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentHandle::totalLeechersCount() const
|
int TorrentHandle::totalLeechersCount() const
|
||||||
{
|
{
|
||||||
return (m_nativeStatus.list_peers - m_nativeStatus.list_seeds);
|
return (m_nativeStatus.num_incomplete > 0) ? m_nativeStatus.num_incomplete : (m_nativeStatus.list_peers - m_nativeStatus.list_seeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentHandle::completeCount() const
|
int TorrentHandle::completeCount() const
|
||||||
{
|
{
|
||||||
|
// additional info: https://github.com/qbittorrent/qBittorrent/pull/5300#issuecomment-267783646
|
||||||
return m_nativeStatus.num_complete;
|
return m_nativeStatus.num_complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentHandle::incompleteCount() const
|
int TorrentHandle::incompleteCount() const
|
||||||
{
|
{
|
||||||
|
// additional info: https://github.com/qbittorrent/qBittorrent/pull/5300#issuecomment-267783646
|
||||||
return m_nativeStatus.num_incomplete;
|
return m_nativeStatus.num_incomplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1280,7 +1313,7 @@ void TorrentHandle::moveStorage(const QString &newPath)
|
|||||||
m_queuedPath = newPath;
|
m_queuedPath = newPath;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QString oldPath = nativeActualSavePath();
|
const QString oldPath = nativeActualSavePath();
|
||||||
if (QDir(oldPath) == QDir(newPath)) return;
|
if (QDir(oldPath) == QDir(newPath)) return;
|
||||||
|
|
||||||
qDebug("move storage: %s to %s", qPrintable(oldPath), qPrintable(newPath));
|
qDebug("move storage: %s to %s", qPrintable(oldPath), qPrintable(newPath));
|
||||||
@@ -1312,7 +1345,7 @@ bool TorrentHandle::saveTorrentFile(const QString &path)
|
|||||||
{
|
{
|
||||||
if (!m_torrentInfo.isValid()) return false;
|
if (!m_torrentInfo.isValid()) return false;
|
||||||
|
|
||||||
libt::create_torrent torrentCreator(*(m_torrentInfo.nativeInfo()));
|
libt::create_torrent torrentCreator = makeTorrentCreator<libt::create_torrent>(*(m_torrentInfo.nativeInfo()));
|
||||||
libt::entry torrentEntry = torrentCreator.generate();
|
libt::entry torrentEntry = torrentCreator.generate();
|
||||||
|
|
||||||
QVector<char> out;
|
QVector<char> out;
|
||||||
@@ -1347,7 +1380,7 @@ void TorrentHandle::handleStorageMovedAlert(libtorrent::storage_moved_alert *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString newPath = Utils::String::fromStdString(p->path);
|
const QString newPath = Utils::String::fromStdString(p->path);
|
||||||
if (newPath != m_newPath) {
|
if (newPath != m_newPath) {
|
||||||
qWarning() << Q_FUNC_INFO << ": New path doesn't match a path in a queue.";
|
qWarning() << Q_FUNC_INFO << ": New path doesn't match a path in a queue.";
|
||||||
return;
|
return;
|
||||||
@@ -1367,13 +1400,6 @@ void TorrentHandle::handleStorageMovedAlert(libtorrent::storage_moved_alert *p)
|
|||||||
m_session->handleTorrentSavePathChanged(this);
|
m_session->handleTorrentSavePathChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to remove old folder if empty
|
|
||||||
QDir oldSaveDir(Utils::Fs::fromNativePath(m_oldPath));
|
|
||||||
if (oldSaveDir != QDir(m_session->defaultSavePath())) {
|
|
||||||
qDebug("Attempting to remove %s", qPrintable(m_oldPath));
|
|
||||||
QDir().rmpath(m_oldPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
||||||
m_moveFinishedTriggers.takeFirst()();
|
m_moveFinishedTriggers.takeFirst()();
|
||||||
}
|
}
|
||||||
@@ -1702,6 +1728,11 @@ void TorrentHandle::manageIncompleteFiles()
|
|||||||
{
|
{
|
||||||
const bool isAppendExtensionEnabled = m_session->isAppendExtensionEnabled();
|
const bool isAppendExtensionEnabled = m_session->isAppendExtensionEnabled();
|
||||||
QVector<qreal> fp = filesProgress();
|
QVector<qreal> fp = filesProgress();
|
||||||
|
if( fp.size() != filesCount() ) {
|
||||||
|
qDebug() << "skip manageIncompleteFiles because of invalid torrent meta-data or empty file-progress";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < filesCount(); ++i) {
|
for (int i = 0; i < filesCount(); ++i) {
|
||||||
QString name = filePath(i);
|
QString name = filePath(i);
|
||||||
if (isAppendExtensionEnabled && (fileSize(i) > 0) && (fp[i] < 1)) {
|
if (isAppendExtensionEnabled && (fileSize(i) > 0) && (fp[i] < 1)) {
|
||||||
@@ -1815,6 +1846,8 @@ void TorrentHandle::setDownloadLimit(int limit)
|
|||||||
void TorrentHandle::setSuperSeeding(bool enable)
|
void TorrentHandle::setSuperSeeding(bool enable)
|
||||||
{
|
{
|
||||||
SAFE_CALL(super_seeding, enable)
|
SAFE_CALL(super_seeding, enable)
|
||||||
|
if (superSeeding() != enable)
|
||||||
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentHandle::flushCache()
|
void TorrentHandle::flushCache()
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ namespace BitTorrent
|
|||||||
void handleTempPathChanged();
|
void handleTempPathChanged();
|
||||||
void handleCategorySavePathChanged();
|
void handleCategorySavePathChanged();
|
||||||
void handleAppendExtensionToggled();
|
void handleAppendExtensionToggled();
|
||||||
void saveResumeData();
|
void saveResumeData(bool updateStatus = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef boost::function<void ()> EventTrigger;
|
typedef boost::function<void ()> EventTrigger;
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ QVector<int> TorrentInfo::fileIndicesForPiece(int pieceIndex) const
|
|||||||
std::vector<libt::file_slice> files(
|
std::vector<libt::file_slice> files(
|
||||||
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex)));
|
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex)));
|
||||||
QVector<int> res;
|
QVector<int> res;
|
||||||
res.reserve(files.size());
|
res.reserve(int(files.size()));
|
||||||
std::transform(files.begin(), files.end(), std::back_inserter(res),
|
std::transform(files.begin(), files.end(), std::back_inserter(res),
|
||||||
[](const libt::file_slice &s) { return s.file_index; });
|
[](const libt::file_slice &s) { return s.file_index; });
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#endif
|
#endif
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QTemporaryFile>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "requestparser.h"
|
#include "requestparser.h"
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#else
|
#else
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#endif
|
#endif
|
||||||
|
#include <QNetworkProxy>
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
@@ -45,6 +46,10 @@ Server::Server(IRequestHandler *requestHandler, QObject *parent)
|
|||||||
, m_https(false)
|
, m_https(false)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
setProxy(QNetworkProxy::NoProxy);
|
||||||
|
#ifndef QT_NO_OPENSSL
|
||||||
|
QSslSocket::setDefaultCiphers(safeCipherList());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
@@ -91,6 +96,7 @@ void Server::incomingConnection(int socketDescriptor)
|
|||||||
#else
|
#else
|
||||||
static_cast<QSslSocket *>(serverSocket)->setLocalCertificate(m_certificates.first());
|
static_cast<QSslSocket *>(serverSocket)->setLocalCertificate(m_certificates.first());
|
||||||
#endif
|
#endif
|
||||||
|
static_cast<QSslSocket *>(serverSocket)->setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
static_cast<QSslSocket *>(serverSocket)->startServerEncryption();
|
static_cast<QSslSocket *>(serverSocket)->startServerEncryption();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -100,3 +106,26 @@ void Server::incomingConnection(int socketDescriptor)
|
|||||||
serverSocket->deleteLater();
|
serverSocket->deleteLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENSSL
|
||||||
|
QList<QSslCipher> Server::safeCipherList() const
|
||||||
|
{
|
||||||
|
const QStringList badCiphers = {"idea", "rc4"};
|
||||||
|
const QList<QSslCipher> allCiphers = QSslSocket::supportedCiphers();
|
||||||
|
QList<QSslCipher> safeCiphers;
|
||||||
|
foreach (const QSslCipher &cipher, allCiphers) {
|
||||||
|
bool isSafe = true;
|
||||||
|
foreach (const QString &badCipher, badCiphers) {
|
||||||
|
if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) {
|
||||||
|
isSafe = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSafe)
|
||||||
|
safeCiphers += cipher;
|
||||||
|
}
|
||||||
|
|
||||||
|
return safeCiphers;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
#include <QSslCertificate>
|
#include <QSslCertificate>
|
||||||
|
#include <QSslCipher>
|
||||||
#include <QSslKey>
|
#include <QSslKey>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -59,15 +60,17 @@ namespace Http
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
IRequestHandler *m_requestHandler;
|
||||||
|
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
void incomingConnection(qintptr socketDescriptor);
|
void incomingConnection(qintptr socketDescriptor);
|
||||||
#else
|
#else
|
||||||
void incomingConnection(int socketDescriptor);
|
void incomingConnection(int socketDescriptor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
|
||||||
IRequestHandler *m_requestHandler;
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
|
QList<QSslCipher> safeCipherList() const;
|
||||||
|
|
||||||
bool m_https;
|
bool m_https;
|
||||||
QList<QSslCertificate> m_certificates;
|
QList<QSslCertificate> m_certificates;
|
||||||
QSslKey m_key;
|
QSslKey m_key;
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ namespace Http
|
|||||||
const QString HEADER_CONTENT_ENCODING = "Content-Encoding";
|
const QString HEADER_CONTENT_ENCODING = "Content-Encoding";
|
||||||
const QString HEADER_CONTENT_LENGTH = "Content-Length";
|
const QString HEADER_CONTENT_LENGTH = "Content-Length";
|
||||||
const QString HEADER_CACHE_CONTROL = "Cache-Control";
|
const QString HEADER_CACHE_CONTROL = "Cache-Control";
|
||||||
|
const QString HEADER_X_FRAME_OPTIONS = "X-Frame-Options";
|
||||||
|
const QString HEADER_X_XSS_PROTECTION = "X-XSS-Protection";
|
||||||
|
const QString HEADER_X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options";
|
||||||
|
const QString HEADER_CONTENT_SECURITY_POLICY = "Content-Security-Policy";
|
||||||
|
|
||||||
const QString CONTENT_TYPE_CSS = "text/css; charset=UTF-8";
|
const QString CONTENT_TYPE_CSS = "text/css; charset=UTF-8";
|
||||||
const QString CONTENT_TYPE_GIF = "image/gif";
|
const QString CONTENT_TYPE_GIF = "image/gif";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include "base/utils/string.h"
|
||||||
|
|
||||||
Logger* Logger::m_instance = 0;
|
Logger* Logger::m_instance = 0;
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
|||||||
{
|
{
|
||||||
QWriteLocker locker(&lock);
|
QWriteLocker locker(&lock);
|
||||||
|
|
||||||
Log::Msg temp = { msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message };
|
Log::Msg temp = { msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, Utils::String::toHtmlEscaped(message) };
|
||||||
m_messages.push_back(temp);
|
m_messages.push_back(temp);
|
||||||
|
|
||||||
if (m_messages.size() >= MAX_LOG_MESSAGES)
|
if (m_messages.size() >= MAX_LOG_MESSAGES)
|
||||||
@@ -49,7 +50,7 @@ void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
|
|||||||
{
|
{
|
||||||
QWriteLocker locker(&lock);
|
QWriteLocker locker(&lock);
|
||||||
|
|
||||||
Log::Peer temp = { peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip, blocked, reason };
|
Log::Peer temp = { peerCounter++, QDateTime::currentMSecsSinceEpoch(), Utils::String::toHtmlEscaped(ip), blocked, Utils::String::toHtmlEscaped(reason) };
|
||||||
m_peers.push_back(temp);
|
m_peers.push_back(temp);
|
||||||
|
|
||||||
if (m_peers.size() >= MAX_LOG_MESSAGES)
|
if (m_peers.size() >= MAX_LOG_MESSAGES)
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ void DownloadHandler::init()
|
|||||||
|
|
||||||
bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
||||||
{
|
{
|
||||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
QTemporaryFile *tmpfile = new QTemporaryFile(Utils::Fs::tempPath() + "XXXXXX");
|
||||||
if (!tmpfile->open()) {
|
if (!tmpfile->open()) {
|
||||||
delete tmpfile;
|
delete tmpfile;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -27,20 +27,21 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "downloadmanager.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QNetworkRequest>
|
#include <QDebug>
|
||||||
#include <QNetworkProxy>
|
|
||||||
#include <QNetworkCookieJar>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QNetworkCookie>
|
#include <QNetworkCookie>
|
||||||
#include <QNetworkCookieJar>
|
#include <QNetworkCookieJar>
|
||||||
|
#include <QNetworkProxy>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
#include <QSslError>
|
#include <QSslError>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "downloadhandler.h"
|
#include "downloadhandler.h"
|
||||||
#include "downloadmanager.h"
|
#include "proxyconfigurationmanager.h"
|
||||||
|
|
||||||
// Spoof Firefox 38 user agent to avoid web server banning
|
// Spoof Firefox 38 user agent to avoid web server banning
|
||||||
const char DEFAULT_USER_AGENT[] = "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0";
|
const char DEFAULT_USER_AGENT[] = "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0";
|
||||||
@@ -208,16 +209,16 @@ bool DownloadManager::deleteCookie(const QNetworkCookie &cookie)
|
|||||||
|
|
||||||
void DownloadManager::applyProxySettings()
|
void DownloadManager::applyProxySettings()
|
||||||
{
|
{
|
||||||
|
auto proxyManager = ProxyConfigurationManager::instance();
|
||||||
|
ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||||
QNetworkProxy proxy;
|
QNetworkProxy proxy;
|
||||||
const Preferences* const pref = Preferences::instance();
|
|
||||||
|
|
||||||
if (pref->isProxyEnabled() && !pref->isProxyOnlyForTorrents()) {
|
if (!proxyManager->isProxyOnlyForTorrents() && (proxyConfig.type != ProxyType::None)) {
|
||||||
// Proxy enabled
|
// Proxy enabled
|
||||||
proxy.setHostName(pref->getProxyIp());
|
proxy.setHostName(proxyConfig.ip);
|
||||||
proxy.setPort(pref->getProxyPort());
|
proxy.setPort(proxyConfig.port);
|
||||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||||
const int proxyType = pref->getProxyType();
|
if ((proxyConfig.type == ProxyType::SOCKS5) || (proxyConfig.type == ProxyType::SOCKS5_PW)) {
|
||||||
if ((proxyType == Proxy::SOCKS5) || (proxyType == Proxy::SOCKS5_PW)) {
|
|
||||||
qDebug() << Q_FUNC_INFO << "using SOCKS proxy";
|
qDebug() << Q_FUNC_INFO << "using SOCKS proxy";
|
||||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||||
}
|
}
|
||||||
@@ -226,10 +227,10 @@ void DownloadManager::applyProxySettings()
|
|||||||
proxy.setType(QNetworkProxy::HttpProxy);
|
proxy.setType(QNetworkProxy::HttpProxy);
|
||||||
}
|
}
|
||||||
// Authentication?
|
// Authentication?
|
||||||
if (pref->isProxyAuthEnabled()) {
|
if (proxyManager->isAuthenticationRequired()) {
|
||||||
qDebug("Proxy requires authentication, authenticating");
|
qDebug("Proxy requires authentication, authenticating");
|
||||||
proxy.setUser(pref->getProxyUsername());
|
proxy.setUser(proxyConfig.username);
|
||||||
proxy.setPassword(pref->getProxyPassword());
|
proxy.setPassword(proxyConfig.password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
static const char DATABASE_URL[] = "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz";
|
static const char DATABASE_URL[] = "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz";
|
||||||
static const char GEOIP_FOLDER[] = "GeoIP";
|
static const char GEOIP_FOLDER[] = "GeoIP";
|
||||||
static const char GEOIP_FILENAME[] = "GeoLite2-Country.mmdb";
|
static const char GEOIP_FILENAME[] = "GeoLite2-Country.mmdb";
|
||||||
static const int CACHE_SIZE = 1000;
|
|
||||||
static const int UPDATE_INTERVAL = 30; // Days between database updates
|
static const int UPDATE_INTERVAL = 30; // Days between database updates
|
||||||
|
|
||||||
using namespace Net;
|
using namespace Net;
|
||||||
|
|||||||
@@ -26,13 +26,17 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "portforwarder.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <libtorrent/session.hpp>
|
#include <libtorrent/session.hpp>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/preferences.h"
|
#include "base/settingsstorage.h"
|
||||||
#include "portforwarder.h"
|
|
||||||
|
static const QString KEY_ENABLED = QLatin1String("Network/PortForwardingEnabled");
|
||||||
|
|
||||||
namespace libt = libtorrent;
|
namespace libt = libtorrent;
|
||||||
using namespace Net;
|
using namespace Net;
|
||||||
@@ -42,8 +46,8 @@ PortForwarder::PortForwarder(libtorrent::session *provider, QObject *parent)
|
|||||||
, m_active(false)
|
, m_active(false)
|
||||||
, m_provider(provider)
|
, m_provider(provider)
|
||||||
{
|
{
|
||||||
configure();
|
if (SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool())
|
||||||
connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure()));
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
PortForwarder::~PortForwarder()
|
PortForwarder::~PortForwarder()
|
||||||
@@ -70,7 +74,24 @@ PortForwarder *PortForwarder::instance()
|
|||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortForwarder::addPort(qint16 port)
|
bool PortForwarder::isEnabled() const
|
||||||
|
{
|
||||||
|
return m_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarder::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (m_active != enabled) {
|
||||||
|
if (enabled)
|
||||||
|
start();
|
||||||
|
else
|
||||||
|
stop();
|
||||||
|
|
||||||
|
SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarder::addPort(quint16 port)
|
||||||
{
|
{
|
||||||
if (!m_mappedPorts.contains(port)) {
|
if (!m_mappedPorts.contains(port)) {
|
||||||
m_mappedPorts.insert(port, 0);
|
m_mappedPorts.insert(port, 0);
|
||||||
@@ -79,7 +100,7 @@ void PortForwarder::addPort(qint16 port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortForwarder::deletePort(qint16 port)
|
void PortForwarder::deletePort(quint16 port)
|
||||||
{
|
{
|
||||||
if (m_mappedPorts.contains(port)) {
|
if (m_mappedPorts.contains(port)) {
|
||||||
if (m_active)
|
if (m_active)
|
||||||
@@ -88,23 +109,19 @@ void PortForwarder::deletePort(qint16 port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortForwarder::configure()
|
|
||||||
{
|
|
||||||
bool enable = Preferences::instance()->isUPnPEnabled();
|
|
||||||
if (m_active != enable) {
|
|
||||||
if (enable)
|
|
||||||
start();
|
|
||||||
else
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::start()
|
void PortForwarder::start()
|
||||||
{
|
{
|
||||||
qDebug("Enabling UPnP / NAT-PMP");
|
qDebug("Enabling UPnP / NAT-PMP");
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
m_provider->start_upnp();
|
m_provider->start_upnp();
|
||||||
m_provider->start_natpmp();
|
m_provider->start_natpmp();
|
||||||
foreach (qint16 port, m_mappedPorts.keys())
|
#else
|
||||||
|
libt::settings_pack settingsPack = m_provider->get_settings();
|
||||||
|
settingsPack.set_bool(libt::settings_pack::enable_upnp, true);
|
||||||
|
settingsPack.set_bool(libt::settings_pack::enable_natpmp, true);
|
||||||
|
m_provider->apply_settings(settingsPack);
|
||||||
|
#endif
|
||||||
|
foreach (quint16 port, m_mappedPorts.keys())
|
||||||
m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port);
|
m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port);
|
||||||
m_active = true;
|
m_active = true;
|
||||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
||||||
@@ -113,8 +130,15 @@ void PortForwarder::start()
|
|||||||
void PortForwarder::stop()
|
void PortForwarder::stop()
|
||||||
{
|
{
|
||||||
qDebug("Disabling UPnP / NAT-PMP");
|
qDebug("Disabling UPnP / NAT-PMP");
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
m_provider->stop_upnp();
|
m_provider->stop_upnp();
|
||||||
m_provider->stop_natpmp();
|
m_provider->stop_natpmp();
|
||||||
|
#else
|
||||||
|
libt::settings_pack settingsPack = m_provider->get_settings();
|
||||||
|
settingsPack.set_bool(libt::settings_pack::enable_upnp, false);
|
||||||
|
settingsPack.set_bool(libt::settings_pack::enable_natpmp, false);
|
||||||
|
m_provider->apply_settings(settingsPack);
|
||||||
|
#endif
|
||||||
m_active = false;
|
m_active = false;
|
||||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,11 +49,11 @@ namespace Net
|
|||||||
static void freeInstance();
|
static void freeInstance();
|
||||||
static PortForwarder *instance();
|
static PortForwarder *instance();
|
||||||
|
|
||||||
void addPort(qint16 port);
|
bool isEnabled() const;
|
||||||
void deletePort(qint16 port);
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
private slots:
|
void addPort(quint16 port);
|
||||||
void configure();
|
void deletePort(quint16 port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit PortForwarder(libtorrent::session *const provider, QObject *parent = 0);
|
explicit PortForwarder(libtorrent::session *const provider, QObject *parent = 0);
|
||||||
@@ -64,7 +64,7 @@ namespace Net
|
|||||||
|
|
||||||
bool m_active;
|
bool m_active;
|
||||||
libtorrent::session *m_provider;
|
libtorrent::session *m_provider;
|
||||||
QHash<qint16, int> m_mappedPorts;
|
QHash<quint16, int> m_mappedPorts;
|
||||||
|
|
||||||
static PortForwarder *m_instance;
|
static PortForwarder *m_instance;
|
||||||
};
|
};
|
||||||
|
|||||||
163
src/base/net/proxyconfigurationmanager.cpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "proxyconfigurationmanager.h"
|
||||||
|
#include "base/settingsstorage.h"
|
||||||
|
|
||||||
|
#define SETTINGS_KEY(name) "Network/Proxy/" name
|
||||||
|
const QString KEY_ONLY_FOR_TORRENTS = SETTINGS_KEY("OnlyForTorrents");
|
||||||
|
const QString KEY_TYPE = SETTINGS_KEY("Type");
|
||||||
|
const QString KEY_IP = SETTINGS_KEY("IP");
|
||||||
|
const QString KEY_PORT = SETTINGS_KEY("Port");
|
||||||
|
const QString KEY_USERNAME = SETTINGS_KEY("Username");
|
||||||
|
const QString KEY_PASSWORD = SETTINGS_KEY("Password");
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
inline SettingsStorage *settings() { return SettingsStorage::instance(); }
|
||||||
|
|
||||||
|
inline bool isSameConfig(const Net::ProxyConfiguration &conf1, const Net::ProxyConfiguration &conf2)
|
||||||
|
{
|
||||||
|
return conf1.type == conf2.type
|
||||||
|
&& conf1.ip == conf2.ip
|
||||||
|
&& conf1.port == conf2.port
|
||||||
|
&& conf1.username == conf2.username
|
||||||
|
&& conf1.password == conf2.password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace Net;
|
||||||
|
|
||||||
|
ProxyConfigurationManager *ProxyConfigurationManager::m_instance = nullptr;
|
||||||
|
|
||||||
|
ProxyConfigurationManager::ProxyConfigurationManager(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
m_isProxyOnlyForTorrents = settings()->loadValue(KEY_ONLY_FOR_TORRENTS, false).toBool();
|
||||||
|
m_config.type = static_cast<ProxyType>(
|
||||||
|
settings()->loadValue(KEY_TYPE, static_cast<int>(ProxyType::None)).toInt());
|
||||||
|
if ((m_config.type < ProxyType::None) || (m_config.type > ProxyType::SOCKS4))
|
||||||
|
m_config.type = ProxyType::None;
|
||||||
|
m_config.ip = settings()->loadValue(KEY_IP, "0.0.0.0").toString();
|
||||||
|
m_config.port = static_cast<ushort>(settings()->loadValue(KEY_PORT, 8080).toUInt());
|
||||||
|
m_config.username = settings()->loadValue(KEY_USERNAME).toString();
|
||||||
|
m_config.password = settings()->loadValue(KEY_PASSWORD).toString();
|
||||||
|
configureProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyConfigurationManager::initInstance()
|
||||||
|
{
|
||||||
|
if (!m_instance)
|
||||||
|
m_instance = new ProxyConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyConfigurationManager::freeInstance()
|
||||||
|
{
|
||||||
|
if (m_instance) {
|
||||||
|
delete m_instance;
|
||||||
|
m_instance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyConfigurationManager *ProxyConfigurationManager::instance()
|
||||||
|
{
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyConfiguration ProxyConfigurationManager::proxyConfiguration() const
|
||||||
|
{
|
||||||
|
return m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyConfigurationManager::setProxyConfiguration(const ProxyConfiguration &config)
|
||||||
|
{
|
||||||
|
if (!isSameConfig(config, m_config)) {
|
||||||
|
m_config = config;
|
||||||
|
settings()->storeValue(KEY_TYPE, static_cast<int>(config.type));
|
||||||
|
settings()->storeValue(KEY_IP, config.ip);
|
||||||
|
settings()->storeValue(KEY_PORT, config.port);
|
||||||
|
settings()->storeValue(KEY_USERNAME, config.username);
|
||||||
|
settings()->storeValue(KEY_PASSWORD, config.password);
|
||||||
|
configureProxy();
|
||||||
|
|
||||||
|
emit proxyConfigurationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyConfigurationManager::isProxyOnlyForTorrents() const
|
||||||
|
{
|
||||||
|
return m_isProxyOnlyForTorrents || (m_config.type == ProxyType::SOCKS4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyConfigurationManager::setProxyOnlyForTorrents(bool onlyForTorrents)
|
||||||
|
{
|
||||||
|
if (m_isProxyOnlyForTorrents != onlyForTorrents) {
|
||||||
|
settings()->storeValue(KEY_ONLY_FOR_TORRENTS, onlyForTorrents);
|
||||||
|
m_isProxyOnlyForTorrents = onlyForTorrents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyConfigurationManager::isAuthenticationRequired() const
|
||||||
|
{
|
||||||
|
return m_config.type == ProxyType::SOCKS5_PW
|
||||||
|
|| m_config.type == ProxyType::HTTP_PW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyConfigurationManager::configureProxy()
|
||||||
|
{
|
||||||
|
// Define environment variables for urllib in search engine plugins
|
||||||
|
QString proxyStrHTTP, proxyStrSOCK;
|
||||||
|
if (!m_isProxyOnlyForTorrents) {
|
||||||
|
switch (m_config.type) {
|
||||||
|
case ProxyType::HTTP_PW:
|
||||||
|
proxyStrHTTP = QString("http://%1:%2@%3:%4").arg(m_config.username)
|
||||||
|
.arg(m_config.password).arg(m_config.ip).arg(m_config.port);
|
||||||
|
break;
|
||||||
|
case ProxyType::HTTP:
|
||||||
|
proxyStrHTTP = QString("http://%1:%2").arg(m_config.ip).arg(m_config.port);
|
||||||
|
break;
|
||||||
|
case ProxyType::SOCKS5:
|
||||||
|
proxyStrSOCK = QString("%1:%2").arg(m_config.ip).arg(m_config.port);
|
||||||
|
break;
|
||||||
|
case ProxyType::SOCKS5_PW:
|
||||||
|
proxyStrSOCK = QString("%1:%2@%3:%4").arg(m_config.username)
|
||||||
|
.arg(m_config.password).arg(m_config.ip).arg(m_config.port);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug("Disabling HTTP communications proxy");
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("HTTP communications proxy string: %s"
|
||||||
|
, qPrintable((m_config.type == ProxyType::SOCKS5) || (m_config.type == ProxyType::SOCKS5_PW)
|
||||||
|
? proxyStrSOCK : proxyStrHTTP));
|
||||||
|
}
|
||||||
|
|
||||||
|
qputenv("http_proxy", proxyStrHTTP.toLocal8Bit());
|
||||||
|
qputenv("https_proxy", proxyStrHTTP.toLocal8Bit());
|
||||||
|
qputenv("sock_proxy", proxyStrSOCK.toLocal8Bit());
|
||||||
|
}
|
||||||
87
src/base/net/proxyconfigurationmanager.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_PROXYCONFIGURATIONMANAGER_H
|
||||||
|
#define NET_PROXYCONFIGURATIONMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Net
|
||||||
|
{
|
||||||
|
enum class ProxyType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
HTTP = 1,
|
||||||
|
SOCKS5 = 2,
|
||||||
|
HTTP_PW = 3,
|
||||||
|
SOCKS5_PW = 4,
|
||||||
|
SOCKS4 = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProxyConfiguration
|
||||||
|
{
|
||||||
|
ProxyType type = ProxyType::None;
|
||||||
|
QString ip = "0.0.0.0";
|
||||||
|
ushort port = 8080;
|
||||||
|
QString username;
|
||||||
|
QString password;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProxyConfigurationManager: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(ProxyConfigurationManager)
|
||||||
|
|
||||||
|
explicit ProxyConfigurationManager(QObject *parent = nullptr);
|
||||||
|
~ProxyConfigurationManager() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void initInstance();
|
||||||
|
static void freeInstance();
|
||||||
|
static ProxyConfigurationManager *instance();
|
||||||
|
|
||||||
|
ProxyConfiguration proxyConfiguration() const;
|
||||||
|
void setProxyConfiguration(const ProxyConfiguration &config);
|
||||||
|
bool isProxyOnlyForTorrents() const;
|
||||||
|
void setProxyOnlyForTorrents(bool onlyForTorrents);
|
||||||
|
|
||||||
|
bool isAuthenticationRequired() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void proxyConfigurationChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void configureProxy();
|
||||||
|
|
||||||
|
static ProxyConfigurationManager *m_instance;
|
||||||
|
ProxyConfiguration m_config;
|
||||||
|
bool m_isProxyOnlyForTorrents;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NET_PROXYCONFIGURATIONMANAGER_H
|
||||||
@@ -53,7 +53,9 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const short DEFAULT_PORT = 25;
|
const short DEFAULT_PORT = 25;
|
||||||
|
#ifndef QT_NO_OPENSSL
|
||||||
const short DEFAULT_PORT_SSL = 465;
|
const short DEFAULT_PORT_SSL = 465;
|
||||||
|
#endif
|
||||||
|
|
||||||
QByteArray hmacMD5(QByteArray key, const QByteArray &msg)
|
QByteArray hmacMD5(QByteArray key, const QByteArray &msg)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,8 +31,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QPair>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QLocale>
|
||||||
|
#include <QPair>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
@@ -50,8 +51,6 @@
|
|||||||
#include <CoreServices/CoreServices.h>
|
#include <CoreServices/CoreServices.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include "utils/fs.h"
|
#include "utils/fs.h"
|
||||||
#include "utils/misc.h"
|
#include "utils/misc.h"
|
||||||
#include "settingsstorage.h"
|
#include "settingsstorage.h"
|
||||||
@@ -60,10 +59,7 @@
|
|||||||
|
|
||||||
Preferences* Preferences::m_instance = 0;
|
Preferences* Preferences::m_instance = 0;
|
||||||
|
|
||||||
Preferences::Preferences()
|
Preferences::Preferences() {}
|
||||||
: m_randomPort(rand() % 64512 + 1024)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Preferences *Preferences::instance()
|
Preferences *Preferences::instance()
|
||||||
{
|
{
|
||||||
@@ -97,7 +93,7 @@ void Preferences::setValue(const QString &key, const QVariant &value)
|
|||||||
// General options
|
// General options
|
||||||
QString Preferences::getLocale() const
|
QString Preferences::getLocale() const
|
||||||
{
|
{
|
||||||
return value("Preferences/General/Locale").toString();
|
return value("Preferences/General/Locale", QLocale::system().name()).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setLocale(const QString &locale)
|
void Preferences::setLocale(const QString &locale)
|
||||||
@@ -165,16 +161,6 @@ void Preferences::setHideZeroComboValues(int n)
|
|||||||
setValue("Preferences/General/HideZeroComboValues", n);
|
setValue("Preferences/General/HideZeroComboValues", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Preferences::useRandomPort() const
|
|
||||||
{
|
|
||||||
return value("Preferences/General/UseRandomPort", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setRandomPort(bool b)
|
|
||||||
{
|
|
||||||
setValue("Preferences/General/UseRandomPort", b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::systrayIntegration() const
|
bool Preferences::systrayIntegration() const
|
||||||
{
|
{
|
||||||
return value("Preferences/General/SystrayEnabled", true).toBool();
|
return value("Preferences/General/SystrayEnabled", true).toBool();
|
||||||
@@ -267,16 +253,6 @@ void Preferences::setWinStartup(bool b)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Downloads
|
// Downloads
|
||||||
bool Preferences::useIncompleteFilesExtension() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Downloads/UseIncompleteExtension", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::useIncompleteFilesExtension(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Downloads/UseIncompleteExtension", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::lastLocationPath() const
|
QString Preferences::lastLocationPath() const
|
||||||
{
|
{
|
||||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/LastLocationPath").toString());
|
return Utils::Fs::fromNativePath(value("Preferences/Downloads/LastLocationPath").toString());
|
||||||
@@ -287,16 +263,6 @@ void Preferences::setLastLocationPath(const QString &path)
|
|||||||
setValue("Preferences/Downloads/LastLocationPath", Utils::Fs::fromNativePath(path));
|
setValue("Preferences/Downloads/LastLocationPath", Utils::Fs::fromNativePath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Preferences::preAllocateAllFiles() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Downloads/PreAllocation", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::preAllocateAllFiles(bool enabled)
|
|
||||||
{
|
|
||||||
return setValue("Preferences/Downloads/PreAllocation", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantHash Preferences::getScanDirs() const
|
QVariantHash Preferences::getScanDirs() const
|
||||||
{
|
{
|
||||||
return value("Preferences/Downloads/ScanDirsV2").toHash();
|
return value("Preferences/Downloads/ScanDirsV2").toHash();
|
||||||
@@ -318,36 +284,6 @@ void Preferences::setScanDirsLastPath(const QString &path)
|
|||||||
setValue("Preferences/Downloads/ScanDirsLastPath", Utils::Fs::fromNativePath(path));
|
setValue("Preferences/Downloads/ScanDirsLastPath", Utils::Fs::fromNativePath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Preferences::isTorrentExportEnabled() const
|
|
||||||
{
|
|
||||||
return !value("Preferences/Downloads/TorrentExportDir").toString().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getTorrentExportDir() const
|
|
||||||
{
|
|
||||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/TorrentExportDir").toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setTorrentExportDir(QString path)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Downloads/TorrentExportDir", Utils::Fs::fromNativePath(path.trimmed()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isFinishedTorrentExportEnabled() const
|
|
||||||
{
|
|
||||||
return !value("Preferences/Downloads/FinishedTorrentExportDir").toString().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getFinishedTorrentExportDir() const
|
|
||||||
{
|
|
||||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/FinishedTorrentExportDir").toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setFinishedTorrentExportDir(QString path)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Downloads/FinishedTorrentExportDir", Utils::Fs::fromNativePath(path.trimmed()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isMailNotificationEnabled() const
|
bool Preferences::isMailNotificationEnabled() const
|
||||||
{
|
{
|
||||||
return value("Preferences/MailNotification/enabled", false).toBool();
|
return value("Preferences/MailNotification/enabled", false).toBool();
|
||||||
@@ -438,97 +374,6 @@ void Preferences::setActionOnDblClOnTorrentFn(int act)
|
|||||||
setValue("Preferences/Downloads/DblClOnTorFn", act);
|
setValue("Preferences/Downloads/DblClOnTorFn", act);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection options
|
|
||||||
int Preferences::getSessionPort() const
|
|
||||||
{
|
|
||||||
if (useRandomPort())
|
|
||||||
return m_randomPort;
|
|
||||||
return value("Preferences/Connection/PortRangeMin", 8999).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setSessionPort(int port)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/PortRangeMin", port);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isUPnPEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/UPnP", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setUPnPEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/UPnP", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getGlobalDownloadLimit() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/GlobalDLLimit", -1).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setGlobalDownloadLimit(int limit)
|
|
||||||
{
|
|
||||||
if (limit <= 0)
|
|
||||||
limit = -1;
|
|
||||||
setValue("Preferences/Connection/GlobalDLLimit", limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getGlobalUploadLimit() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/GlobalUPLimit", -1).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setGlobalUploadLimit(int limit)
|
|
||||||
{
|
|
||||||
if (limit <= 0)
|
|
||||||
limit = -1;
|
|
||||||
setValue("Preferences/Connection/GlobalUPLimit", limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getAltGlobalDownloadLimit() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/GlobalDLLimitAlt", 10).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setAltGlobalDownloadLimit(int limit)
|
|
||||||
{
|
|
||||||
if (limit <= 0)
|
|
||||||
limit = -1;
|
|
||||||
setValue("Preferences/Connection/GlobalDLLimitAlt", limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getAltGlobalUploadLimit() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/GlobalUPLimitAlt", 10).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setAltGlobalUploadLimit(int limit)
|
|
||||||
{
|
|
||||||
if (limit <= 0)
|
|
||||||
limit = -1;
|
|
||||||
setValue("Preferences/Connection/GlobalUPLimitAlt", limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isAltBandwidthEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/alt_speeds_on", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setAltBandwidthEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/alt_speeds_on", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isSchedulerEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Scheduler/Enabled", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setSchedulerEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Scheduler/Enabled", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
QTime Preferences::getSchedulerStartTime() const
|
QTime Preferences::getSchedulerStartTime() const
|
||||||
{
|
{
|
||||||
return value("Preferences/Scheduler/start_time", QTime(8,0)).toTime();
|
return value("Preferences/Scheduler/start_time", QTime(8,0)).toTime();
|
||||||
@@ -559,286 +404,6 @@ void Preferences::setSchedulerDays(scheduler_days days)
|
|||||||
setValue("Preferences/Scheduler/days", (int)days);
|
setValue("Preferences/Scheduler/days", (int)days);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proxy options
|
|
||||||
bool Preferences::isProxyEnabled() const
|
|
||||||
{
|
|
||||||
return getProxyType() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isProxyAuthEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/Proxy/Authentication", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyAuthEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/Proxy/Authentication", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getProxyIp() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/Proxy/IP", "0.0.0.0").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyIp(const QString &ip)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/Proxy/IP", ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short Preferences::getProxyPort() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/Proxy/Port", 8080).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyPort(unsigned short port)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/Proxy/Port", port);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getProxyUsername() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/Proxy/Username").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyUsername(const QString &username)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/Proxy/Username", username);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getProxyPassword() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/Proxy/Password").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyPassword(const QString &password)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/Proxy/Password", password);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getProxyType() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/ProxyType", 0).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyType(int type)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/ProxyType", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::proxyPeerConnections() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/ProxyPeerConnections", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyPeerConnections(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/ProxyPeerConnections", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::getForceProxy() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/ProxyForce", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setForceProxy(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/ProxyForce", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setProxyOnlyForTorrents(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/ProxyOnlyForTorrents", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isProxyOnlyForTorrents() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/ProxyOnlyForTorrents", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bittorrent options
|
|
||||||
int Preferences::getMaxConnecs() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/MaxConnecs", 500).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxConnecs(int val)
|
|
||||||
{
|
|
||||||
if (val <= 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Bittorrent/MaxConnecs", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getMaxConnecsPerTorrent() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/MaxConnecsPerTorrent", 100).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxConnecsPerTorrent(int val)
|
|
||||||
{
|
|
||||||
if (val <= 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Bittorrent/MaxConnecsPerTorrent", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getMaxUploads() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/MaxUploads", -1).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxUploads(int val)
|
|
||||||
{
|
|
||||||
if (val <= 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Bittorrent/MaxUploads", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getMaxUploadsPerTorrent() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/MaxUploadsPerTorrent", -1).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxUploadsPerTorrent(int val)
|
|
||||||
{
|
|
||||||
if (val <= 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Bittorrent/MaxUploadsPerTorrent", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isuTPEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/uTP", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setuTPEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/uTP", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isuTPRateLimited() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/uTP_rate_limited", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setuTPRateLimited(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/uTP_rate_limited", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isDHTEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/DHT", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setDHTEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/DHT", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isPeXEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/PeX", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setPeXEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/PeX", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isLSDEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/LSD", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setLSDEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/LSD", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getEncryptionSetting() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/Encryption", 0).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setEncryptionSetting(int val)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/Encryption", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isAddTrackersEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/AddTrackers", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setAddTrackersEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/AddTrackers", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getTrackersList() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/TrackersList").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setTrackersList(const QString &val)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/TrackersList", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal Preferences::getGlobalMaxRatio() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Bittorrent/MaxRatio", -1).toReal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setGlobalMaxRatio(qreal ratio)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Bittorrent/MaxRatio", ratio);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IP Filter
|
|
||||||
bool Preferences::isFilteringEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/IPFilter/Enabled", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setFilteringEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/IPFilter/Enabled", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isFilteringTrackerEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/IPFilter/FilterTracker", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setFilteringTrackerEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/IPFilter/FilterTracker", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getFilter() const
|
|
||||||
{
|
|
||||||
return Utils::Fs::fromNativePath(value("Preferences/IPFilter/File").toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setFilter(const QString &path)
|
|
||||||
{
|
|
||||||
setValue("Preferences/IPFilter/File", Utils::Fs::fromNativePath(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList Preferences::bannedIPs() const
|
|
||||||
{
|
|
||||||
return value("Preferences/IPFilter/BannedIPs").toStringList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::banIP(const QString &ip)
|
|
||||||
{
|
|
||||||
QStringList banned_ips = value("Preferences/IPFilter/BannedIPs").toStringList();
|
|
||||||
if (!banned_ips.contains(ip)) {
|
|
||||||
banned_ips << ip;
|
|
||||||
setValue("Preferences/IPFilter/BannedIPs", banned_ips);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
bool Preferences::isSearchEnabled() const
|
bool Preferences::isSearchEnabled() const
|
||||||
{
|
{
|
||||||
@@ -850,63 +415,6 @@ void Preferences::setSearchEnabled(bool enabled)
|
|||||||
setValue("Preferences/Search/SearchEnabled", enabled);
|
setValue("Preferences/Search/SearchEnabled", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Queueing system
|
|
||||||
bool Preferences::isQueueingSystemEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Queueing/QueueingEnabled", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setQueueingSystemEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Queueing/QueueingEnabled", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getMaxActiveDownloads() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Queueing/MaxActiveDownloads", 3).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxActiveDownloads(int val)
|
|
||||||
{
|
|
||||||
if (val < 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Queueing/MaxActiveDownloads", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getMaxActiveUploads() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Queueing/MaxActiveUploads", 3).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxActiveUploads(int val)
|
|
||||||
{
|
|
||||||
if (val < 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Queueing/MaxActiveUploads", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getMaxActiveTorrents() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Queueing/MaxActiveTorrents", 5).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxActiveTorrents(int val)
|
|
||||||
{
|
|
||||||
if (val < 0)
|
|
||||||
val = -1;
|
|
||||||
setValue("Preferences/Queueing/MaxActiveTorrents", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::ignoreSlowTorrentsForQueueing() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Queueing/IgnoreSlowTorrents", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setIgnoreSlowTorrentsForQueueing(bool ignore)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Queueing/IgnoreSlowTorrents", ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isWebUiEnabled() const
|
bool Preferences::isWebUiEnabled() const
|
||||||
{
|
{
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
@@ -943,7 +451,11 @@ void Preferences::setWebUiPort(quint16 port)
|
|||||||
|
|
||||||
bool Preferences::useUPnPForWebUIPort() const
|
bool Preferences::useUPnPForWebUIPort() const
|
||||||
{
|
{
|
||||||
|
#ifdef DISABLE_GUI
|
||||||
return value("Preferences/WebUI/UseUPnP", true).toBool();
|
return value("Preferences/WebUI/UseUPnP", true).toBool();
|
||||||
|
#else
|
||||||
|
return value("Preferences/WebUI/UseUPnP", false).toBool();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setUPnPForWebUIPort(bool enabled)
|
void Preferences::setUPnPForWebUIPort(bool enabled)
|
||||||
@@ -1164,111 +676,6 @@ void Preferences::setDontConfirmAutoExit(bool dontConfirmAutoExit)
|
|||||||
setValue("ShutdownConfirmDlg/DontConfirmAutoExit", dontConfirmAutoExit);
|
setValue("ShutdownConfirmDlg/DontConfirmAutoExit", dontConfirmAutoExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Preferences::diskCacheSize() const
|
|
||||||
{
|
|
||||||
uint size = value("Preferences/Downloads/DiskWriteCacheSize", 0).toUInt();
|
|
||||||
// These macros may not be available on compilers other than MSVC and GCC
|
|
||||||
#if defined(__x86_64__) || defined(_M_X64)
|
|
||||||
size = qMin(size, (uint) 4096); // 4GiB
|
|
||||||
#else
|
|
||||||
// When build as 32bit binary, set the maximum at less than 2GB to prevent crashes
|
|
||||||
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
|
|
||||||
size = qMin(size, (uint) 1536);
|
|
||||||
#endif
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setDiskCacheSize(uint size)
|
|
||||||
{
|
|
||||||
#if defined(__x86_64__) || defined(_M_X64)
|
|
||||||
size = qMin(size, (uint) 4096); // 4GiB
|
|
||||||
#else
|
|
||||||
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
|
|
||||||
size = qMin(size, (uint) 1536);
|
|
||||||
#endif
|
|
||||||
setValue("Preferences/Downloads/DiskWriteCacheSize", size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Preferences::diskCacheTTL() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Downloads/DiskWriteCacheTTL", 60).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setDiskCacheTTL(uint ttl)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Downloads/DiskWriteCacheTTL", ttl);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::osCache() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/osCache", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setOsCache(bool enable)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/osCache", enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Preferences::saveResumeDataInterval() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Downloads/SaveResumeDataInterval", 3).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setSaveResumeDataInterval(uint m)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Downloads/SaveResumeDataInterval", m);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Preferences::outgoingPortsMin() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/OutgoingPortsMin", 0).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setOutgoingPortsMin(uint val)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/OutgoingPortsMin", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Preferences::outgoingPortsMax() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/OutgoingPortsMax", 0).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setOutgoingPortsMax(uint val)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/OutgoingPortsMax", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::getIgnoreLimitsOnLAN() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/IgnoreLimitsLAN", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setIgnoreLimitsOnLAN(bool ignore)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/IgnoreLimitsLAN", ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::includeOverheadInLimits() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/IncludeOverhead", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::includeOverheadInLimits(bool include)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/IncludeOverhead", include);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::trackerExchangeEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/LtTrackerExchange", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setTrackerExchangeEnabled(bool enable)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/LtTrackerExchange", enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::recheckTorrentsOnCompletion() const
|
bool Preferences::recheckTorrentsOnCompletion() const
|
||||||
{
|
{
|
||||||
return value("Preferences/Advanced/RecheckOnCompletion", false).toBool();
|
return value("Preferences/Advanced/RecheckOnCompletion", false).toBool();
|
||||||
@@ -1279,16 +686,6 @@ void Preferences::recheckTorrentsOnCompletion(bool recheck)
|
|||||||
setValue("Preferences/Advanced/RecheckOnCompletion", recheck);
|
setValue("Preferences/Advanced/RecheckOnCompletion", recheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Preferences::getRefreshInterval() const
|
|
||||||
{
|
|
||||||
return value("Preferences/General/RefreshInterval", 1500).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setRefreshInterval(uint interval)
|
|
||||||
{
|
|
||||||
setValue("Preferences/General/RefreshInterval", interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::resolvePeerCountries() const
|
bool Preferences::resolvePeerCountries() const
|
||||||
{
|
{
|
||||||
return value("Preferences/Connection/ResolvePeerCountries", true).toBool();
|
return value("Preferences/Connection/ResolvePeerCountries", true).toBool();
|
||||||
@@ -1309,101 +706,6 @@ void Preferences::resolvePeerHostNames(bool resolve)
|
|||||||
setValue("Preferences/Connection/ResolvePeerHostNames", resolve);
|
setValue("Preferences/Connection/ResolvePeerHostNames", resolve);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Preferences::getMaxHalfOpenConnections() const
|
|
||||||
{
|
|
||||||
const int val = value("Preferences/Connection/MaxHalfOpenConnec", 20).toInt();
|
|
||||||
if (val <= 0)
|
|
||||||
return -1;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setMaxHalfOpenConnections(int value)
|
|
||||||
{
|
|
||||||
if (value <= 0)
|
|
||||||
value = -1;
|
|
||||||
setValue("Preferences/Connection/MaxHalfOpenConnec", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getNetworkInterface() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/Interface").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setNetworkInterface(const QString& iface)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/Interface", iface);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getNetworkInterfaceName() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/InterfaceName").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setNetworkInterfaceName(const QString& iface)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/InterfaceName", iface);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setNetworkInterfaceAddress(const QString& addr)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/InterfaceAddress", addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getNetworkInterfaceAddress() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/InterfaceAddress").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::getListenIPv6() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/InterfaceListenIPv6", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setListenIPv6(bool enable)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/InterfaceListenIPv6", enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Preferences::getNetworkAddress() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Connection/InetAddress").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setNetworkAddress(const QString& addr)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Connection/InetAddress", addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isAnonymousModeEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/AnonymousMode", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::enableAnonymousMode(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/AnonymousMode", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::isSuperSeedingEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/SuperSeeding", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::enableSuperSeeding(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/SuperSeeding", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Preferences::announceToAllTrackers() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/AnnounceToAllTrackers", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setAnnounceToAllTrackers(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/AnnounceToAllTrackers", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||||
bool Preferences::useSystemIconTheme() const
|
bool Preferences::useSystemIconTheme() const
|
||||||
{
|
{
|
||||||
@@ -1710,16 +1012,6 @@ void Preferences::setMagnetLinkAssoc()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Preferences::isTrackerEnabled() const
|
|
||||||
{
|
|
||||||
return value("Preferences/Advanced/trackerEnabled", false).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preferences::setTrackerEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
setValue("Preferences/Advanced/trackerEnabled", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Preferences::getTrackerPort() const
|
int Preferences::getTrackerPort() const
|
||||||
{
|
{
|
||||||
return value("Preferences/Advanced/trackerPort", 9000).toInt();
|
return value("Preferences/Advanced/trackerPort", 9000).toInt();
|
||||||
@@ -1997,7 +1289,7 @@ void Preferences::setRssOpenFolders(const QStringList &folders)
|
|||||||
setValue("Rss/open_folders", folders);
|
setValue("Rss/open_folders", folders);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Preferences::getRssHSplitterState() const
|
QByteArray Preferences::getRssSideSplitterState() const
|
||||||
{
|
{
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
return value("Rss/qt5/splitter_h").toByteArray();
|
return value("Rss/qt5/splitter_h").toByteArray();
|
||||||
@@ -2006,7 +1298,7 @@ QByteArray Preferences::getRssHSplitterState() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setRssHSplitterState(const QByteArray &state)
|
void Preferences::setRssSideSplitterState(const QByteArray &state)
|
||||||
{
|
{
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
setValue("Rss/qt5/splitter_h", state);
|
setValue("Rss/qt5/splitter_h", state);
|
||||||
@@ -2015,32 +1307,40 @@ void Preferences::setRssHSplitterState(const QByteArray &state)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Preferences::getRssVSplitterState() const
|
QByteArray Preferences::getRssMainSplitterState() const
|
||||||
{
|
{
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
return value("Rss/qt5/splitter_v").toByteArray();
|
return value("Rss/qt5/splitterMain").toByteArray();
|
||||||
#else
|
#else
|
||||||
return value("Rss/splitter_v").toByteArray();
|
return value("Rss/splitterMain").toByteArray();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setRssVSplitterState(const QByteArray &state)
|
void Preferences::setRssMainSplitterState(const QByteArray &state)
|
||||||
{
|
{
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
setValue("Rss/qt5/splitter_v", state);
|
setValue("Rss/qt5/splitterMain", state);
|
||||||
#else
|
#else
|
||||||
setValue("Rss/splitter_v", state);
|
setValue("Rss/splitterMain", state);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Preferences::getSearchColsWidth() const
|
QByteArray Preferences::getSearchTabHeaderState() const
|
||||||
{
|
{
|
||||||
return value("SearchResultsColsWidth").toString();
|
#ifdef QBT_USES_QT5
|
||||||
|
return value("SearchTab/qt5/HeaderState").toByteArray();
|
||||||
|
#else
|
||||||
|
return value("SearchTab/HeaderState").toByteArray();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setSearchColsWidth(const QString &width)
|
void Preferences::setSearchTabHeaderState(const QByteArray &state)
|
||||||
{
|
{
|
||||||
setValue("SearchResultsColsWidth", width);
|
#ifdef QBT_USES_QT5
|
||||||
|
setValue("SearchTab/qt5/HeaderState", state);
|
||||||
|
#else
|
||||||
|
setValue("SearchTab/HeaderState", state);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList Preferences::getSearchEngDisabled() const
|
QStringList Preferences::getSearchEngDisabled() const
|
||||||
|
|||||||
@@ -57,18 +57,6 @@ enum scheduler_days
|
|||||||
SUN
|
SUN
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Proxy
|
|
||||||
{
|
|
||||||
enum ProxyType
|
|
||||||
{
|
|
||||||
HTTP = 1,
|
|
||||||
SOCKS5 = 2,
|
|
||||||
HTTP_PW = 3,
|
|
||||||
SOCKS5_PW = 4,
|
|
||||||
SOCKS4 = 5
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace TrayIcon
|
namespace TrayIcon
|
||||||
{
|
{
|
||||||
enum Style
|
enum Style
|
||||||
@@ -102,7 +90,6 @@ class Preferences: public QObject
|
|||||||
void setValue(const QString &key, const QVariant &value);
|
void setValue(const QString &key, const QVariant &value);
|
||||||
|
|
||||||
static Preferences* m_instance;
|
static Preferences* m_instance;
|
||||||
int m_randomPort;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void changed();
|
void changed();
|
||||||
@@ -127,8 +114,6 @@ public:
|
|||||||
void setHideZeroValues(bool b);
|
void setHideZeroValues(bool b);
|
||||||
int getHideZeroComboValues() const;
|
int getHideZeroComboValues() const;
|
||||||
void setHideZeroComboValues(int n);
|
void setHideZeroComboValues(int n);
|
||||||
bool useRandomPort() const;
|
|
||||||
void setRandomPort(bool b);
|
|
||||||
bool systrayIntegration() const;
|
bool systrayIntegration() const;
|
||||||
void setSystrayIntegration(bool enabled);
|
void setSystrayIntegration(bool enabled);
|
||||||
bool isToolbarDisplayed() const;
|
bool isToolbarDisplayed() const;
|
||||||
@@ -149,22 +134,12 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Downloads
|
// Downloads
|
||||||
bool useIncompleteFilesExtension() const;
|
|
||||||
void useIncompleteFilesExtension(bool enabled);
|
|
||||||
QString lastLocationPath() const;
|
QString lastLocationPath() const;
|
||||||
void setLastLocationPath(const QString &path);
|
void setLastLocationPath(const QString &path);
|
||||||
bool preAllocateAllFiles() const;
|
|
||||||
void preAllocateAllFiles(bool enabled);
|
|
||||||
QVariantHash getScanDirs() const;
|
QVariantHash getScanDirs() const;
|
||||||
void setScanDirs(const QVariantHash &dirs);
|
void setScanDirs(const QVariantHash &dirs);
|
||||||
QString getScanDirsLastPath() const;
|
QString getScanDirsLastPath() const;
|
||||||
void setScanDirsLastPath(const QString &path);
|
void setScanDirsLastPath(const QString &path);
|
||||||
bool isTorrentExportEnabled() const;
|
|
||||||
QString getTorrentExportDir() const;
|
|
||||||
void setTorrentExportDir(QString path);
|
|
||||||
bool isFinishedTorrentExportEnabled() const;
|
|
||||||
QString getFinishedTorrentExportDir() const;
|
|
||||||
void setFinishedTorrentExportDir(QString path);
|
|
||||||
bool isMailNotificationEnabled() const;
|
bool isMailNotificationEnabled() const;
|
||||||
void setMailNotificationEnabled(bool enabled);
|
void setMailNotificationEnabled(bool enabled);
|
||||||
QString getMailNotificationEmail() const;
|
QString getMailNotificationEmail() const;
|
||||||
@@ -185,22 +160,6 @@ public:
|
|||||||
void setActionOnDblClOnTorrentFn(int act);
|
void setActionOnDblClOnTorrentFn(int act);
|
||||||
|
|
||||||
// Connection options
|
// Connection options
|
||||||
int getSessionPort() const;
|
|
||||||
void setSessionPort(int port);
|
|
||||||
bool isUPnPEnabled() const;
|
|
||||||
void setUPnPEnabled(bool enabled);
|
|
||||||
int getGlobalDownloadLimit() const;
|
|
||||||
void setGlobalDownloadLimit(int limit);
|
|
||||||
int getGlobalUploadLimit() const;
|
|
||||||
void setGlobalUploadLimit(int limit);
|
|
||||||
int getAltGlobalDownloadLimit() const;
|
|
||||||
void setAltGlobalDownloadLimit(int limit);
|
|
||||||
int getAltGlobalUploadLimit() const;
|
|
||||||
void setAltGlobalUploadLimit(int limit);
|
|
||||||
bool isAltBandwidthEnabled() const;
|
|
||||||
void setAltBandwidthEnabled(bool enabled);
|
|
||||||
bool isSchedulerEnabled() const;
|
|
||||||
void setSchedulerEnabled(bool enabled);
|
|
||||||
QTime getSchedulerStartTime() const;
|
QTime getSchedulerStartTime() const;
|
||||||
void setSchedulerStartTime(const QTime &time);
|
void setSchedulerStartTime(const QTime &time);
|
||||||
QTime getSchedulerEndTime() const;
|
QTime getSchedulerEndTime() const;
|
||||||
@@ -208,80 +167,10 @@ public:
|
|||||||
scheduler_days getSchedulerDays() const;
|
scheduler_days getSchedulerDays() const;
|
||||||
void setSchedulerDays(scheduler_days days);
|
void setSchedulerDays(scheduler_days days);
|
||||||
|
|
||||||
// Proxy options
|
|
||||||
bool isProxyEnabled() const;
|
|
||||||
bool isProxyAuthEnabled() const;
|
|
||||||
void setProxyAuthEnabled(bool enabled);
|
|
||||||
QString getProxyIp() const;
|
|
||||||
void setProxyIp(const QString &ip);
|
|
||||||
unsigned short getProxyPort() const;
|
|
||||||
void setProxyPort(unsigned short port);
|
|
||||||
QString getProxyUsername() const;
|
|
||||||
void setProxyUsername(const QString &username);
|
|
||||||
QString getProxyPassword() const;
|
|
||||||
void setProxyPassword(const QString &password);
|
|
||||||
int getProxyType() const;
|
|
||||||
void setProxyType(int type);
|
|
||||||
bool proxyPeerConnections() const;
|
|
||||||
void setProxyPeerConnections(bool enabled);
|
|
||||||
bool getForceProxy() const;
|
|
||||||
void setForceProxy(bool enabled);
|
|
||||||
void setProxyOnlyForTorrents(bool enabled);
|
|
||||||
bool isProxyOnlyForTorrents() const;
|
|
||||||
|
|
||||||
// Bittorrent options
|
|
||||||
int getMaxConnecs() const;
|
|
||||||
void setMaxConnecs(int val);
|
|
||||||
int getMaxConnecsPerTorrent() const;
|
|
||||||
void setMaxConnecsPerTorrent(int val);
|
|
||||||
int getMaxUploads() const;
|
|
||||||
void setMaxUploads(int val);
|
|
||||||
int getMaxUploadsPerTorrent() const;
|
|
||||||
void setMaxUploadsPerTorrent(int val);
|
|
||||||
bool isuTPEnabled() const;
|
|
||||||
void setuTPEnabled(bool enabled);
|
|
||||||
bool isuTPRateLimited() const;
|
|
||||||
void setuTPRateLimited(bool enabled);
|
|
||||||
bool isDHTEnabled() const;
|
|
||||||
void setDHTEnabled(bool enabled);
|
|
||||||
bool isPeXEnabled() const;
|
|
||||||
void setPeXEnabled(bool enabled);
|
|
||||||
bool isLSDEnabled() const;
|
|
||||||
void setLSDEnabled(bool enabled);
|
|
||||||
int getEncryptionSetting() const;
|
|
||||||
void setEncryptionSetting(int val);
|
|
||||||
bool isAddTrackersEnabled() const;
|
|
||||||
void setAddTrackersEnabled(bool enabled);
|
|
||||||
QString getTrackersList() const;
|
|
||||||
void setTrackersList(const QString &val);
|
|
||||||
qreal getGlobalMaxRatio() const;
|
|
||||||
void setGlobalMaxRatio(qreal ratio);
|
|
||||||
|
|
||||||
// IP Filter
|
|
||||||
bool isFilteringEnabled() const;
|
|
||||||
void setFilteringEnabled(bool enabled);
|
|
||||||
bool isFilteringTrackerEnabled() const;
|
|
||||||
void setFilteringTrackerEnabled(bool enabled);
|
|
||||||
QString getFilter() const;
|
|
||||||
void setFilter(const QString &path);
|
|
||||||
QStringList bannedIPs() const;
|
|
||||||
void banIP(const QString &ip);
|
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
bool isSearchEnabled() const;
|
bool isSearchEnabled() const;
|
||||||
void setSearchEnabled(bool enabled);
|
void setSearchEnabled(bool enabled);
|
||||||
|
|
||||||
// Queueing system
|
|
||||||
bool isQueueingSystemEnabled() const;
|
|
||||||
void setQueueingSystemEnabled(bool enabled);
|
|
||||||
int getMaxActiveDownloads() const;
|
|
||||||
void setMaxActiveDownloads(int val);
|
|
||||||
int getMaxActiveUploads() const;
|
|
||||||
void setMaxActiveUploads(int val);
|
|
||||||
int getMaxActiveTorrents() const;
|
|
||||||
void setMaxActiveTorrents(int val);
|
|
||||||
bool ignoreSlowTorrentsForQueueing() const;
|
|
||||||
void setIgnoreSlowTorrentsForQueueing(bool ignore);
|
|
||||||
bool isWebUiEnabled() const;
|
bool isWebUiEnabled() const;
|
||||||
void setWebUiEnabled(bool enabled);
|
void setWebUiEnabled(bool enabled);
|
||||||
bool isWebUiLocalAuthEnabled() const;
|
bool isWebUiLocalAuthEnabled() const;
|
||||||
@@ -331,50 +220,12 @@ public:
|
|||||||
void setShutdownqBTWhenDownloadsComplete(bool shutdown);
|
void setShutdownqBTWhenDownloadsComplete(bool shutdown);
|
||||||
bool dontConfirmAutoExit() const;
|
bool dontConfirmAutoExit() const;
|
||||||
void setDontConfirmAutoExit(bool dontConfirmAutoExit);
|
void setDontConfirmAutoExit(bool dontConfirmAutoExit);
|
||||||
uint diskCacheSize() const;
|
|
||||||
void setDiskCacheSize(uint size);
|
|
||||||
uint diskCacheTTL() const;
|
|
||||||
void setDiskCacheTTL(uint ttl);
|
|
||||||
bool osCache() const;
|
|
||||||
void setOsCache(bool enable);
|
|
||||||
uint saveResumeDataInterval() const;
|
|
||||||
void setSaveResumeDataInterval(uint m);
|
|
||||||
uint outgoingPortsMin() const;
|
|
||||||
void setOutgoingPortsMin(uint val);
|
|
||||||
uint outgoingPortsMax() const;
|
|
||||||
void setOutgoingPortsMax(uint val);
|
|
||||||
bool getIgnoreLimitsOnLAN() const;
|
|
||||||
void setIgnoreLimitsOnLAN(bool ignore);
|
|
||||||
bool includeOverheadInLimits() const;
|
|
||||||
void includeOverheadInLimits(bool include);
|
|
||||||
bool trackerExchangeEnabled() const;
|
|
||||||
void setTrackerExchangeEnabled(bool enable);
|
|
||||||
bool recheckTorrentsOnCompletion() const;
|
bool recheckTorrentsOnCompletion() const;
|
||||||
void recheckTorrentsOnCompletion(bool recheck);
|
void recheckTorrentsOnCompletion(bool recheck);
|
||||||
unsigned int getRefreshInterval() const;
|
|
||||||
void setRefreshInterval(uint interval);
|
|
||||||
bool resolvePeerCountries() const;
|
bool resolvePeerCountries() const;
|
||||||
void resolvePeerCountries(bool resolve);
|
void resolvePeerCountries(bool resolve);
|
||||||
bool resolvePeerHostNames() const;
|
bool resolvePeerHostNames() const;
|
||||||
void resolvePeerHostNames(bool resolve);
|
void resolvePeerHostNames(bool resolve);
|
||||||
int getMaxHalfOpenConnections() const;
|
|
||||||
void setMaxHalfOpenConnections(int value);
|
|
||||||
QString getNetworkInterface() const;
|
|
||||||
void setNetworkInterface(const QString& iface);
|
|
||||||
QString getNetworkInterfaceName() const;
|
|
||||||
void setNetworkInterfaceName(const QString& iface);
|
|
||||||
QString getNetworkInterfaceAddress() const;
|
|
||||||
void setNetworkInterfaceAddress(const QString& addr);
|
|
||||||
bool getListenIPv6() const;
|
|
||||||
void setListenIPv6(bool enable);
|
|
||||||
QString getNetworkAddress() const;
|
|
||||||
void setNetworkAddress(const QString& addr);
|
|
||||||
bool isAnonymousModeEnabled() const;
|
|
||||||
void enableAnonymousMode(bool enabled);
|
|
||||||
bool isSuperSeedingEnabled() const;
|
|
||||||
void enableSuperSeeding(bool enabled);
|
|
||||||
bool announceToAllTrackers() const;
|
|
||||||
void setAnnounceToAllTrackers(bool enabled);
|
|
||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||||
bool useSystemIconTheme() const;
|
bool useSystemIconTheme() const;
|
||||||
void useSystemIconTheme(bool enabled);
|
void useSystemIconTheme(bool enabled);
|
||||||
@@ -396,8 +247,6 @@ public:
|
|||||||
static void setTorrentFileAssoc();
|
static void setTorrentFileAssoc();
|
||||||
static void setMagnetLinkAssoc();
|
static void setMagnetLinkAssoc();
|
||||||
#endif
|
#endif
|
||||||
bool isTrackerEnabled() const;
|
|
||||||
void setTrackerEnabled(bool enabled);
|
|
||||||
int getTrackerPort() const;
|
int getTrackerPort() const;
|
||||||
void setTrackerPort(int port);
|
void setTrackerPort(int port);
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
@@ -451,12 +300,12 @@ public:
|
|||||||
void setRssHSplitterSizes(const QByteArray &sizes);
|
void setRssHSplitterSizes(const QByteArray &sizes);
|
||||||
QStringList getRssOpenFolders() const;
|
QStringList getRssOpenFolders() const;
|
||||||
void setRssOpenFolders(const QStringList &folders);
|
void setRssOpenFolders(const QStringList &folders);
|
||||||
QByteArray getRssHSplitterState() const;
|
QByteArray getRssSideSplitterState() const;
|
||||||
void setRssHSplitterState(const QByteArray &state);
|
void setRssSideSplitterState(const QByteArray &state);
|
||||||
QByteArray getRssVSplitterState() const;
|
QByteArray getRssMainSplitterState() const;
|
||||||
void setRssVSplitterState(const QByteArray &state);
|
void setRssMainSplitterState(const QByteArray &state);
|
||||||
QString getSearchColsWidth() const;
|
QByteArray getSearchTabHeaderState() const;
|
||||||
void setSearchColsWidth(const QString &width);
|
void setSearchTabHeaderState(const QByteArray &state);
|
||||||
QStringList getSearchEngDisabled() const;
|
QStringList getSearchEngDisabled() const;
|
||||||
void setSearchEngDisabled(const QStringList &engines);
|
void setSearchEngDisabled(const QStringList &engines);
|
||||||
QString getCreateTorLastAddPath() const;
|
QString getCreateTorLastAddPath() const;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class QIniSettings : public QSettings {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QIniSettings(const QString &organization = "qBittorrent", const QString &application = "qBittorrent", QObject *parent = 0 ):
|
QIniSettings(const QString &organization = "qBittorrent", const QString &application = "qBittorrent", QObject *parent = 0 ):
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
QSettings(QSettings::IniFormat, QSettings::UserScope, organization, application, parent)
|
QSettings(QSettings::IniFormat, QSettings::UserScope, organization, application, parent)
|
||||||
#else
|
#else
|
||||||
QSettings(organization, application, parent)
|
QSettings(organization, application, parent)
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
@@ -48,55 +50,124 @@ DownloadRule::DownloadRule()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DownloadRule::matches(const QString &articleTitle, const QString &expression) const
|
||||||
|
{
|
||||||
|
static QRegExp whitespace("\\s+");
|
||||||
|
|
||||||
|
if (expression.isEmpty()) {
|
||||||
|
// A regex of the form "expr|" will always match, so do the same for wildcards
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (m_useRegex) {
|
||||||
|
QRegExp reg(expression, Qt::CaseInsensitive, QRegExp::RegExp);
|
||||||
|
return reg.indexIn(articleTitle) > -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Only match if every wildcard token (separated by spaces) is present in the article name.
|
||||||
|
// Order of wildcard tokens is unimportant (if order is important, they should have used *).
|
||||||
|
foreach (const QString &wildcard, expression.split(whitespace, QString::SplitBehavior::SkipEmptyParts)) {
|
||||||
|
QRegExp reg(wildcard, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||||
|
|
||||||
|
if (reg.indexIn(articleTitle) == -1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool DownloadRule::matches(const QString &articleTitle) const
|
bool DownloadRule::matches(const QString &articleTitle) const
|
||||||
{
|
{
|
||||||
foreach (const QString &token, m_mustContain) {
|
if (!m_mustContain.empty()) {
|
||||||
if (!token.isEmpty()) {
|
bool logged = false;
|
||||||
QRegExp reg(token, Qt::CaseInsensitive, m_useRegex ? QRegExp::RegExp : QRegExp::Wildcard);
|
bool foundMustContain = false;
|
||||||
if (reg.indexIn(articleTitle) < 0)
|
|
||||||
|
// Each expression is either a regex, or a set of wildcards separated by whitespace.
|
||||||
|
// Accept if any complete expression matches.
|
||||||
|
foreach (const QString &expression, m_mustContain) {
|
||||||
|
if (!logged) {
|
||||||
|
qDebug() << "Checking matching" << (m_useRegex ? "regex:" : "wildcard expressions:") << m_mustContain.join("|");
|
||||||
|
logged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A regex of the form "expr|" will always match, so do the same for wildcards
|
||||||
|
foundMustContain = matches(articleTitle, expression);
|
||||||
|
|
||||||
|
if (foundMustContain) {
|
||||||
|
qDebug() << "Found matching" << (m_useRegex ? "regex:" : "wildcard expression:") << expression;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundMustContain)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_mustNotContain.empty()) {
|
||||||
|
bool logged = false;
|
||||||
|
|
||||||
|
// Each expression is either a regex, or a set of wildcards separated by whitespace.
|
||||||
|
// Reject if any complete expression matches.
|
||||||
|
foreach (const QString &expression, m_mustNotContain) {
|
||||||
|
if (!logged) {
|
||||||
|
qDebug() << "Checking not matching" << (m_useRegex ? "regex:" : "wildcard expressions:") << m_mustNotContain.join("|");
|
||||||
|
logged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A regex of the form "expr|" will always match, so do the same for wildcards
|
||||||
|
if (matches(articleTitle, expression)) {
|
||||||
|
qDebug() << "Found not matching" << (m_useRegex ? "regex:" : "wildcard expression:") << expression;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug("Checking not matching tokens");
|
|
||||||
// Checking not matching
|
|
||||||
foreach (const QString &token, m_mustNotContain) {
|
|
||||||
if (!token.isEmpty()) {
|
|
||||||
QRegExp reg(token, Qt::CaseInsensitive, m_useRegex ? QRegExp::RegExp : QRegExp::Wildcard);
|
|
||||||
if (reg.indexIn(articleTitle) > -1)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_episodeFilter.isEmpty()) {
|
if (!m_episodeFilter.isEmpty()) {
|
||||||
qDebug("Checking episode filter");
|
qDebug() << "Checking episode filter:" << m_episodeFilter;
|
||||||
QRegExp f("(^\\d{1,4})x(.*;$)");
|
QRegExp f("(^\\d{1,4})x(.*;$)");
|
||||||
int pos = f.indexIn(m_episodeFilter);
|
int pos = f.indexIn(m_episodeFilter);
|
||||||
|
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QString s = f.cap(1);
|
QString s = f.cap(1);
|
||||||
QStringList eps = f.cap(2).split(";");
|
QStringList eps = f.cap(2).split(";");
|
||||||
QString expStr;
|
int sOurs = s.toInt();
|
||||||
expStr += "s0?" + s + "[ -_\\.]?" + "e0?";
|
|
||||||
|
|
||||||
foreach (const QString &ep, eps) {
|
foreach (QString ep, eps) {
|
||||||
if (ep.isEmpty())
|
if (ep.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// We need to trim leading zeroes, but if it's all zeros then we want episode zero.
|
||||||
|
while (ep.size() > 1 && ep.startsWith("0"))
|
||||||
|
ep = ep.right(ep.size() - 1);
|
||||||
|
|
||||||
if (ep.indexOf('-') != -1) { // Range detected
|
if (ep.indexOf('-') != -1) { // Range detected
|
||||||
QString partialPattern = "s0?" + s + "[ -_\\.]?" + "e(0?\\d{1,4})";
|
QString partialPattern1 = "\\bs0?(\\d{1,4})[ -_\\.]?e(0?\\d{1,4})(?:\\D|\\b)";
|
||||||
QRegExp reg(partialPattern, Qt::CaseInsensitive);
|
QString partialPattern2 = "\\b(\\d{1,4})x(0?\\d{1,4})(?:\\D|\\b)";
|
||||||
|
QRegExp reg(partialPattern1, Qt::CaseInsensitive);
|
||||||
|
|
||||||
if (ep.endsWith('-')) { // Infinite range
|
if (ep.endsWith('-')) { // Infinite range
|
||||||
int epOurs = ep.left(ep.size() - 1).toInt();
|
int epOurs = ep.left(ep.size() - 1).toInt();
|
||||||
|
|
||||||
// Extract partial match from article and compare as digits
|
// Extract partial match from article and compare as digits
|
||||||
pos = reg.indexIn(articleTitle);
|
pos = reg.indexIn(articleTitle);
|
||||||
|
|
||||||
|
if (pos == -1) {
|
||||||
|
reg = QRegExp(partialPattern2, Qt::CaseInsensitive);
|
||||||
|
pos = reg.indexIn(articleTitle);
|
||||||
|
}
|
||||||
|
|
||||||
if (pos != -1) {
|
if (pos != -1) {
|
||||||
int epTheirs = reg.cap(1).toInt();
|
int sTheirs = reg.cap(1).toInt();
|
||||||
if (epTheirs >= epOurs)
|
int epTheirs = reg.cap(2).toInt();
|
||||||
|
if (((sTheirs == sOurs) && (epTheirs >= epOurs)) || (sTheirs > sOurs)) {
|
||||||
|
qDebug() << "Matched episode:" << ep;
|
||||||
|
qDebug() << "Matched article:" << articleTitle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else { // Normal range
|
else { // Normal range
|
||||||
QStringList range = ep.split('-');
|
QStringList range = ep.split('-');
|
||||||
Q_ASSERT(range.size() == 2);
|
Q_ASSERT(range.size() == 2);
|
||||||
@@ -108,21 +179,38 @@ bool DownloadRule::matches(const QString &articleTitle) const
|
|||||||
|
|
||||||
// Extract partial match from article and compare as digits
|
// Extract partial match from article and compare as digits
|
||||||
pos = reg.indexIn(articleTitle);
|
pos = reg.indexIn(articleTitle);
|
||||||
|
|
||||||
|
if (pos == -1) {
|
||||||
|
reg = QRegExp(partialPattern2, Qt::CaseInsensitive);
|
||||||
|
pos = reg.indexIn(articleTitle);
|
||||||
|
}
|
||||||
|
|
||||||
if (pos != -1) {
|
if (pos != -1) {
|
||||||
int epTheirs = reg.cap(1).toInt();
|
int sTheirs = reg.cap(1).toInt();
|
||||||
if (epOursFirst <= epTheirs && epOursLast >= epTheirs)
|
int epTheirs = reg.cap(2).toInt();
|
||||||
|
if ((sTheirs == sOurs) && ((epOursFirst <= epTheirs) && (epOursLast >= epTheirs))) {
|
||||||
|
qDebug() << "Matched episode:" << ep;
|
||||||
|
qDebug() << "Matched article:" << articleTitle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else { // Single number
|
else { // Single number
|
||||||
QRegExp reg(expStr + ep + "\\D", Qt::CaseInsensitive);
|
QString expStr("\\b(?:s0?" + s + "[ -_\\.]?" + "e0?" + ep + "|" + s + "x" + "0?" + ep + ")(?:\\D|\\b)");
|
||||||
if (reg.indexIn(articleTitle) != -1)
|
QRegExp reg(expStr, Qt::CaseInsensitive);
|
||||||
|
if (reg.indexIn(articleTitle) != -1) {
|
||||||
|
qDebug() << "Matched episode:" << ep;
|
||||||
|
qDebug() << "Matched article:" << articleTitle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << "Matched article:" << articleTitle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +219,11 @@ void DownloadRule::setMustContain(const QString &tokens)
|
|||||||
if (m_useRegex)
|
if (m_useRegex)
|
||||||
m_mustContain = QStringList() << tokens;
|
m_mustContain = QStringList() << tokens;
|
||||||
else
|
else
|
||||||
m_mustContain = tokens.split(" ");
|
m_mustContain = tokens.split("|");
|
||||||
|
|
||||||
|
// Check for single empty string - if so, no condition
|
||||||
|
if ((m_mustContain.size() == 1) && m_mustContain[0].isEmpty())
|
||||||
|
m_mustContain.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadRule::setMustNotContain(const QString &tokens)
|
void DownloadRule::setMustNotContain(const QString &tokens)
|
||||||
@@ -140,6 +232,10 @@ void DownloadRule::setMustNotContain(const QString &tokens)
|
|||||||
m_mustNotContain = QStringList() << tokens;
|
m_mustNotContain = QStringList() << tokens;
|
||||||
else
|
else
|
||||||
m_mustNotContain = tokens.split("|");
|
m_mustNotContain = tokens.split("|");
|
||||||
|
|
||||||
|
// Check for single empty string - if so, no condition
|
||||||
|
if ((m_mustNotContain.size() == 1) && m_mustNotContain[0].isEmpty())
|
||||||
|
m_mustNotContain.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList DownloadRule::rssFeeds() const
|
QStringList DownloadRule::rssFeeds() const
|
||||||
@@ -189,7 +285,7 @@ QVariantHash DownloadRule::toVariantHash() const
|
|||||||
{
|
{
|
||||||
QVariantHash hash;
|
QVariantHash hash;
|
||||||
hash["name"] = m_name;
|
hash["name"] = m_name;
|
||||||
hash["must_contain"] = m_mustContain.join(" ");
|
hash["must_contain"] = m_mustContain.join("|");
|
||||||
hash["must_not_contain"] = m_mustNotContain.join("|");
|
hash["must_not_contain"] = m_mustNotContain.join("|");
|
||||||
hash["save_path"] = m_savePath;
|
hash["save_path"] = m_savePath;
|
||||||
hash["affected_feeds"] = m_rssFeeds;
|
hash["affected_feeds"] = m_rssFeeds;
|
||||||
@@ -265,7 +361,7 @@ int DownloadRule::ignoreDays() const
|
|||||||
|
|
||||||
QString DownloadRule::mustContain() const
|
QString DownloadRule::mustContain() const
|
||||||
{
|
{
|
||||||
return m_mustContain.join(" ");
|
return m_mustContain.join("|");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DownloadRule::mustNotContain() const
|
QString DownloadRule::mustNotContain() const
|
||||||
@@ -302,6 +398,7 @@ QStringList DownloadRule::findMatchingArticles(const FeedPtr &feed) const
|
|||||||
ArticleHash::ConstIterator artItend = feedArticles.end();
|
ArticleHash::ConstIterator artItend = feedArticles.end();
|
||||||
for (; artIt != artItend; ++artIt) {
|
for (; artIt != artItend; ++artIt) {
|
||||||
const QString title = artIt.value()->title();
|
const QString title = artIt.value()->title();
|
||||||
|
qDebug() << "Matching article:" << title;
|
||||||
if (matches(title))
|
if (matches(title))
|
||||||
ret << title;
|
ret << title;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ namespace Rss
|
|||||||
bool operator==(const DownloadRule &other) const;
|
bool operator==(const DownloadRule &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool matches(const QString &articleTitle, const QString &expression) const;
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QStringList m_mustContain;
|
QStringList m_mustContain;
|
||||||
QStringList m_mustNotContain;
|
QStringList m_mustNotContain;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ DownloadRuleList::DownloadRuleList()
|
|||||||
DownloadRulePtr DownloadRuleList::findMatchingRule(const QString &feedUrl, const QString &articleTitle) const
|
DownloadRulePtr DownloadRuleList::findMatchingRule(const QString &feedUrl, const QString &articleTitle) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
|
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
|
||||||
|
qDebug() << "Matching article:" << articleTitle;
|
||||||
QStringList ruleNames = m_feedRules.value(feedUrl);
|
QStringList ruleNames = m_feedRules.value(feedUrl);
|
||||||
foreach (const QString &rule_name, ruleNames) {
|
foreach (const QString &rule_name, ruleNames) {
|
||||||
DownloadRulePtr rule = m_rules[rule_name];
|
DownloadRulePtr rule = m_rules[rule_name];
|
||||||
|
|||||||
@@ -99,24 +99,24 @@ void Feed::saveItemsToDisk()
|
|||||||
|
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
|
|
||||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
QIniSettings qBTRSSFeeds("qBittorrent", "qBittorrent-rss-feeds");
|
||||||
QVariantList oldItems;
|
QVariantList oldItems;
|
||||||
|
|
||||||
ArticleHash::ConstIterator it = m_articles.begin();
|
ArticleHash::ConstIterator it = m_articles.begin();
|
||||||
ArticleHash::ConstIterator itend = m_articles.end();
|
ArticleHash::ConstIterator itend = m_articles.end();
|
||||||
for ( ; it != itend; ++it) {
|
for (; it != itend; ++it)
|
||||||
oldItems << it.value()->toHash();
|
oldItems << it.value()->toHash();
|
||||||
}
|
|
||||||
qDebug("Saving %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
qDebug("Saving %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
||||||
QHash<QString, QVariant> allOldItems = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> allOldItems = qBTRSSFeeds.value("old_items", QHash<QString, QVariant>()).toHash();
|
||||||
allOldItems[m_url] = oldItems;
|
allOldItems[m_url] = oldItems;
|
||||||
qBTRSS.setValue("old_items", allOldItems);
|
qBTRSSFeeds.setValue("old_items", allOldItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Feed::loadItemsFromDisk()
|
void Feed::loadItemsFromDisk()
|
||||||
{
|
{
|
||||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
QIniSettings qBTRSSFeeds("qBittorrent", "qBittorrent-rss-feeds");
|
||||||
QHash<QString, QVariant> allOldItems = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> allOldItems = qBTRSSFeeds.value("old_items", QHash<QString, QVariant>()).toHash();
|
||||||
|
|
||||||
const QVariantList oldItems = allOldItems.value(m_url, QVariantList()).toList();
|
const QVariantList oldItems = allOldItems.value(m_url, QVariantList()).toList();
|
||||||
qDebug("Loading %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
qDebug("Loading %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
||||||
|
|
||||||
@@ -155,23 +155,21 @@ void Feed::addArticle(const ArticlePtr &article)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if article was inserted at the end of the list and will break max_articles limit
|
// Check if article was inserted at the end of the list and will break max_articles limit
|
||||||
if (Preferences::instance()->isRssDownloadingEnabled()) {
|
if (Preferences::instance()->isRssDownloadingEnabled())
|
||||||
if ((lbIndex < maxArticles) && !article->isRead())
|
if ((lbIndex < maxArticles) && !article->isRead())
|
||||||
downloadArticleTorrentIfMatching(article);
|
downloadArticleTorrentIfMatching(article);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
// m_articles.contains(article->guid())
|
// m_articles.contains(article->guid())
|
||||||
// Try to download skipped articles
|
// Try to download skipped articles
|
||||||
if (Preferences::instance()->isRssDownloadingEnabled()) {
|
if (Preferences::instance()->isRssDownloadingEnabled()) {
|
||||||
ArticlePtr skipped = m_articles.value(article->guid(), ArticlePtr());
|
ArticlePtr skipped = m_articles.value(article->guid(), ArticlePtr());
|
||||||
if (skipped) {
|
if (skipped)
|
||||||
if (!skipped->isRead())
|
if (!skipped->isRead())
|
||||||
downloadArticleTorrentIfMatching(skipped);
|
downloadArticleTorrentIfMatching(skipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool Feed::refresh()
|
bool Feed::refresh()
|
||||||
{
|
{
|
||||||
@@ -206,10 +204,11 @@ void Feed::removeAllSettings()
|
|||||||
allFeedsFilters.remove(m_url);
|
allFeedsFilters.remove(m_url);
|
||||||
qBTRSS.setValue("feed_filters", allFeedsFilters);
|
qBTRSS.setValue("feed_filters", allFeedsFilters);
|
||||||
}
|
}
|
||||||
QVariantHash allOldItems = qBTRSS.value("old_items", QVariantHash()).toHash();
|
QIniSettings qBTRSSFeeds("qBittorrent", "qBittorrent-rss-feeds");
|
||||||
|
QVariantHash allOldItems = qBTRSSFeeds.value("old_items", QVariantHash()).toHash();
|
||||||
if (allOldItems.contains(m_url)) {
|
if (allOldItems.contains(m_url)) {
|
||||||
allOldItems.remove(m_url);
|
allOldItems.remove(m_url);
|
||||||
qBTRSS.setValue("old_items", allOldItems);
|
qBTRSSFeeds.setValue("old_items", allOldItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,8 +258,13 @@ bool Feed::hasCustomIcon() const
|
|||||||
|
|
||||||
void Feed::setIconPath(const QString &path)
|
void Feed::setIconPath(const QString &path)
|
||||||
{
|
{
|
||||||
if (!path.isEmpty() && QFile::exists(path))
|
QString nativePath = Utils::Fs::fromNativePath(path);
|
||||||
m_icon = path;
|
if ((nativePath == m_icon) || nativePath.isEmpty() || !QFile::exists(nativePath)) return;
|
||||||
|
|
||||||
|
if (!m_icon.startsWith(":/") && QFile::exists(m_icon))
|
||||||
|
Utils::Fs::forceRemove(m_icon);
|
||||||
|
|
||||||
|
m_icon = nativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArticlePtr Feed::getItem(const QString &guid) const
|
ArticlePtr Feed::getItem(const QString &guid) const
|
||||||
@@ -277,9 +281,8 @@ void Feed::markAsRead()
|
|||||||
{
|
{
|
||||||
ArticleHash::ConstIterator it = m_articles.begin();
|
ArticleHash::ConstIterator it = m_articles.begin();
|
||||||
ArticleHash::ConstIterator itend = m_articles.end();
|
ArticleHash::ConstIterator itend = m_articles.end();
|
||||||
for ( ; it != itend; ++it) {
|
for (; it != itend; ++it)
|
||||||
it.value()->markAsRead();
|
it.value()->markAsRead();
|
||||||
}
|
|
||||||
m_unreadCount = 0;
|
m_unreadCount = 0;
|
||||||
m_manager->forwardFeedInfosChanged(m_url, displayName(), 0);
|
m_manager->forwardFeedInfosChanged(m_url, displayName(), 0);
|
||||||
}
|
}
|
||||||
@@ -305,10 +308,9 @@ ArticleList Feed::unreadArticleListByDateDesc() const
|
|||||||
|
|
||||||
ArticleList::ConstIterator it = m_articlesByDate.begin();
|
ArticleList::ConstIterator it = m_articlesByDate.begin();
|
||||||
ArticleList::ConstIterator itend = m_articlesByDate.end();
|
ArticleList::ConstIterator itend = m_articlesByDate.end();
|
||||||
for ( ; it != itend; ++it) {
|
for (; it != itend; ++it)
|
||||||
if (!(*it)->isRead())
|
if (!(*it)->isRead())
|
||||||
unreadNews << *it;
|
unreadNews << *it;
|
||||||
}
|
|
||||||
return unreadNews;
|
return unreadNews;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +324,7 @@ QString Feed::iconUrl() const
|
|||||||
void Feed::handleIconDownloadFinished(const QString &url, const QString &filePath)
|
void Feed::handleIconDownloadFinished(const QString &url, const QString &filePath)
|
||||||
{
|
{
|
||||||
Q_UNUSED(url);
|
Q_UNUSED(url);
|
||||||
m_icon = filePath;
|
setIconPath(filePath);
|
||||||
qDebug() << Q_FUNC_INFO << "icon path:" << m_icon;
|
qDebug() << Q_FUNC_INFO << "icon path:" << m_icon;
|
||||||
m_manager->forwardFeedIconChanged(m_url, m_icon);
|
m_manager->forwardFeedIconChanged(m_url, m_icon);
|
||||||
}
|
}
|
||||||
@@ -359,6 +361,14 @@ void Feed::handleFeedTitle(const QString &title)
|
|||||||
void Feed::downloadArticleTorrentIfMatching(const ArticlePtr &article)
|
void Feed::downloadArticleTorrentIfMatching(const ArticlePtr &article)
|
||||||
{
|
{
|
||||||
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
|
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
|
||||||
|
qDebug().nospace() << Q_FUNC_INFO << " Deferring matching of " << article->title() << " from " << displayName() << " RSS feed";
|
||||||
|
m_manager->downloadArticleTorrentIfMatching(m_url, article);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Feed::deferredDownloadArticleTorrentIfMatching(const ArticlePtr &article)
|
||||||
|
{
|
||||||
|
qDebug().nospace() << Q_FUNC_INFO << " Matching of " << article->title() << " from " << displayName() << " RSS feed";
|
||||||
|
|
||||||
DownloadRuleList *rules = m_manager->downloadRules();
|
DownloadRuleList *rules = m_manager->downloadRules();
|
||||||
DownloadRulePtr matchingRule = rules->findMatchingRule(m_url, article->title());
|
DownloadRulePtr matchingRule = rules->findMatchingRule(m_url, article->title());
|
||||||
if (!matchingRule) return;
|
if (!matchingRule) return;
|
||||||
@@ -402,11 +412,10 @@ void Feed::downloadArticleTorrentIfMatching(const ArticlePtr &article)
|
|||||||
void Feed::recheckRssItemsForDownload()
|
void Feed::recheckRssItemsForDownload()
|
||||||
{
|
{
|
||||||
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
|
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
|
||||||
foreach (const ArticlePtr &article, m_articlesByDate) {
|
foreach (const ArticlePtr &article, m_articlesByDate)
|
||||||
if (!article->isRead())
|
if (!article->isRead())
|
||||||
downloadArticleTorrentIfMatching(article);
|
downloadArticleTorrentIfMatching(article);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Feed::handleNewArticle(const QVariantHash &articleData)
|
void Feed::handleNewArticle(const QVariantHash &articleData)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -98,10 +98,13 @@ namespace Rss
|
|||||||
void handleArticleRead();
|
void handleArticleRead();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class Manager;
|
||||||
|
|
||||||
QString iconUrl() const;
|
QString iconUrl() const;
|
||||||
void loadItemsFromDisk();
|
void loadItemsFromDisk();
|
||||||
void addArticle(const ArticlePtr &article);
|
void addArticle(const ArticlePtr &article);
|
||||||
void downloadArticleTorrentIfMatching(const ArticlePtr &article);
|
void downloadArticleTorrentIfMatching(const ArticlePtr &article);
|
||||||
|
void deferredDownloadArticleTorrentIfMatching(const ArticlePtr &article);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Manager *m_manager;
|
Manager *m_manager;
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ Manager::Manager(QObject *parent)
|
|||||||
connect(&m_refreshTimer, SIGNAL(timeout()), SLOT(refresh()));
|
connect(&m_refreshTimer, SIGNAL(timeout()), SLOT(refresh()));
|
||||||
m_refreshInterval = Preferences::instance()->getRSSRefreshInterval();
|
m_refreshInterval = Preferences::instance()->getRSSRefreshInterval();
|
||||||
m_refreshTimer.start(m_refreshInterval * MSECS_PER_MIN);
|
m_refreshTimer.start(m_refreshInterval * MSECS_PER_MIN);
|
||||||
|
|
||||||
|
m_deferredDownloadTimer.setInterval(1);
|
||||||
|
m_deferredDownloadTimer.setSingleShot(true);
|
||||||
|
connect(&m_deferredDownloadTimer, SIGNAL(timeout()), SLOT(downloadNextArticleTorrentIfMatching()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager()
|
Manager::~Manager()
|
||||||
@@ -188,3 +192,27 @@ void Manager::refresh()
|
|||||||
{
|
{
|
||||||
m_rootFolder->refresh();
|
m_rootFolder->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Manager::downloadArticleTorrentIfMatching(const QString &url, const ArticlePtr &article)
|
||||||
|
{
|
||||||
|
m_deferredDownloads.append(qMakePair(url, article));
|
||||||
|
m_deferredDownloadTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::downloadNextArticleTorrentIfMatching()
|
||||||
|
{
|
||||||
|
if (m_deferredDownloads.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Schedule to process the next article (if any)
|
||||||
|
m_deferredDownloadTimer.start();
|
||||||
|
|
||||||
|
QPair<QString, ArticlePtr> urlArticle(m_deferredDownloads.takeFirst());
|
||||||
|
FeedList streams = m_rootFolder->getAllFeeds();
|
||||||
|
foreach (const FeedPtr &stream, streams) {
|
||||||
|
if (stream->url() == urlArticle.first) {
|
||||||
|
stream->deferredDownloadArticleTorrentIfMatching(urlArticle.second);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,19 +32,23 @@
|
|||||||
#ifndef RSSMANAGER_H
|
#ifndef RSSMANAGER_H
|
||||||
#define RSSMANAGER_H
|
#define RSSMANAGER_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPair>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
namespace Rss
|
namespace Rss
|
||||||
{
|
{
|
||||||
|
class Article;
|
||||||
class DownloadRuleList;
|
class DownloadRuleList;
|
||||||
class File;
|
class File;
|
||||||
class Folder;
|
class Folder;
|
||||||
class Feed;
|
class Feed;
|
||||||
class Manager;
|
class Manager;
|
||||||
|
|
||||||
|
typedef QSharedPointer<Article> ArticlePtr;
|
||||||
typedef QSharedPointer<File> FilePtr;
|
typedef QSharedPointer<File> FilePtr;
|
||||||
typedef QSharedPointer<Folder> FolderPtr;
|
typedef QSharedPointer<Folder> FolderPtr;
|
||||||
typedef QSharedPointer<Feed> FeedPtr;
|
typedef QSharedPointer<Feed> FeedPtr;
|
||||||
@@ -62,6 +66,7 @@ namespace Rss
|
|||||||
DownloadRuleList *downloadRules() const;
|
DownloadRuleList *downloadRules() const;
|
||||||
FolderPtr rootFolder() const;
|
FolderPtr rootFolder() const;
|
||||||
QThread *workingThread() const;
|
QThread *workingThread() const;
|
||||||
|
void downloadArticleTorrentIfMatching(const QString &url, const ArticlePtr &article);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refresh();
|
void refresh();
|
||||||
@@ -78,12 +83,17 @@ namespace Rss
|
|||||||
void feedInfosChanged(const QString &url, const QString &displayName, uint unreadCount);
|
void feedInfosChanged(const QString &url, const QString &displayName, uint unreadCount);
|
||||||
void feedIconChanged(const QString &url, const QString &iconPath);
|
void feedIconChanged(const QString &url, const QString &iconPath);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void downloadNextArticleTorrentIfMatching();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTimer m_refreshTimer;
|
QTimer m_refreshTimer;
|
||||||
uint m_refreshInterval;
|
uint m_refreshInterval;
|
||||||
DownloadRuleList *m_downloadRules;
|
DownloadRuleList *m_downloadRules;
|
||||||
FolderPtr m_rootFolder;
|
FolderPtr m_rootFolder;
|
||||||
QThread *m_workingThread;
|
QThread *m_workingThread;
|
||||||
|
QTimer m_deferredDownloadTimer;
|
||||||
|
QList<QPair<QString, ArticlePtr>> m_deferredDownloads;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ static inline void removePythonScriptIfExists(const QString &scriptPath)
|
|||||||
const QHash<QString, QString> SearchEngine::m_categoryNames = SearchEngine::initializeCategoryNames();
|
const QHash<QString, QString> SearchEngine::m_categoryNames = SearchEngine::initializeCategoryNames();
|
||||||
|
|
||||||
SearchEngine::SearchEngine()
|
SearchEngine::SearchEngine()
|
||||||
: m_updateUrl(QString("https://raw.github.com/qbittorrent/qBittorrent/master/src/searchengine/%1/engines/").arg(Utils::Misc::pythonVersion() >= 3 ? "nova3" : "nova"))
|
: m_updateUrl(QString("http://searchplugins.qbittorrent.org/%1/engines/").arg(Utils::Misc::pythonVersion() >= 3 ? "nova3" : "nova"))
|
||||||
, m_searchStopped(false)
|
, m_searchStopped(false)
|
||||||
{
|
{
|
||||||
updateNova();
|
updateNova();
|
||||||
|
|||||||
@@ -38,10 +38,6 @@
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "utils/fs.h"
|
#include "utils/fs.h"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
#define QSETTINGS_SYNC_IS_SAVE // whether QSettings::sync() is "atomic"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Encapsulates serialization of settings in "atomic" way.
|
// Encapsulates serialization of settings in "atomic" way.
|
||||||
@@ -69,7 +65,7 @@ namespace
|
|||||||
using SettingsPtr = std::unique_ptr<QSettings>;
|
using SettingsPtr = std::unique_ptr<QSettings>;
|
||||||
SettingsPtr createSettings(const QString &name)
|
SettingsPtr createSettings(const QString &name)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
return SettingsPtr(new QSettings(QSettings::IniFormat, QSettings::UserScope, "qBittorrent", name));
|
return SettingsPtr(new QSettings(QSettings::IniFormat, QSettings::UserScope, "qBittorrent", name));
|
||||||
#else
|
#else
|
||||||
return SettingsPtr(new QSettings("qBittorrent", name));
|
return SettingsPtr(new QSettings("qBittorrent", name));
|
||||||
@@ -103,6 +99,68 @@ namespace
|
|||||||
{"BitTorrent/Session/TempPath", "Preferences/Downloads/TempPath"},
|
{"BitTorrent/Session/TempPath", "Preferences/Downloads/TempPath"},
|
||||||
{"BitTorrent/Session/TempPathEnabled", "Preferences/Downloads/TempPathEnabled"},
|
{"BitTorrent/Session/TempPathEnabled", "Preferences/Downloads/TempPathEnabled"},
|
||||||
{"BitTorrent/Session/AddTorrentPaused", "Preferences/Downloads/StartInPause"},
|
{"BitTorrent/Session/AddTorrentPaused", "Preferences/Downloads/StartInPause"},
|
||||||
|
{"BitTorrent/Session/RefreshInterval", "Preferences/General/RefreshInterval"},
|
||||||
|
{"BitTorrent/Session/Preallocation", "Preferences/Downloads/PreAllocation"},
|
||||||
|
{"BitTorrent/Session/AddExtensionToIncompleteFiles", "Preferences/Downloads/UseIncompleteExtension"},
|
||||||
|
{"BitTorrent/Session/TorrentExportDirectory", "Preferences/Downloads/TorrentExportDir"},
|
||||||
|
{"BitTorrent/Session/FinishedTorrentExportDirectory", "Preferences/Downloads/FinishedTorrentExportDir"},
|
||||||
|
{"BitTorrent/Session/GlobalUPSpeedLimit", "Preferences/Connection/GlobalUPLimit"},
|
||||||
|
{"BitTorrent/Session/GlobalDLSpeedLimit", "Preferences/Connection/GlobalDLLimit"},
|
||||||
|
{"BitTorrent/Session/AlternativeGlobalUPSpeedLimit", "Preferences/Connection/GlobalUPLimitAlt"},
|
||||||
|
{"BitTorrent/Session/AlternativeGlobalDLSpeedLimit", "Preferences/Connection/GlobalDLLimitAlt"},
|
||||||
|
{"BitTorrent/Session/UseAlternativeGlobalSpeedLimit", "Preferences/Connection/alt_speeds_on"},
|
||||||
|
{"BitTorrent/Session/BandwidthSchedulerEnabled", "Preferences/Scheduler/Enabled"},
|
||||||
|
{"BitTorrent/Session/Port", "Preferences/Connection/PortRangeMin"},
|
||||||
|
{"BitTorrent/Session/UseRandomPort", "Preferences/General/UseRandomPort"},
|
||||||
|
{"BitTorrent/Session/IPv6Enabled", "Preferences/Connection/InterfaceListenIPv6"},
|
||||||
|
{"BitTorrent/Session/Interface", "Preferences/Connection/Interface"},
|
||||||
|
{"BitTorrent/Session/InterfaceName", "Preferences/Connection/InterfaceName"},
|
||||||
|
{"BitTorrent/Session/InterfaceAddress", "Preferences/Connection/InterfaceAddress"},
|
||||||
|
{"BitTorrent/Session/SaveResumeDataInterval", "Preferences/Downloads/SaveResumeDataInterval"},
|
||||||
|
{"BitTorrent/Session/Encryption", "Preferences/Bittorrent/Encryption"},
|
||||||
|
{"BitTorrent/Session/ForceProxy", "Preferences/Connection/ProxyForce"},
|
||||||
|
{"BitTorrent/Session/ProxyPeerConnections", "Preferences/Connection/ProxyPeerConnections"},
|
||||||
|
{"BitTorrent/Session/MaxConnections", "Preferences/Bittorrent/MaxConnecs"},
|
||||||
|
{"BitTorrent/Session/MaxUploads", "Preferences/Bittorrent/MaxUploads"},
|
||||||
|
{"BitTorrent/Session/MaxConnectionsPerTorrent", "Preferences/Bittorrent/MaxConnecsPerTorrent"},
|
||||||
|
{"BitTorrent/Session/MaxUploadsPerTorrent", "Preferences/Bittorrent/MaxUploadsPerTorrent"},
|
||||||
|
{"BitTorrent/Session/DHTEnabled", "Preferences/Bittorrent/DHT"},
|
||||||
|
{"BitTorrent/Session/LSDEnabled", "Preferences/Bittorrent/LSD"},
|
||||||
|
{"BitTorrent/Session/PeXEnabled", "Preferences/Bittorrent/PeX"},
|
||||||
|
{"BitTorrent/Session/AddTrackersEnabled", "Preferences/Bittorrent/AddTrackers"},
|
||||||
|
{"BitTorrent/Session/AdditionalTrackers", "Preferences/Bittorrent/TrackersList"},
|
||||||
|
{"BitTorrent/Session/IPFilteringEnabled", "Preferences/IPFilter/Enabled"},
|
||||||
|
{"BitTorrent/Session/TrackerFilteringEnabled", "Preferences/IPFilter/FilterTracker"},
|
||||||
|
{"BitTorrent/Session/IPFilter", "Preferences/IPFilter/File"},
|
||||||
|
{"BitTorrent/Session/GlobalMaxRatio", "Preferences/Bittorrent/MaxRatio"},
|
||||||
|
{"BitTorrent/Session/AnnounceToAllTrackers", "Preferences/Advanced/AnnounceToAllTrackers"},
|
||||||
|
{"BitTorrent/Session/DiskCacheSize", "Preferences/Downloads/DiskWriteCacheSize"},
|
||||||
|
{"BitTorrent/Session/DiskCacheTTL", "Preferences/Downloads/DiskWriteCacheTTL"},
|
||||||
|
{"BitTorrent/Session/UseOSCache", "Preferences/Advanced/osCache"},
|
||||||
|
{"BitTorrent/Session/AnonymousModeEnabled", "Preferences/Advanced/AnonymousMode"},
|
||||||
|
{"BitTorrent/Session/QueueingSystemEnabled", "Preferences/Queueing/QueueingEnabled"},
|
||||||
|
{"BitTorrent/Session/MaxActiveDownloads", "Preferences/Queueing/MaxActiveDownloads"},
|
||||||
|
{"BitTorrent/Session/MaxActiveUploads", "Preferences/Queueing/MaxActiveUploads"},
|
||||||
|
{"BitTorrent/Session/MaxActiveTorrents", "Preferences/Queueing/MaxActiveTorrents"},
|
||||||
|
{"BitTorrent/Session/IgnoreSlowTorrentsForQueueing", "Preferences/Queueing/IgnoreSlowTorrents"},
|
||||||
|
{"BitTorrent/Session/OutgoingPortsMin", "Preferences/Advanced/OutgoingPortsMin"},
|
||||||
|
{"BitTorrent/Session/OutgoingPortsMax", "Preferences/Advanced/OutgoingPortsMax"},
|
||||||
|
{"BitTorrent/Session/IgnoreLimitsOnLAN", "Preferences/Advanced/IgnoreLimitsLAN"},
|
||||||
|
{"BitTorrent/Session/IncludeOverheadInLimits", "Preferences/Advanced/IncludeOverhead"},
|
||||||
|
{"BitTorrent/Session/AnnounceIP", "Preferences/Connection/InetAddress"},
|
||||||
|
{"BitTorrent/Session/SuperSeedingEnabled", "Preferences/Advanced/SuperSeeding"},
|
||||||
|
{"BitTorrent/Session/MaxHalfOpenConnections", "Preferences/Connection/MaxHalfOpenConnec"},
|
||||||
|
{"BitTorrent/Session/uTPEnabled", "Preferences/Bittorrent/uTP"},
|
||||||
|
{"BitTorrent/Session/uTPRateLimited", "Preferences/Bittorrent/uTP_rate_limited"},
|
||||||
|
{"BitTorrent/TrackerEnabled", "Preferences/Advanced/trackerEnabled"},
|
||||||
|
{"Network/Proxy/OnlyForTorrents", "Preferences/Connection/ProxyOnlyForTorrents"},
|
||||||
|
{"Network/Proxy/Type", "Preferences/Connection/ProxyType"},
|
||||||
|
{"Network/Proxy/Authentication", "Preferences/Connection/Proxy/Authentication"},
|
||||||
|
{"Network/Proxy/Username", "Preferences/Connection/Proxy/Username"},
|
||||||
|
{"Network/Proxy/Password", "Preferences/Connection/Proxy/Password"},
|
||||||
|
{"Network/Proxy/IP", "Preferences/Connection/Proxy/IP"},
|
||||||
|
{"Network/Proxy/Port", "Preferences/Connection/Proxy/Port"},
|
||||||
|
{"Network/PortForwardingEnabled", "Preferences/Connection/UPnP"},
|
||||||
#ifdef QBT_USES_QT5
|
#ifdef QBT_USES_QT5
|
||||||
{"AddNewTorrentDialog/TreeHeaderState", "AddNewTorrentDialog/qt5/treeHeaderState"},
|
{"AddNewTorrentDialog/TreeHeaderState", "AddNewTorrentDialog/qt5/treeHeaderState"},
|
||||||
#else
|
#else
|
||||||
@@ -113,7 +171,9 @@ namespace
|
|||||||
{"AddNewTorrentDialog/Expanded", "AddNewTorrentDialog/expanded"},
|
{"AddNewTorrentDialog/Expanded", "AddNewTorrentDialog/expanded"},
|
||||||
{"AddNewTorrentDialog/SavePathHistory", "TorrentAdditionDlg/save_path_history"},
|
{"AddNewTorrentDialog/SavePathHistory", "TorrentAdditionDlg/save_path_history"},
|
||||||
{"AddNewTorrentDialog/Enabled", "Preferences/Downloads/NewAdditionDialog"},
|
{"AddNewTorrentDialog/Enabled", "Preferences/Downloads/NewAdditionDialog"},
|
||||||
{ "AddNewTorrentDialog/TopLevel", "Preferences/Downloads/NewAdditionDialogFront" }
|
{"AddNewTorrentDialog/TopLevel", "Preferences/Downloads/NewAdditionDialogFront"},
|
||||||
|
|
||||||
|
{"State/BannedIPs", "Preferences/IPFilter/BannedIPs"}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -201,9 +261,6 @@ void SettingsStorage::removeValue(const QString &key)
|
|||||||
QVariantHash TransactionalSettings::read()
|
QVariantHash TransactionalSettings::read()
|
||||||
{
|
{
|
||||||
QVariantHash res;
|
QVariantHash res;
|
||||||
#ifdef QSETTINGS_SYNC_IS_SAVE
|
|
||||||
deserialize(m_name, res);
|
|
||||||
#else
|
|
||||||
bool writeBackNeeded = false;
|
bool writeBackNeeded = false;
|
||||||
QString newPath = deserialize(m_name + QLatin1String("_new"), res);
|
QString newPath = deserialize(m_name + QLatin1String("_new"), res);
|
||||||
if (!newPath.isEmpty()) { // "_new" file is NOT empty
|
if (!newPath.isEmpty()) { // "_new" file is NOT empty
|
||||||
@@ -222,15 +279,12 @@ QVariantHash TransactionalSettings::read()
|
|||||||
|
|
||||||
if (writeBackNeeded)
|
if (writeBackNeeded)
|
||||||
write(res);
|
write(res);
|
||||||
#endif
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransactionalSettings::write(const QVariantHash &data)
|
bool TransactionalSettings::write(const QVariantHash &data)
|
||||||
{
|
{
|
||||||
#ifdef QSETTINGS_SYNC_IS_SAVE
|
|
||||||
serialize(m_name, data);
|
|
||||||
#else
|
|
||||||
// QSettings delete the file before writing it out. This can result in problems
|
// QSettings delete the file before writing it out. This can result in problems
|
||||||
// if the disk is full or a power outage occurs. Those events might occur
|
// if the disk is full or a power outage occurs. Those events might occur
|
||||||
// between deleting the file and recreating it. This is a safety measure.
|
// between deleting the file and recreating it. This is a safety measure.
|
||||||
@@ -247,7 +301,7 @@ bool TransactionalSettings::write(const QVariantHash &data)
|
|||||||
finalPath.remove(index, 4);
|
finalPath.remove(index, 4);
|
||||||
Utils::Fs::forceRemove(finalPath);
|
Utils::Fs::forceRemove(finalPath);
|
||||||
QFile::rename(newPath, finalPath);
|
QFile::rename(newPath, finalPath);
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
src/base/settingvalue.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SETTINGVALUE_H
|
||||||
|
#define SETTINGVALUE_H
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "settingsstorage.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class CachedSettingValue
|
||||||
|
{
|
||||||
|
using ProxyFunc = std::function<T (const T&)>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CachedSettingValue(const char *keyName, const T &defaultValue = T()
|
||||||
|
, ProxyFunc proxyFunc = [](const T &value) { return value; })
|
||||||
|
: m_keyName(QLatin1String(keyName))
|
||||||
|
, m_value(proxyFunc(SettingsStorage::instance()->loadValue(
|
||||||
|
m_keyName, defaultValue).template value<T>()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
T value() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedSettingValue<T> &operator=(const T &newValue)
|
||||||
|
{
|
||||||
|
m_value = newValue;
|
||||||
|
SettingsStorage::instance()->storeValue(m_keyName, m_value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T() const
|
||||||
|
{
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_keyName;
|
||||||
|
T m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SETTINGVALUE_H
|
||||||
@@ -92,9 +92,11 @@ void TorrentFileGuard::setAutoDeleteMode(TorrentFileGuard::AutoDeleteMode mode)
|
|||||||
|
|
||||||
QMetaEnum TorrentFileGuard::modeMetaEnum()
|
QMetaEnum TorrentFileGuard::modeMetaEnum()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||||
return QMetaEnum::fromType<AutoDeleteMode>();
|
return QMetaEnum::fromType<AutoDeleteMode>();
|
||||||
#else
|
#else
|
||||||
return staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AutoDeleteMode"));
|
const int enumeratorIndex = staticMetaObject.indexOfEnumerator("AutoDeleteMode");
|
||||||
|
Q_ASSERT(enumeratorIndex >= 0);
|
||||||
|
return staticMetaObject.enumerator(enumeratorIndex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef TOFFENTFILEGURAD_H
|
||||||
|
#define TOFFENTFILEGURAD_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
@@ -50,6 +53,10 @@ private:
|
|||||||
class TorrentFileGuard
|
class TorrentFileGuard
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
// moc from Qt4 ignores Q_ENUMS when it is behind #if QT_VERSION check
|
||||||
|
// this declaration is needed for Qt 4 only
|
||||||
|
// TODO Qt5: remove when dropping Qt4 support
|
||||||
|
Q_ENUMS(AutoDeleteMode)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TorrentFileGuard(const QString &path = QString());
|
TorrentFileGuard(const QString &path = QString());
|
||||||
@@ -72,9 +79,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static QMetaEnum modeMetaEnum();
|
static QMetaEnum modeMetaEnum();
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||||
Q_ENUMS(AutoDeleteMode)
|
|
||||||
#else
|
|
||||||
Q_ENUM(AutoDeleteMode)
|
Q_ENUM(AutoDeleteMode)
|
||||||
#endif
|
#endif
|
||||||
AutoDeleteMode m_mode;
|
AutoDeleteMode m_mode;
|
||||||
@@ -87,9 +92,12 @@ private:
|
|||||||
// This problem is NOT present in Qt 5.7.0 and maybe in some older Qt 5 versions too
|
// This problem is NOT present in Qt 5.7.0 and maybe in some older Qt 5 versions too
|
||||||
// Qt 4.8.7 has it.
|
// Qt 4.8.7 has it.
|
||||||
// Therefore, we can't inherit FileGuard :(
|
// Therefore, we can't inherit FileGuard :(
|
||||||
|
// TODO Qt5: port to private inheritance when dropping Qt 4 support
|
||||||
FileGuard m_guard;
|
FileGuard m_guard;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
|
||||||
Q_DECLARE_METATYPE(TorrentFileGuard::AutoDeleteMode)
|
Q_DECLARE_METATYPE(TorrentFileGuard::AutoDeleteMode)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // TOFFENTFILEGURAD_H
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
// we put all problematic UTF-8 chars/strings in this file.
|
// we put all problematic UTF-8 chars/strings in this file.
|
||||||
// See issue #3059 for more details (https://github.com/qbittorrent/qBittorrent/issues/3059).
|
// See issue #3059 for more details (https://github.com/qbittorrent/qBittorrent/issues/3059).
|
||||||
const char C_INFINITY[] = "∞";
|
const char C_INFINITY[] = "∞";
|
||||||
|
const char C_NON_BREAKING_SPACE[] = " ";
|
||||||
const char C_UP[] = "▲";
|
const char C_UP[] = "▲";
|
||||||
const char C_DOWN[] = "▼";
|
const char C_DOWN[] = "▼";
|
||||||
const char C_COPYRIGHT[] = "©";
|
const char C_COPYRIGHT[] = "©";
|
||||||
@@ -46,16 +47,20 @@ const char C_LOCALE_ESPERANTO[] = "Esperanto";
|
|||||||
const char C_LOCALE_FRENCH[] = "Français";
|
const char C_LOCALE_FRENCH[] = "Français";
|
||||||
const char C_LOCALE_GERMAN[] = "Deutsch";
|
const char C_LOCALE_GERMAN[] = "Deutsch";
|
||||||
const char C_LOCALE_HUNGARIAN[] = "Magyar";
|
const char C_LOCALE_HUNGARIAN[] = "Magyar";
|
||||||
|
const char C_LOCALE_ICELANDIC[] = "Íslenska";
|
||||||
const char C_LOCALE_INDONESIAN[] = "Bahasa Indonesia";
|
const char C_LOCALE_INDONESIAN[] = "Bahasa Indonesia";
|
||||||
const char C_LOCALE_ITALIAN[] = "Italiano";
|
const char C_LOCALE_ITALIAN[] = "Italiano";
|
||||||
const char C_LOCALE_DUTCH[] = "Nederlands";
|
const char C_LOCALE_DUTCH[] = "Nederlands";
|
||||||
const char C_LOCALE_SPANISH[] = "Español";
|
const char C_LOCALE_SPANISH[] = "Español";
|
||||||
const char C_LOCALE_CATALAN[] = "Català";
|
const char C_LOCALE_CATALAN[] = "Català";
|
||||||
const char C_LOCALE_GALICIAN[] = "Galego";
|
const char C_LOCALE_GALICIAN[] = "Galego";
|
||||||
|
const char C_LOCALE_OCCITAN[] = "lenga d'òc";
|
||||||
const char C_LOCALE_PORTUGUESE[] = "Português";
|
const char C_LOCALE_PORTUGUESE[] = "Português";
|
||||||
const char C_LOCALE_PORTUGUESE_BRAZIL[] = "Português brasileiro";
|
const char C_LOCALE_PORTUGUESE_BRAZIL[] = "Português brasileiro";
|
||||||
const char C_LOCALE_POLISH[] = "Polski";
|
const char C_LOCALE_POLISH[] = "Polski";
|
||||||
|
const char C_LOCALE_LATVIAN[] = "latviešu valoda";
|
||||||
const char C_LOCALE_LITHUANIAN[] = "Lietuvių";
|
const char C_LOCALE_LITHUANIAN[] = "Lietuvių";
|
||||||
|
const char C_LOCALE_MALAY[] = "بهاس ملايو";
|
||||||
const char C_LOCALE_CZECH[] = "Čeština";
|
const char C_LOCALE_CZECH[] = "Čeština";
|
||||||
const char C_LOCALE_SLOVAK[] = "Slovenčina";
|
const char C_LOCALE_SLOVAK[] = "Slovenčina";
|
||||||
const char C_LOCALE_SLOVENIAN[] = "Slovenščina";
|
const char C_LOCALE_SLOVENIAN[] = "Slovenščina";
|
||||||
@@ -71,6 +76,7 @@ const char C_LOCALE_NORWEGIAN[] = "Norsk";
|
|||||||
const char C_LOCALE_DANISH[] = "Dansk";
|
const char C_LOCALE_DANISH[] = "Dansk";
|
||||||
const char C_LOCALE_BULGARIAN[] = "Български";
|
const char C_LOCALE_BULGARIAN[] = "Български";
|
||||||
const char C_LOCALE_UKRAINIAN[] = "Українська";
|
const char C_LOCALE_UKRAINIAN[] = "Українська";
|
||||||
|
const char C_LOCALE_UZBEK[] = "أۇزبېك";
|
||||||
const char C_LOCALE_RUSSIAN[] = "Русский";
|
const char C_LOCALE_RUSSIAN[] = "Русский";
|
||||||
const char C_LOCALE_JAPANESE[] = "日本語";
|
const char C_LOCALE_JAPANESE[] = "日本語";
|
||||||
const char C_LOCALE_HEBREW[] = "עברית";
|
const char C_LOCALE_HEBREW[] = "עברית";
|
||||||
|
|||||||
@@ -269,67 +269,43 @@ bool Utils::Fs::isValidFileSystemName(const QString &name, bool allowSeparators)
|
|||||||
return !name.contains(regex);
|
return !name.contains(regex);
|
||||||
}
|
}
|
||||||
|
|
||||||
qlonglong Utils::Fs::freeDiskSpaceOnPath(QString path)
|
qulonglong Utils::Fs::freeDiskSpaceOnPath(const QString &path)
|
||||||
{
|
{
|
||||||
if (path.isEmpty()) return -1;
|
if (path.isEmpty()) return 0;
|
||||||
QDir dir_path(path);
|
|
||||||
if (!dir_path.exists()) {
|
|
||||||
QStringList parts = path.split("/");
|
|
||||||
while (parts.size() > 1 && !QDir(parts.join("/")).exists()) {
|
|
||||||
parts.removeLast();
|
|
||||||
}
|
|
||||||
dir_path = QDir(parts.join("/"));
|
|
||||||
if (!dir_path.exists()) return -1;
|
|
||||||
}
|
|
||||||
Q_ASSERT(dir_path.exists());
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
QDir dirPath(path);
|
||||||
unsigned long long available;
|
if (!dirPath.exists()) {
|
||||||
#ifdef Q_OS_HAIKU
|
QStringList parts = path.split("/");
|
||||||
const QString statfs_path = dir_path.path() + "/.";
|
while (parts.size() > 1 && !QDir(parts.join("/")).exists())
|
||||||
dev_t device = dev_for_path (qPrintable(statfs_path));
|
parts.removeLast();
|
||||||
if (device >= 0) {
|
|
||||||
|
dirPath = QDir(parts.join("/"));
|
||||||
|
if (!dirPath.exists()) return 0;
|
||||||
|
}
|
||||||
|
Q_ASSERT(dirPath.exists());
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
ULARGE_INTEGER bytesFree;
|
||||||
|
LPCWSTR nativePath = reinterpret_cast<LPCWSTR>((toNativePath(dirPath.path())).utf16());
|
||||||
|
if (GetDiskFreeSpaceExW(nativePath, &bytesFree, NULL, NULL) == 0)
|
||||||
|
return 0;
|
||||||
|
return bytesFree.QuadPart;
|
||||||
|
#elif defined(Q_OS_HAIKU)
|
||||||
|
const QString statfsPath = dirPath.path() + "/.";
|
||||||
|
dev_t device = dev_for_path(qPrintable(statfsPath));
|
||||||
|
if (device < 0)
|
||||||
|
return 0;
|
||||||
fs_info info;
|
fs_info info;
|
||||||
if (fs_stat_dev(device, &info) == B_OK) {
|
if (fs_stat_dev(device, &info) != B_OK)
|
||||||
available = ((unsigned long long)(info.free_blocks * info.block_size));
|
return 0;
|
||||||
return available;
|
return ((qulonglong) info.free_blocks * (qulonglong) info.block_size);
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
#else
|
#else
|
||||||
struct statfs stats;
|
struct statfs stats;
|
||||||
const QString statfs_path = dir_path.path() + "/.";
|
const QString statfsPath = dirPath.path() + "/.";
|
||||||
const int ret = statfs(qPrintable(statfs_path), &stats);
|
const int ret = statfs(qPrintable(statfsPath), &stats);
|
||||||
if (ret == 0) {
|
if (ret != 0)
|
||||||
available = ((unsigned long long)stats.f_bavail)
|
return 0;
|
||||||
* ((unsigned long long)stats.f_bsize);
|
return ((qulonglong) stats.f_bavail * (qulonglong) stats.f_bsize);
|
||||||
return available;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
|
|
||||||
PULARGE_INTEGER,
|
|
||||||
PULARGE_INTEGER,
|
|
||||||
PULARGE_INTEGER);
|
|
||||||
GetDiskFreeSpaceEx_t pGetDiskFreeSpaceEx =
|
|
||||||
(GetDiskFreeSpaceEx_t)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "GetDiskFreeSpaceExW");
|
|
||||||
if (pGetDiskFreeSpaceEx) {
|
|
||||||
ULARGE_INTEGER bytesFree, bytesTotal;
|
|
||||||
unsigned long long *ret;
|
|
||||||
if (pGetDiskFreeSpaceEx((LPCTSTR)(toNativePath(dir_path.path())).utf16(), &bytesFree, &bytesTotal, NULL)) {
|
|
||||||
ret = (unsigned long long*)&bytesFree;
|
|
||||||
return *ret;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,19 +354,17 @@ QString Utils::Fs::expandPathAbs(const QString& path)
|
|||||||
QString Utils::Fs::QDesktopServicesDataLocation()
|
QString Utils::Fs::QDesktopServicesDataLocation()
|
||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN)
|
||||||
LPWSTR path=new WCHAR[256];
|
wchar_t path[MAX_PATH + 1] = {L'\0'};
|
||||||
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
if (SHGetSpecialFolderPathW(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||||
result = fromNativePath(QString::fromWCharArray(path));
|
result = fromNativePath(QString::fromWCharArray(path));
|
||||||
if (!QCoreApplication::applicationName().isEmpty())
|
if (!QCoreApplication::applicationName().isEmpty())
|
||||||
result += QLatin1String("/") + qApp->applicationName();
|
result += QLatin1String("/") + qApp->applicationName();
|
||||||
#else
|
#elif defined(Q_OS_MAC)
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
FSRef ref;
|
FSRef ref;
|
||||||
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
||||||
if (err)
|
if (err)
|
||||||
return QString();
|
return QString();
|
||||||
QString path;
|
|
||||||
QByteArray ba(2048, 0);
|
QByteArray ba(2048, 0);
|
||||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||||
@@ -402,7 +376,6 @@ QString Utils::Fs::QDesktopServicesDataLocation()
|
|||||||
xdgDataHome += QLatin1String("/data/")
|
xdgDataHome += QLatin1String("/data/")
|
||||||
+ qApp->applicationName();
|
+ qApp->applicationName();
|
||||||
result = xdgDataHome;
|
result = xdgDataHome;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
if (!result.endsWith("/"))
|
if (!result.endsWith("/"))
|
||||||
result += "/";
|
result += "/";
|
||||||
@@ -518,3 +491,10 @@ QString Utils::Fs::cacheLocation()
|
|||||||
locationDir.mkpath(locationDir.absolutePath());
|
locationDir.mkpath(locationDir.absolutePath());
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utils::Fs::tempPath()
|
||||||
|
{
|
||||||
|
static const QString path = QDir::tempPath() + "/.qBittorrent/";
|
||||||
|
QDir().mkdir(path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Utils
|
|||||||
bool sameFiles(const QString& path1, const QString& path2);
|
bool sameFiles(const QString& path1, const QString& path2);
|
||||||
QString toValidFileSystemName(const QString &name, bool allowSeparators = false);
|
QString toValidFileSystemName(const QString &name, bool allowSeparators = false);
|
||||||
bool isValidFileSystemName(const QString& name, bool allowSeparators = false);
|
bool isValidFileSystemName(const QString& name, bool allowSeparators = false);
|
||||||
qlonglong freeDiskSpaceOnPath(QString path);
|
qulonglong freeDiskSpaceOnPath(const QString &path);
|
||||||
QString branchPath(const QString& file_path, QString* removed = 0);
|
QString branchPath(const QString& file_path, QString* removed = 0);
|
||||||
bool sameFileNames(const QString& first, const QString& second);
|
bool sameFileNames(const QString& first, const QString& second);
|
||||||
QString expandPath(const QString& path);
|
QString expandPath(const QString& path);
|
||||||
@@ -67,6 +67,7 @@ namespace Utils
|
|||||||
/* End of Qt4 code */
|
/* End of Qt4 code */
|
||||||
|
|
||||||
QString cacheLocation();
|
QString cacheLocation();
|
||||||
|
QString tempPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,73 @@ static struct { const char *source; const char *comment; } units[] = {
|
|||||||
|
|
||||||
void Utils::Misc::shutdownComputer(const ShutdownDialogAction &action)
|
void Utils::Misc::shutdownComputer(const ShutdownDialogAction &action)
|
||||||
{
|
{
|
||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB)
|
#if defined(Q_OS_WIN)
|
||||||
|
HANDLE hToken; // handle to process token
|
||||||
|
TOKEN_PRIVILEGES tkp; // pointer to token structure
|
||||||
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||||
|
return;
|
||||||
|
// Get the LUID for shutdown privilege.
|
||||||
|
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
|
||||||
|
&tkp.Privileges[0].Luid);
|
||||||
|
|
||||||
|
tkp.PrivilegeCount = 1; // one privilege to set
|
||||||
|
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
|
// Get shutdown privilege for this process.
|
||||||
|
|
||||||
|
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
|
||||||
|
(PTOKEN_PRIVILEGES) NULL, 0);
|
||||||
|
|
||||||
|
// Cannot test the return value of AdjustTokenPrivileges.
|
||||||
|
|
||||||
|
if (GetLastError() != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (action == ShutdownDialogAction::Suspend)
|
||||||
|
SetSuspendState(false, false, false);
|
||||||
|
else if (action == ShutdownDialogAction::Hibernate)
|
||||||
|
SetSuspendState(true, false, false);
|
||||||
|
else
|
||||||
|
InitiateSystemShutdownA(0, QCoreApplication::translate("misc", "qBittorrent will shutdown the computer now because all downloads are complete.").toLocal8Bit().data(), 10, true, false);
|
||||||
|
|
||||||
|
// Disable shutdown privilege.
|
||||||
|
tkp.Privileges[0].Attributes = 0;
|
||||||
|
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
|
||||||
|
|
||||||
|
#elif defined(Q_OS_MAC)
|
||||||
|
AEEventID EventToSend;
|
||||||
|
if (action != ShutdownDialogAction::Shutdown)
|
||||||
|
EventToSend = kAESleep;
|
||||||
|
else
|
||||||
|
EventToSend = kAEShutDown;
|
||||||
|
AEAddressDesc targetDesc;
|
||||||
|
static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
|
||||||
|
AppleEvent eventReply = {typeNull, NULL};
|
||||||
|
AppleEvent appleEventToSend = {typeNull, NULL};
|
||||||
|
|
||||||
|
OSStatus error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess,
|
||||||
|
sizeof(kPSNOfSystemProcess), &targetDesc);
|
||||||
|
|
||||||
|
if (error != noErr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc,
|
||||||
|
kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);
|
||||||
|
|
||||||
|
AEDisposeDesc(&targetDesc);
|
||||||
|
if (error != noErr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
error = AESend(&appleEventToSend, &eventReply, kAENoReply,
|
||||||
|
kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
|
||||||
|
|
||||||
|
AEDisposeDesc(&appleEventToSend);
|
||||||
|
if (error != noErr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AEDisposeDesc(&eventReply);
|
||||||
|
|
||||||
|
#elif (defined(Q_OS_UNIX) && defined(QT_DBUS_LIB))
|
||||||
// Use dbus to power off / suspend the system
|
// Use dbus to power off / suspend the system
|
||||||
if (action != ShutdownDialogAction::Shutdown) {
|
if (action != ShutdownDialogAction::Shutdown) {
|
||||||
// Some recent systems use systemd's logind
|
// Some recent systems use systemd's logind
|
||||||
@@ -147,73 +213,9 @@ void Utils::Misc::shutdownComputer(const ShutdownDialogAction &action)
|
|||||||
QDBusConnection::systemBus());
|
QDBusConnection::systemBus());
|
||||||
halIface.call("Shutdown");
|
halIface.call("Shutdown");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
AEEventID EventToSend;
|
|
||||||
if (action != ShutdownDialogAction::Shutdown)
|
|
||||||
EventToSend = kAESleep;
|
|
||||||
else
|
|
||||||
EventToSend = kAEShutDown;
|
|
||||||
AEAddressDesc targetDesc;
|
|
||||||
static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
|
|
||||||
AppleEvent eventReply = {typeNull, NULL};
|
|
||||||
AppleEvent appleEventToSend = {typeNull, NULL};
|
|
||||||
|
|
||||||
OSStatus error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess,
|
#else
|
||||||
sizeof(kPSNOfSystemProcess), &targetDesc);
|
Q_UNUSED(action);
|
||||||
|
|
||||||
if (error != noErr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc,
|
|
||||||
kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);
|
|
||||||
|
|
||||||
AEDisposeDesc(&targetDesc);
|
|
||||||
if (error != noErr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
error = AESend(&appleEventToSend, &eventReply, kAENoReply,
|
|
||||||
kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
|
|
||||||
|
|
||||||
AEDisposeDesc(&appleEventToSend);
|
|
||||||
if (error != noErr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AEDisposeDesc(&eventReply);
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
HANDLE hToken; // handle to process token
|
|
||||||
TOKEN_PRIVILEGES tkp; // pointer to token structure
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
|
||||||
return;
|
|
||||||
// Get the LUID for shutdown privilege.
|
|
||||||
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
|
|
||||||
&tkp.Privileges[0].Luid);
|
|
||||||
|
|
||||||
tkp.PrivilegeCount = 1; // one privilege to set
|
|
||||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
|
|
||||||
// Get shutdown privilege for this process.
|
|
||||||
|
|
||||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
|
|
||||||
(PTOKEN_PRIVILEGES) NULL, 0);
|
|
||||||
|
|
||||||
// Cannot test the return value of AdjustTokenPrivileges.
|
|
||||||
|
|
||||||
if (GetLastError() != ERROR_SUCCESS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (action == ShutdownDialogAction::Suspend)
|
|
||||||
SetSuspendState(false, false, false);
|
|
||||||
else if (action == ShutdownDialogAction::Hibernate)
|
|
||||||
SetSuspendState(true, false, false);
|
|
||||||
else
|
|
||||||
InitiateSystemShutdownA(0, QCoreApplication::translate("misc", "qBittorrent will shutdown the computer now because all downloads are complete.").toLocal8Bit().data(), 10, true, false);
|
|
||||||
|
|
||||||
// Disable shutdown privilege.
|
|
||||||
tkp.Privileges[0].Attributes = 0;
|
|
||||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
|
|
||||||
(PTOKEN_PRIVILEGES) NULL, 0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,14 +358,22 @@ QString Utils::Misc::friendlyUnit(qint64 bytesValue, bool isSpeed)
|
|||||||
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
||||||
QString ret;
|
QString ret;
|
||||||
if (unit == SizeUnit::Byte)
|
if (unit == SizeUnit::Byte)
|
||||||
ret = QString::number(bytesValue) + " " + unitString(unit);
|
ret = QString::number(bytesValue) + QString::fromUtf8(C_NON_BREAKING_SPACE) + unitString(unit);
|
||||||
else
|
else
|
||||||
ret = Utils::String::fromDouble(friendlyVal, 1) + " " + unitString(unit);
|
ret = Utils::String::fromDouble(friendlyVal, friendlyUnitPrecision(unit)) + QString::fromUtf8(C_NON_BREAKING_SPACE) + unitString(unit);
|
||||||
if (isSpeed)
|
if (isSpeed)
|
||||||
ret += QCoreApplication::translate("misc", "/s", "per second");
|
ret += QCoreApplication::translate("misc", "/s", "per second");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Utils::Misc::friendlyUnitPrecision(SizeUnit unit)
|
||||||
|
{
|
||||||
|
// friendlyUnit's number of digits after the decimal point
|
||||||
|
if (unit <= SizeUnit::MebiByte) return 1;
|
||||||
|
else if (unit == SizeUnit::GibiByte) return 2;
|
||||||
|
else return 3;
|
||||||
|
}
|
||||||
|
|
||||||
qlonglong Utils::Misc::sizeInBytes(qreal size, Utils::Misc::SizeUnit unit)
|
qlonglong Utils::Misc::sizeInBytes(qreal size, Utils::Misc::SizeUnit unit)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < static_cast<int>(unit); ++i)
|
for (int i = 0; i < static_cast<int>(unit); ++i)
|
||||||
@@ -430,21 +440,27 @@ QString Utils::Misc::userFriendlyDuration(qlonglong seconds)
|
|||||||
{
|
{
|
||||||
if ((seconds < 0) || (seconds >= MAX_ETA))
|
if ((seconds < 0) || (seconds >= MAX_ETA))
|
||||||
return QString::fromUtf8(C_INFINITY);
|
return QString::fromUtf8(C_INFINITY);
|
||||||
|
|
||||||
if (seconds == 0)
|
if (seconds == 0)
|
||||||
return "0";
|
return "0";
|
||||||
|
|
||||||
if (seconds < 60)
|
if (seconds < 60)
|
||||||
return QCoreApplication::translate("misc", "< 1m", "< 1 minute");
|
return QCoreApplication::translate("misc", "< 1m", "< 1 minute");
|
||||||
int minutes = seconds / 60;
|
|
||||||
|
qlonglong minutes = seconds / 60;
|
||||||
if (minutes < 60)
|
if (minutes < 60)
|
||||||
return QCoreApplication::translate("misc", "%1m", "e.g: 10minutes").arg(QString::number(minutes));
|
return QCoreApplication::translate("misc", "%1m", "e.g: 10minutes").arg(QString::number(minutes));
|
||||||
int hours = minutes / 60;
|
|
||||||
minutes = minutes - hours * 60;
|
qlonglong hours = minutes / 60;
|
||||||
|
minutes -= hours * 60;
|
||||||
if (hours < 24)
|
if (hours < 24)
|
||||||
return QCoreApplication::translate("misc", "%1h %2m", "e.g: 3hours 5minutes").arg(QString::number(hours)).arg(QString::number(minutes));
|
return QCoreApplication::translate("misc", "%1h %2m", "e.g: 3hours 5minutes").arg(QString::number(hours)).arg(QString::number(minutes));
|
||||||
int days = hours / 24;
|
|
||||||
hours = hours - days * 24;
|
qlonglong days = hours / 24;
|
||||||
|
hours -= days * 24;
|
||||||
if (days < 100)
|
if (days < 100)
|
||||||
return QCoreApplication::translate("misc", "%1d %2h", "e.g: 2days 10hours").arg(QString::number(days)).arg(QString::number(hours));
|
return QCoreApplication::translate("misc", "%1d %2h", "e.g: 2days 10hours").arg(QString::number(days)).arg(QString::number(hours));
|
||||||
|
|
||||||
return QString::fromUtf8(C_INFINITY);
|
return QString::fromUtf8(C_INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,7 +596,7 @@ void Utils::Misc::openFolderSelect(const QString &absolutePath)
|
|||||||
}
|
}
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
HRESULT hresult = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
HRESULT hresult = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||||
ITEMIDLIST *pidl = ::ILCreateFromPathW(reinterpret_cast<PCTSTR>(Utils::Fs::toNativePath(path).utf16()));
|
PIDLIST_ABSOLUTE pidl = ::ILCreateFromPathW(reinterpret_cast<PCTSTR>(Utils::Fs::toNativePath(path).utf16()));
|
||||||
if (pidl) {
|
if (pidl) {
|
||||||
::SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0);
|
::SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0);
|
||||||
::ILFree(pidl);
|
::ILFree(pidl);
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ namespace Utils
|
|||||||
// value must be given in bytes
|
// value must be given in bytes
|
||||||
bool friendlyUnit(qint64 sizeInBytes, qreal& val, SizeUnit& unit);
|
bool friendlyUnit(qint64 sizeInBytes, qreal& val, SizeUnit& unit);
|
||||||
QString friendlyUnit(qint64 bytesValue, bool isSpeed = false);
|
QString friendlyUnit(qint64 bytesValue, bool isSpeed = false);
|
||||||
|
int friendlyUnitPrecision(SizeUnit unit);
|
||||||
qint64 sizeInBytes(qreal size, SizeUnit unit);
|
qint64 sizeInBytes(qreal size, SizeUnit unit);
|
||||||
|
|
||||||
bool isPreviewable(const QString& extension);
|
bool isPreviewable(const QString& extension);
|
||||||
|
|||||||
@@ -177,8 +177,12 @@ QString Utils::String::fromStdString(const std::string &str)
|
|||||||
|
|
||||||
std::string Utils::String::toStdString(const QString &str)
|
std::string Utils::String::toStdString(const QString &str)
|
||||||
{
|
{
|
||||||
|
#ifdef QBT_USES_QT5
|
||||||
|
return str.toStdString();
|
||||||
|
#else
|
||||||
QByteArray utf8 = str.toUtf8();
|
QByteArray utf8 = str.toUtf8();
|
||||||
return std::string(utf8.constData(), utf8.length());
|
return std::string(utf8.constData(), utf8.length());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// to send numbers instead of strings with suffixes
|
// to send numbers instead of strings with suffixes
|
||||||
@@ -207,3 +211,12 @@ bool Utils::String::slowEquals(const QByteArray &a, const QByteArray &b)
|
|||||||
|
|
||||||
return (diff == 0);
|
return (diff == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utils::String::toHtmlEscaped(const QString &str)
|
||||||
|
{
|
||||||
|
#ifdef QBT_USES_QT5
|
||||||
|
return str.toHtmlEscaped();
|
||||||
|
#else
|
||||||
|
return Qt::escape(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ namespace Utils
|
|||||||
// Taken from https://crackstation.net/hashing-security.htm
|
// Taken from https://crackstation.net/hashing-security.htm
|
||||||
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
||||||
|
|
||||||
|
QString toHtmlEscaped(const QString &str);
|
||||||
|
|
||||||
bool naturalCompareCaseSensitive(const QString &left, const QString &right);
|
bool naturalCompareCaseSensitive(const QString &left, const QString &right);
|
||||||
bool naturalCompareCaseInsensitive(const QString &left, const QString &right);
|
bool naturalCompareCaseInsensitive(const QString &left, const QString &right);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ addnewtorrentdialog.h
|
|||||||
advancedsettings.h
|
advancedsettings.h
|
||||||
advancedsettings.h
|
advancedsettings.h
|
||||||
autoexpandabledialog.h
|
autoexpandabledialog.h
|
||||||
|
categoryfiltermodel.h
|
||||||
|
categoryfilterwidget.h
|
||||||
cookiesdialog.h
|
cookiesdialog.h
|
||||||
cookiesmodel.h
|
cookiesmodel.h
|
||||||
deletionconfirmationdlg.h
|
deletionconfirmationdlg.h
|
||||||
@@ -71,6 +73,8 @@ set(QBT_GUI_SOURCES
|
|||||||
addnewtorrentdialog.cpp
|
addnewtorrentdialog.cpp
|
||||||
advancedsettings.cpp
|
advancedsettings.cpp
|
||||||
autoexpandabledialog.cpp
|
autoexpandabledialog.cpp
|
||||||
|
categoryfiltermodel.cpp
|
||||||
|
categoryfilterwidget.cpp
|
||||||
cookiesdialog.cpp
|
cookiesdialog.cpp
|
||||||
cookiesmodel.cpp
|
cookiesmodel.cpp
|
||||||
executionlog.cpp
|
executionlog.cpp
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public:
|
|||||||
"</table>"
|
"</table>"
|
||||||
"</p>")
|
"</p>")
|
||||||
.arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar."))
|
.arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar."))
|
||||||
.arg(tr("Copyright %1 2006-2016 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT)))
|
.arg(tr("Copyright %1 2006-2017 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT)))
|
||||||
.arg(tr("Home Page:"))
|
.arg(tr("Home Page:"))
|
||||||
.arg(tr("Forum:"))
|
.arg(tr("Forum:"))
|
||||||
.arg(tr("Bug Tracker:"));
|
.arg(tr("Bug Tracker:"));
|
||||||
|
|||||||
@@ -58,7 +58,6 @@
|
|||||||
|
|
||||||
#define SETTINGS_KEY(name) "AddNewTorrentDialog/" name
|
#define SETTINGS_KEY(name) "AddNewTorrentDialog/" name
|
||||||
const QString KEY_ENABLED = SETTINGS_KEY("Enabled");
|
const QString KEY_ENABLED = SETTINGS_KEY("Enabled");
|
||||||
const QString KEY_DEFAULTSAVEPATH = SETTINGS_KEY("DefaultSavePath");
|
|
||||||
const QString KEY_DEFAULTCATEGORY = SETTINGS_KEY("DefaultCategory");
|
const QString KEY_DEFAULTCATEGORY = SETTINGS_KEY("DefaultCategory");
|
||||||
const QString KEY_TREEHEADERSTATE = SETTINGS_KEY("TreeHeaderState");
|
const QString KEY_TREEHEADERSTATE = SETTINGS_KEY("TreeHeaderState");
|
||||||
const QString KEY_WIDTH = SETTINGS_KEY("Width");
|
const QString KEY_WIDTH = SETTINGS_KEY("Width");
|
||||||
@@ -118,7 +117,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(QWidget *parent)
|
|||||||
// Signal / slots
|
// Signal / slots
|
||||||
connect(ui->adv_button, SIGNAL(clicked(bool)), SLOT(showAdvancedSettings(bool)));
|
connect(ui->adv_button, SIGNAL(clicked(bool)), SLOT(showAdvancedSettings(bool)));
|
||||||
connect(ui->doNotDeleteTorrentCheckBox, SIGNAL(clicked(bool)), SLOT(doNotDeleteTorrentClicked(bool)));
|
connect(ui->doNotDeleteTorrentCheckBox, SIGNAL(clicked(bool)), SLOT(doNotDeleteTorrentClicked(bool)));
|
||||||
editHotkey = new QShortcut(QKeySequence("F2"), ui->contentTreeView, 0, 0, Qt::WidgetShortcut);
|
editHotkey = new QShortcut(Qt::Key_F2, ui->contentTreeView, 0, 0, Qt::WidgetShortcut);
|
||||||
connect(editHotkey, SIGNAL(activated()), SLOT(renameSelectedFile()));
|
connect(editHotkey, SIGNAL(activated()), SLOT(renameSelectedFile()));
|
||||||
connect(ui->contentTreeView, SIGNAL(doubleClicked(QModelIndex)), SLOT(renameSelectedFile()));
|
connect(ui->contentTreeView, SIGNAL(doubleClicked(QModelIndex)), SLOT(renameSelectedFile()));
|
||||||
|
|
||||||
@@ -394,7 +393,7 @@ void AddNewTorrentDialog::onSavePathChanged(int index)
|
|||||||
ui->defaultSavePathCheckBox->setChecked(false);
|
ui->defaultSavePathCheckBox->setChecked(false);
|
||||||
ui->defaultSavePathCheckBox->setVisible(
|
ui->defaultSavePathCheckBox->setVisible(
|
||||||
QDir(ui->savePathComboBox->itemData(ui->savePathComboBox->currentIndex()).toString())
|
QDir(ui->savePathComboBox->itemData(ui->savePathComboBox->currentIndex()).toString())
|
||||||
!= QDir(defaultSavePath()));
|
!= QDir(BitTorrent::Session::instance()->defaultSavePath()));
|
||||||
|
|
||||||
// Remember index
|
// Remember index
|
||||||
m_oldIndex = index;
|
m_oldIndex = index;
|
||||||
@@ -567,7 +566,7 @@ void AddNewTorrentDialog::setdialogPosition()
|
|||||||
|
|
||||||
void AddNewTorrentDialog::populateSavePathComboBox()
|
void AddNewTorrentDialog::populateSavePathComboBox()
|
||||||
{
|
{
|
||||||
QString defSavePath = defaultSavePath();
|
QString defSavePath = BitTorrent::Session::instance()->defaultSavePath();
|
||||||
|
|
||||||
ui->savePathComboBox->clear();
|
ui->savePathComboBox->clear();
|
||||||
ui->savePathComboBox->addItem(Utils::Fs::toNativePath(defSavePath), defSavePath);
|
ui->savePathComboBox->addItem(Utils::Fs::toNativePath(defSavePath), defSavePath);
|
||||||
@@ -646,7 +645,7 @@ void AddNewTorrentDialog::accept()
|
|||||||
params.savePath = savePath;
|
params.savePath = savePath;
|
||||||
saveSavePathHistory();
|
saveSavePathHistory();
|
||||||
if (ui->defaultSavePathCheckBox->isChecked())
|
if (ui->defaultSavePathCheckBox->isChecked())
|
||||||
settings()->storeValue(KEY_DEFAULTSAVEPATH, savePath);
|
BitTorrent::Session::instance()->setDefaultSavePath(savePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnabled(!ui->never_show_cb->isChecked());
|
setEnabled(!ui->never_show_cb->isChecked());
|
||||||
@@ -690,7 +689,6 @@ void AddNewTorrentDialog::updateMetadata(const BitTorrent::TorrentInfo &info)
|
|||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
setupTreeview();
|
setupTreeview();
|
||||||
TMMChanged(ui->comboTTM->currentIndex());
|
|
||||||
setMetadataProgressIndicator(false, tr("Metadata retrieval complete"));
|
setMetadataProgressIndicator(false, tr("Metadata retrieval complete"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,13 +742,6 @@ void AddNewTorrentDialog::setupTreeview()
|
|||||||
setdialogPosition();
|
setdialogPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AddNewTorrentDialog::defaultSavePath() const
|
|
||||||
{
|
|
||||||
return Utils::Fs::fromNativePath(
|
|
||||||
settings()->loadValue(KEY_DEFAULTSAVEPATH,
|
|
||||||
BitTorrent::Session::instance()->defaultSavePath()).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddNewTorrentDialog::handleDownloadFailed(const QString &url, const QString &reason)
|
void AddNewTorrentDialog::handleDownloadFailed(const QString &url, const QString &reason)
|
||||||
{
|
{
|
||||||
MessageBoxRaised::critical(0, tr("Download Error"), QString("Cannot download '%1': %2").arg(url).arg(reason));
|
MessageBoxRaised::critical(0, tr("Download Error"), QString("Cannot download '%1': %2").arg(url).arg(reason));
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ private:
|
|||||||
void saveState();
|
void saveState();
|
||||||
void setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText = QString());
|
void setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText = QString());
|
||||||
void setupTreeview();
|
void setupTreeview();
|
||||||
QString defaultSavePath() const;
|
|
||||||
void setCommentText(const QString &str) const;
|
void setCommentText(const QString &str) const;
|
||||||
|
|
||||||
void showEvent(QShowEvent *event) override;
|
void showEvent(QShowEvent *event) override;
|
||||||
|
|||||||
@@ -27,11 +27,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "advancedsettings.h"
|
#include "advancedsettings.h"
|
||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
|
|
||||||
#include "app/application.h"
|
#include "app/application.h"
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "gui/mainwindow.h"
|
#include "gui/mainwindow.h"
|
||||||
|
|
||||||
@@ -63,6 +66,7 @@ enum AdvSettingsRows
|
|||||||
RESOLVE_COUNTRIES,
|
RESOLVE_COUNTRIES,
|
||||||
PROGRAM_NOTIFICATIONS,
|
PROGRAM_NOTIFICATIONS,
|
||||||
TORRENT_ADDED_NOTIFICATIONS,
|
TORRENT_ADDED_NOTIFICATIONS,
|
||||||
|
DOWNLOAD_TRACKER_FAVICON,
|
||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||||
USE_ICON_THEME,
|
USE_ICON_THEME,
|
||||||
#endif
|
#endif
|
||||||
@@ -83,9 +87,8 @@ enum AdvSettingsRows
|
|||||||
// seeding
|
// seeding
|
||||||
SUPER_SEEDING,
|
SUPER_SEEDING,
|
||||||
// tracker
|
// tracker
|
||||||
TRACKER_EXCHANGE,
|
|
||||||
ANNOUNCE_ALL_TRACKERS,
|
ANNOUNCE_ALL_TRACKERS,
|
||||||
NETWORK_ADDRESS,
|
ANNOUNCE_IP,
|
||||||
|
|
||||||
ROW_COUNT
|
ROW_COUNT
|
||||||
};
|
};
|
||||||
@@ -116,61 +119,63 @@ AdvancedSettings::AdvancedSettings(QWidget *parent)
|
|||||||
void AdvancedSettings::saveAdvancedSettings()
|
void AdvancedSettings::saveAdvancedSettings()
|
||||||
{
|
{
|
||||||
Preferences* const pref = Preferences::instance();
|
Preferences* const pref = Preferences::instance();
|
||||||
|
BitTorrent::Session *const session = BitTorrent::Session::instance();
|
||||||
|
|
||||||
// Disk write cache
|
// Disk write cache
|
||||||
pref->setDiskCacheSize(spin_cache.value());
|
session->setDiskCacheSize(spin_cache.value());
|
||||||
pref->setDiskCacheTTL(spin_cache_ttl.value());
|
session->setDiskCacheTTL(spin_cache_ttl.value());
|
||||||
// Enable OS cache
|
// Enable OS cache
|
||||||
pref->setOsCache(cb_os_cache.isChecked());
|
session->setUseOSCache(cb_os_cache.isChecked());
|
||||||
// Save resume data interval
|
// Save resume data interval
|
||||||
pref->setSaveResumeDataInterval(spin_save_resume_data_interval.value());
|
session->setSaveResumeDataInterval(spin_save_resume_data_interval.value());
|
||||||
// Outgoing ports
|
// Outgoing ports
|
||||||
pref->setOutgoingPortsMin(outgoing_ports_min.value());
|
session->setOutgoingPortsMin(outgoing_ports_min.value());
|
||||||
pref->setOutgoingPortsMax(outgoing_ports_max.value());
|
session->setOutgoingPortsMax(outgoing_ports_max.value());
|
||||||
// Recheck torrents on completion
|
// Recheck torrents on completion
|
||||||
pref->recheckTorrentsOnCompletion(cb_recheck_completed.isChecked());
|
pref->recheckTorrentsOnCompletion(cb_recheck_completed.isChecked());
|
||||||
// Transfer list refresh interval
|
// Transfer list refresh interval
|
||||||
pref->setRefreshInterval(spin_list_refresh.value());
|
session->setRefreshInterval(spin_list_refresh.value());
|
||||||
// Peer resolution
|
// Peer resolution
|
||||||
pref->resolvePeerCountries(cb_resolve_countries.isChecked());
|
pref->resolvePeerCountries(cb_resolve_countries.isChecked());
|
||||||
pref->resolvePeerHostNames(cb_resolve_hosts.isChecked());
|
pref->resolvePeerHostNames(cb_resolve_hosts.isChecked());
|
||||||
// Max Half-Open connections
|
// Max Half-Open connections
|
||||||
pref->setMaxHalfOpenConnections(spin_maxhalfopen.value());
|
session->setMaxHalfOpenConnections(spin_maxhalfopen.value());
|
||||||
// Super seeding
|
// Super seeding
|
||||||
pref->enableSuperSeeding(cb_super_seeding.isChecked());
|
session->setSuperSeedingEnabled(cb_super_seeding.isChecked());
|
||||||
// Network interface
|
// Network interface
|
||||||
if (combo_iface.currentIndex() == 0) {
|
if (combo_iface.currentIndex() == 0) {
|
||||||
// All interfaces (default)
|
// All interfaces (default)
|
||||||
pref->setNetworkInterface(QString::null);
|
session->setNetworkInterface(QString());
|
||||||
pref->setNetworkInterfaceName(QString::null);
|
session->setNetworkInterfaceName(QString());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pref->setNetworkInterface(combo_iface.itemData(combo_iface.currentIndex()).toString());
|
session->setNetworkInterface(combo_iface.itemData(combo_iface.currentIndex()).toString());
|
||||||
pref->setNetworkInterfaceName(combo_iface.currentText());
|
session->setNetworkInterfaceName(combo_iface.currentText());
|
||||||
}
|
}
|
||||||
// Listen on IPv6 address
|
|
||||||
pref->setListenIPv6(cb_listen_ipv6.isChecked());
|
|
||||||
// Interface address
|
// Interface address
|
||||||
if (combo_iface_address.currentIndex() == 0) {
|
if (combo_iface_address.currentIndex() == 0) {
|
||||||
// All addresses (default)
|
// All addresses (default)
|
||||||
pref->setNetworkInterfaceAddress(QString::null);
|
session->setNetworkInterfaceAddress(QString::null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QHostAddress ifaceAddr(combo_iface_address.currentText().trimmed());
|
QHostAddress ifaceAddr(combo_iface_address.currentText().trimmed());
|
||||||
ifaceAddr.isNull() ? pref->setNetworkInterfaceAddress(QString::null) : pref->setNetworkInterfaceAddress(ifaceAddr.toString());
|
ifaceAddr.isNull() ? session->setNetworkInterfaceAddress(QString::null) : session->setNetworkInterfaceAddress(ifaceAddr.toString());
|
||||||
}
|
}
|
||||||
// Network Announce address
|
session->setIPv6Enabled(cb_listen_ipv6.isChecked());
|
||||||
QHostAddress networkAddr(txt_network_address.text().trimmed());
|
// Announce IP
|
||||||
if (networkAddr.isNull())
|
QHostAddress addr(txtAnnounceIP.text().trimmed());
|
||||||
pref->setNetworkAddress("");
|
session->setAnnounceIP(addr.isNull() ? "" : addr.toString());
|
||||||
else
|
|
||||||
pref->setNetworkAddress(networkAddr.toString());
|
|
||||||
|
|
||||||
// Program notification
|
// Program notification
|
||||||
MainWindow * const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();
|
MainWindow * const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();
|
||||||
mainWindow->setNotificationsEnabled(cb_program_notifications.isChecked());
|
mainWindow->setNotificationsEnabled(cb_program_notifications.isChecked());
|
||||||
mainWindow->setTorrentAddedNotificationsEnabled(cb_torrent_added_notifications.isChecked());
|
mainWindow->setTorrentAddedNotificationsEnabled(cb_torrent_added_notifications.isChecked());
|
||||||
|
// Misc GUI properties
|
||||||
|
mainWindow->setDownloadTrackerFavicon(cb_tracker_favicon.isChecked());
|
||||||
|
|
||||||
// Tracker
|
// Tracker
|
||||||
pref->setTrackerEnabled(cb_tracker_status.isChecked());
|
session->setTrackerEnabled(cb_tracker_status.isChecked());
|
||||||
pref->setTrackerPort(spin_tracker_port.value());
|
pref->setTrackerPort(spin_tracker_port.value());
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
pref->setUpdateCheckEnabled(cb_update_check.isChecked());
|
pref->setUpdateCheckEnabled(cb_update_check.isChecked());
|
||||||
@@ -180,9 +185,7 @@ void AdvancedSettings::saveAdvancedSettings()
|
|||||||
pref->useSystemIconTheme(cb_use_icon_theme.isChecked());
|
pref->useSystemIconTheme(cb_use_icon_theme.isChecked());
|
||||||
#endif
|
#endif
|
||||||
pref->setConfirmTorrentRecheck(cb_confirm_torrent_recheck.isChecked());
|
pref->setConfirmTorrentRecheck(cb_confirm_torrent_recheck.isChecked());
|
||||||
// Tracker exchange
|
session->setAnnounceToAllTrackers(cb_announce_all_trackers.isChecked());
|
||||||
pref->setTrackerExchangeEnabled(cb_enable_tracker_ext.isChecked());
|
|
||||||
pref->setAnnounceToAllTrackers(cb_announce_all_trackers.isChecked());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedSettings::updateCacheSpinSuffix(int value)
|
void AdvancedSettings::updateCacheSpinSuffix(int value)
|
||||||
@@ -197,7 +200,7 @@ void AdvancedSettings::updateInterfaceAddressCombo()
|
|||||||
{
|
{
|
||||||
// Try to get the currently selected interface name
|
// Try to get the currently selected interface name
|
||||||
const QString ifaceName = combo_iface.itemData(combo_iface.currentIndex()).toString(); // Empty string for the first element
|
const QString ifaceName = combo_iface.itemData(combo_iface.currentIndex()).toString(); // Empty string for the first element
|
||||||
const QString currentAddress = Preferences::instance()->getNetworkInterfaceAddress();
|
const QString currentAddress = BitTorrent::Session::instance()->networkInterfaceAddress();
|
||||||
|
|
||||||
//Clear all items and reinsert them, default to all
|
//Clear all items and reinsert them, default to all
|
||||||
combo_iface_address.clear();
|
combo_iface_address.clear();
|
||||||
@@ -233,6 +236,8 @@ void AdvancedSettings::updateInterfaceAddressCombo()
|
|||||||
void AdvancedSettings::loadAdvancedSettings()
|
void AdvancedSettings::loadAdvancedSettings()
|
||||||
{
|
{
|
||||||
const Preferences* const pref = Preferences::instance();
|
const Preferences* const pref = Preferences::instance();
|
||||||
|
const BitTorrent::Session *const session = BitTorrent::Session::instance();
|
||||||
|
|
||||||
// add section headers
|
// add section headers
|
||||||
QFont boldFont;
|
QFont boldFont;
|
||||||
boldFont.setBold(true);
|
boldFont.setBold(true);
|
||||||
@@ -255,33 +260,33 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
|
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
|
||||||
spin_cache.setMaximum(1536);
|
spin_cache.setMaximum(1536);
|
||||||
#endif
|
#endif
|
||||||
spin_cache.setValue(pref->diskCacheSize());
|
spin_cache.setValue(session->diskCacheSize());
|
||||||
updateCacheSpinSuffix(spin_cache.value());
|
updateCacheSpinSuffix(spin_cache.value());
|
||||||
addRow(DISK_CACHE, tr("Disk write cache size"), &spin_cache);
|
addRow(DISK_CACHE, tr("Disk write cache size"), &spin_cache);
|
||||||
// Disk cache expiry
|
// Disk cache expiry
|
||||||
spin_cache_ttl.setMinimum(15);
|
spin_cache_ttl.setMinimum(15);
|
||||||
spin_cache_ttl.setMaximum(600);
|
spin_cache_ttl.setMaximum(600);
|
||||||
spin_cache_ttl.setValue(pref->diskCacheTTL());
|
spin_cache_ttl.setValue(session->diskCacheTTL());
|
||||||
spin_cache_ttl.setSuffix(tr(" s", " seconds"));
|
spin_cache_ttl.setSuffix(tr(" s", " seconds"));
|
||||||
addRow(DISK_CACHE_TTL, tr("Disk cache expiry interval"), &spin_cache_ttl);
|
addRow(DISK_CACHE_TTL, tr("Disk cache expiry interval"), &spin_cache_ttl);
|
||||||
// Enable OS cache
|
// Enable OS cache
|
||||||
cb_os_cache.setChecked(pref->osCache());
|
cb_os_cache.setChecked(session->useOSCache());
|
||||||
addRow(OS_CACHE, tr("Enable OS cache"), &cb_os_cache);
|
addRow(OS_CACHE, tr("Enable OS cache"), &cb_os_cache);
|
||||||
// Save resume data interval
|
// Save resume data interval
|
||||||
spin_save_resume_data_interval.setMinimum(1);
|
spin_save_resume_data_interval.setMinimum(1);
|
||||||
spin_save_resume_data_interval.setMaximum(1440);
|
spin_save_resume_data_interval.setMaximum(1440);
|
||||||
spin_save_resume_data_interval.setValue(pref->saveResumeDataInterval());
|
spin_save_resume_data_interval.setValue(session->saveResumeDataInterval());
|
||||||
spin_save_resume_data_interval.setSuffix(tr(" m", " minutes"));
|
spin_save_resume_data_interval.setSuffix(tr(" m", " minutes"));
|
||||||
addRow(SAVE_RESUME_DATA_INTERVAL, tr("Save resume data interval", "How often the fastresume file is saved."), &spin_save_resume_data_interval);
|
addRow(SAVE_RESUME_DATA_INTERVAL, tr("Save resume data interval", "How often the fastresume file is saved."), &spin_save_resume_data_interval);
|
||||||
// Outgoing port Min
|
// Outgoing port Min
|
||||||
outgoing_ports_min.setMinimum(0);
|
outgoing_ports_min.setMinimum(0);
|
||||||
outgoing_ports_min.setMaximum(65535);
|
outgoing_ports_min.setMaximum(65535);
|
||||||
outgoing_ports_min.setValue(pref->outgoingPortsMin());
|
outgoing_ports_min.setValue(session->outgoingPortsMin());
|
||||||
addRow(OUTGOING_PORT_MIN, tr("Outgoing ports (Min) [0: Disabled]"), &outgoing_ports_min);
|
addRow(OUTGOING_PORT_MIN, tr("Outgoing ports (Min) [0: Disabled]"), &outgoing_ports_min);
|
||||||
// Outgoing port Min
|
// Outgoing port Min
|
||||||
outgoing_ports_max.setMinimum(0);
|
outgoing_ports_max.setMinimum(0);
|
||||||
outgoing_ports_max.setMaximum(65535);
|
outgoing_ports_max.setMaximum(65535);
|
||||||
outgoing_ports_max.setValue(pref->outgoingPortsMax());
|
outgoing_ports_max.setValue(session->outgoingPortsMax());
|
||||||
addRow(OUTGOING_PORT_MAX, tr("Outgoing ports (Max) [0: Disabled]"), &outgoing_ports_max);
|
addRow(OUTGOING_PORT_MAX, tr("Outgoing ports (Max) [0: Disabled]"), &outgoing_ports_max);
|
||||||
// Recheck completed torrents
|
// Recheck completed torrents
|
||||||
cb_recheck_completed.setChecked(pref->recheckTorrentsOnCompletion());
|
cb_recheck_completed.setChecked(pref->recheckTorrentsOnCompletion());
|
||||||
@@ -289,7 +294,7 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
// Transfer list refresh interval
|
// Transfer list refresh interval
|
||||||
spin_list_refresh.setMinimum(30);
|
spin_list_refresh.setMinimum(30);
|
||||||
spin_list_refresh.setMaximum(99999);
|
spin_list_refresh.setMaximum(99999);
|
||||||
spin_list_refresh.setValue(pref->getRefreshInterval());
|
spin_list_refresh.setValue(session->refreshInterval());
|
||||||
spin_list_refresh.setSuffix(tr(" ms", " milliseconds"));
|
spin_list_refresh.setSuffix(tr(" ms", " milliseconds"));
|
||||||
addRow(LIST_REFRESH, tr("Transfer list refresh interval"), &spin_list_refresh);
|
addRow(LIST_REFRESH, tr("Transfer list refresh interval"), &spin_list_refresh);
|
||||||
// Resolve Peer countries
|
// Resolve Peer countries
|
||||||
@@ -301,14 +306,14 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
// Max Half Open connections
|
// Max Half Open connections
|
||||||
spin_maxhalfopen.setMinimum(0);
|
spin_maxhalfopen.setMinimum(0);
|
||||||
spin_maxhalfopen.setMaximum(99999);
|
spin_maxhalfopen.setMaximum(99999);
|
||||||
spin_maxhalfopen.setValue(pref->getMaxHalfOpenConnections());
|
spin_maxhalfopen.setValue(session->maxHalfOpenConnections());
|
||||||
addRow(MAX_HALF_OPEN, tr("Maximum number of half-open connections [0: Unlimited]"), &spin_maxhalfopen);
|
addRow(MAX_HALF_OPEN, tr("Maximum number of half-open connections [0: Unlimited]"), &spin_maxhalfopen);
|
||||||
// Super seeding
|
// Super seeding
|
||||||
cb_super_seeding.setChecked(pref->isSuperSeedingEnabled());
|
cb_super_seeding.setChecked(session->isSuperSeedingEnabled());
|
||||||
addRow(SUPER_SEEDING, tr("Strict super seeding"), &cb_super_seeding);
|
addRow(SUPER_SEEDING, tr("Strict super seeding"), &cb_super_seeding);
|
||||||
// Network interface
|
// Network interface
|
||||||
combo_iface.addItem(tr("Any interface", "i.e. Any network interface"));
|
combo_iface.addItem(tr("Any interface", "i.e. Any network interface"));
|
||||||
const QString current_iface = pref->getNetworkInterface();
|
const QString current_iface = session->networkInterface();
|
||||||
bool interface_exists = current_iface.isEmpty();
|
bool interface_exists = current_iface.isEmpty();
|
||||||
int i = 1;
|
int i = 1;
|
||||||
foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
|
foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
|
||||||
@@ -328,7 +333,7 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
}
|
}
|
||||||
// Saved interface does not exist, show it anyway
|
// Saved interface does not exist, show it anyway
|
||||||
if (!interface_exists) {
|
if (!interface_exists) {
|
||||||
combo_iface.addItem(pref->getNetworkInterfaceName(), current_iface);
|
combo_iface.addItem(session->networkInterfaceName(), current_iface);
|
||||||
combo_iface.setCurrentIndex(i);
|
combo_iface.setCurrentIndex(i);
|
||||||
}
|
}
|
||||||
addRow(NETWORK_IFACE, tr("Network Interface (requires restart)"), &combo_iface);
|
addRow(NETWORK_IFACE, tr("Network Interface (requires restart)"), &combo_iface);
|
||||||
@@ -336,11 +341,11 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
updateInterfaceAddressCombo();
|
updateInterfaceAddressCombo();
|
||||||
addRow(NETWORK_IFACE_ADDRESS, tr("Optional IP Address to bind to (requires restart)"), &combo_iface_address);
|
addRow(NETWORK_IFACE_ADDRESS, tr("Optional IP Address to bind to (requires restart)"), &combo_iface_address);
|
||||||
// Listen on IPv6 address
|
// Listen on IPv6 address
|
||||||
cb_listen_ipv6.setChecked(pref->getListenIPv6());
|
cb_listen_ipv6.setChecked(session->isIPv6Enabled());
|
||||||
addRow(NETWORK_LISTEN_IPV6, tr("Listen on IPv6 address (requires restart)"), &cb_listen_ipv6);
|
addRow(NETWORK_LISTEN_IPV6, tr("Listen on IPv6 address (requires restart)"), &cb_listen_ipv6);
|
||||||
// Announce address
|
// Announce IP
|
||||||
txt_network_address.setText(pref->getNetworkAddress());
|
txtAnnounceIP.setText(session->announceIP());
|
||||||
addRow(NETWORK_ADDRESS, tr("IP Address to report to trackers (requires restart)"), &txt_network_address);
|
addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &txtAnnounceIP);
|
||||||
|
|
||||||
// Program notifications
|
// Program notifications
|
||||||
const MainWindow * const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();
|
const MainWindow * const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();
|
||||||
@@ -349,8 +354,12 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
// Torrent added notifications
|
// Torrent added notifications
|
||||||
cb_torrent_added_notifications.setChecked(mainWindow->isTorrentAddedNotificationsEnabled());
|
cb_torrent_added_notifications.setChecked(mainWindow->isTorrentAddedNotificationsEnabled());
|
||||||
addRow(TORRENT_ADDED_NOTIFICATIONS, tr("Display notifications for added torrents"), &cb_torrent_added_notifications);
|
addRow(TORRENT_ADDED_NOTIFICATIONS, tr("Display notifications for added torrents"), &cb_torrent_added_notifications);
|
||||||
|
// Download tracker's favicon
|
||||||
|
cb_tracker_favicon.setChecked(mainWindow->isDownloadTrackerFavicon());
|
||||||
|
addRow(DOWNLOAD_TRACKER_FAVICON, tr("Download tracker's favicon"), &cb_tracker_favicon);
|
||||||
|
|
||||||
// Tracker State
|
// Tracker State
|
||||||
cb_tracker_status.setChecked(pref->isTrackerEnabled());
|
cb_tracker_status.setChecked(session->isTrackerEnabled());
|
||||||
addRow(TRACKER_STATUS, tr("Enable embedded tracker"), &cb_tracker_status);
|
addRow(TRACKER_STATUS, tr("Enable embedded tracker"), &cb_tracker_status);
|
||||||
// Tracker port
|
// Tracker port
|
||||||
spin_tracker_port.setMinimum(1);
|
spin_tracker_port.setMinimum(1);
|
||||||
@@ -368,17 +377,18 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||||||
// Torrent recheck confirmation
|
// Torrent recheck confirmation
|
||||||
cb_confirm_torrent_recheck.setChecked(pref->confirmTorrentRecheck());
|
cb_confirm_torrent_recheck.setChecked(pref->confirmTorrentRecheck());
|
||||||
addRow(CONFIRM_RECHECK_TORRENT, tr("Confirm torrent recheck"), &cb_confirm_torrent_recheck);
|
addRow(CONFIRM_RECHECK_TORRENT, tr("Confirm torrent recheck"), &cb_confirm_torrent_recheck);
|
||||||
// Tracker exchange
|
|
||||||
cb_enable_tracker_ext.setChecked(pref->trackerExchangeEnabled());
|
|
||||||
addRow(TRACKER_EXCHANGE, tr("Exchange trackers with other peers"), &cb_enable_tracker_ext);
|
|
||||||
// Announce to all trackers
|
// Announce to all trackers
|
||||||
cb_announce_all_trackers.setChecked(pref->announceToAllTrackers());
|
cb_announce_all_trackers.setChecked(session->announceToAllTrackers());
|
||||||
addRow(ANNOUNCE_ALL_TRACKERS, tr("Always announce to all trackers"), &cb_announce_all_trackers);
|
addRow(ANNOUNCE_ALL_TRACKERS, tr("Always announce to all trackers"), &cb_announce_all_trackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void AdvancedSettings::addRow(int row, const QString &rowText, T* widget)
|
void AdvancedSettings::addRow(int row, const QString &rowText, T* widget)
|
||||||
{
|
{
|
||||||
|
// ignore mouse wheel event
|
||||||
|
static WheelEventEater filter;
|
||||||
|
widget->installEventFilter(&filter);
|
||||||
|
|
||||||
setItem(row, PROPERTY, new QTableWidgetItem(rowText));
|
setItem(row, PROPERTY, new QTableWidgetItem(rowText));
|
||||||
setCellWidget(row, VALUE, widget);
|
setCellWidget(row, VALUE, widget);
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#ifndef ADVANCEDSETTINGS_H
|
#ifndef ADVANCEDSETTINGS_H
|
||||||
#define ADVANCEDSETTINGS_H
|
#define ADVANCEDSETTINGS_H
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
@@ -37,6 +38,22 @@
|
|||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
|
|
||||||
|
|
||||||
|
class WheelEventEater: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
switch (event->type()) {
|
||||||
|
case QEvent::Wheel:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class AdvancedSettings: public QTableWidget
|
class AdvancedSettings: public QTableWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -60,11 +77,11 @@ private:
|
|||||||
|
|
||||||
QLabel labelQbtLink, labelLibtorrentLink;
|
QLabel labelQbtLink, labelLibtorrentLink;
|
||||||
QSpinBox spin_cache, spin_save_resume_data_interval, outgoing_ports_min, outgoing_ports_max, spin_list_refresh, spin_maxhalfopen, spin_tracker_port, spin_cache_ttl;
|
QSpinBox spin_cache, spin_save_resume_data_interval, outgoing_ports_min, outgoing_ports_max, spin_list_refresh, spin_maxhalfopen, spin_tracker_port, spin_cache_ttl;
|
||||||
QCheckBox cb_os_cache, cb_recheck_completed, cb_resolve_countries, cb_resolve_hosts,
|
QCheckBox cb_os_cache, cb_recheck_completed, cb_resolve_countries, cb_resolve_hosts, cb_super_seeding,
|
||||||
cb_super_seeding, cb_program_notifications, cb_torrent_added_notifications, cb_tracker_status,
|
cb_program_notifications, cb_torrent_added_notifications, cb_tracker_favicon, cb_tracker_status,
|
||||||
cb_confirm_torrent_recheck, cb_enable_tracker_ext, cb_listen_ipv6, cb_announce_all_trackers;
|
cb_confirm_torrent_recheck, cb_listen_ipv6, cb_announce_all_trackers;
|
||||||
QComboBox combo_iface, combo_iface_address;
|
QComboBox combo_iface, combo_iface_address;
|
||||||
QLineEdit txt_network_address;
|
QLineEdit txtAnnounceIP;
|
||||||
|
|
||||||
// OS dependent settings
|
// OS dependent settings
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
|
|||||||
@@ -18,15 +18,6 @@
|
|||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="bandwidthSlider">
|
<widget class="QSlider" name="bandwidthSlider">
|
||||||
<property name="minimum">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="sliderPosition">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
442
src/gui/categoryfiltermodel.cpp
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "categoryfiltermodel.h"
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
|
#include "guiiconprovider.h"
|
||||||
|
|
||||||
|
class CategoryModelItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CategoryModelItem()
|
||||||
|
: m_parent(nullptr)
|
||||||
|
, m_torrentsCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryModelItem(CategoryModelItem *parent, QString categoryName, int torrentsCount = 0)
|
||||||
|
: m_parent(nullptr)
|
||||||
|
, m_name(categoryName)
|
||||||
|
, m_torrentsCount(torrentsCount)
|
||||||
|
{
|
||||||
|
if (parent)
|
||||||
|
parent->addChild(m_name, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CategoryModelItem()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->m_torrentsCount -= m_torrentsCount;
|
||||||
|
const QString uid = m_parent->m_children.key(this);
|
||||||
|
m_parent->m_children.remove(uid);
|
||||||
|
m_parent->m_childUids.removeOne(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fullName() const
|
||||||
|
{
|
||||||
|
if (!m_parent || m_parent->name().isEmpty())
|
||||||
|
return m_name;
|
||||||
|
|
||||||
|
return QString("%1/%2").arg(m_parent->fullName()).arg(m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryModelItem *parent() const
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
int torrentsCount() const
|
||||||
|
{
|
||||||
|
return m_torrentsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increaseTorrentsCount()
|
||||||
|
{
|
||||||
|
++m_torrentsCount;
|
||||||
|
if (m_parent)
|
||||||
|
m_parent->increaseTorrentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void decreaseTorrentsCount()
|
||||||
|
{
|
||||||
|
--m_torrentsCount;
|
||||||
|
if (m_parent)
|
||||||
|
m_parent->decreaseTorrentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos() const
|
||||||
|
{
|
||||||
|
if (!m_parent) return -1;
|
||||||
|
|
||||||
|
return m_parent->m_childUids.indexOf(m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasChild(const QString &name) const
|
||||||
|
{
|
||||||
|
return m_children.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int childCount() const
|
||||||
|
{
|
||||||
|
return m_children.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryModelItem *child(const QString &uid) const
|
||||||
|
{
|
||||||
|
return m_children.value(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryModelItem *childAt(int index) const
|
||||||
|
{
|
||||||
|
if ((index < 0) || (index >= m_childUids.count()))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return m_children[m_childUids[index]];
|
||||||
|
}
|
||||||
|
|
||||||
|
void addChild(const QString &uid, CategoryModelItem *item)
|
||||||
|
{
|
||||||
|
Q_ASSERT(item);
|
||||||
|
Q_ASSERT(!item->parent());
|
||||||
|
Q_ASSERT(!m_children.contains(uid));
|
||||||
|
|
||||||
|
item->m_parent = this;
|
||||||
|
m_children[uid] = item;
|
||||||
|
auto pos = std::lower_bound(m_childUids.begin(), m_childUids.end(), uid);
|
||||||
|
m_childUids.insert(pos, uid);
|
||||||
|
m_torrentsCount += item->torrentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
// use copy of m_children for qDeleteAll
|
||||||
|
// to avoid collision when child removes
|
||||||
|
// itself from parent children
|
||||||
|
qDeleteAll(decltype(m_children)(m_children));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CategoryModelItem *m_parent;
|
||||||
|
QString m_name;
|
||||||
|
int m_torrentsCount;
|
||||||
|
QHash<QString, CategoryModelItem *> m_children;
|
||||||
|
QStringList m_childUids;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QString shortName(const QString &fullName)
|
||||||
|
{
|
||||||
|
int pos = fullName.lastIndexOf(QLatin1Char('/'));
|
||||||
|
if (pos >= 0)
|
||||||
|
return fullName.mid(pos + 1);
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryFilterModel::CategoryFilterModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
, m_rootItem(new CategoryModelItem)
|
||||||
|
{
|
||||||
|
auto session = BitTorrent::Session::instance();
|
||||||
|
|
||||||
|
connect(session, SIGNAL(categoryAdded(QString)), SLOT(categoryAdded(QString)));
|
||||||
|
connect(session, SIGNAL(categoryRemoved(QString)), SLOT(categoryRemoved(QString)));
|
||||||
|
connect(session, SIGNAL(torrentCategoryChanged(BitTorrent::TorrentHandle *const, QString))
|
||||||
|
, SLOT(torrentCategoryChanged(BitTorrent::TorrentHandle *const, QString)));
|
||||||
|
connect(session, SIGNAL(subcategoriesSupportChanged()), SLOT(subcategoriesSupportChanged()));
|
||||||
|
connect(session, SIGNAL(torrentAdded(BitTorrent::TorrentHandle *const))
|
||||||
|
, SLOT(torrentAdded(BitTorrent::TorrentHandle *const)));
|
||||||
|
connect(session, SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const))
|
||||||
|
, SLOT(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)));
|
||||||
|
|
||||||
|
populate();
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryFilterModel::~CategoryFilterModel()
|
||||||
|
{
|
||||||
|
delete m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CategoryFilterModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CategoryFilterModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid()) return QVariant();
|
||||||
|
|
||||||
|
auto item = static_cast<CategoryModelItem *>(index.internalPointer());
|
||||||
|
|
||||||
|
if ((index.column() == 0) && (role == Qt::DecorationRole)) {
|
||||||
|
return GuiIconProvider::instance()->getIcon("inode-directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((index.column() == 0) && (role == Qt::DisplayRole)) {
|
||||||
|
return QString(QStringLiteral("%1 (%2)"))
|
||||||
|
.arg(item->name()).arg(item->torrentsCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((index.column() == 0) && (role == Qt::UserRole)) {
|
||||||
|
return item->torrentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags CategoryFilterModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid()) return 0;
|
||||||
|
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CategoryFilterModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
|
||||||
|
if (section == 0)
|
||||||
|
return tr("Categories");
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CategoryFilterModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (column > 0)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (parent.isValid() && (parent.column() != 0))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
auto parentItem = parent.isValid() ? static_cast<CategoryModelItem *>(parent.internalPointer())
|
||||||
|
: m_rootItem;
|
||||||
|
if (row < parentItem->childCount())
|
||||||
|
return createIndex(row, column, parentItem->childAt(row));
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CategoryFilterModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
auto item = static_cast<CategoryModelItem *>(index.internalPointer());
|
||||||
|
if (!item) return QModelIndex();
|
||||||
|
|
||||||
|
return this->index(item->parent());
|
||||||
|
}
|
||||||
|
|
||||||
|
int CategoryFilterModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.column() > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!parent.isValid())
|
||||||
|
return m_rootItem->childCount();
|
||||||
|
|
||||||
|
auto item = static_cast<CategoryModelItem *>(parent.internalPointer());
|
||||||
|
if (!item) return 0;
|
||||||
|
|
||||||
|
return item->childCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CategoryFilterModel::index(const QString &categoryName) const
|
||||||
|
{
|
||||||
|
return index(findItem(categoryName));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CategoryFilterModel::categoryName(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid()) return QString();
|
||||||
|
return static_cast<CategoryModelItem *>(index.internalPointer())->fullName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CategoryFilterModel::index(CategoryModelItem *item) const
|
||||||
|
{
|
||||||
|
if (!item || !item->parent()) return QModelIndex();
|
||||||
|
|
||||||
|
return index(item->pos(), 0, index(item->parent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::categoryAdded(const QString &categoryName)
|
||||||
|
{
|
||||||
|
CategoryModelItem *parent = m_rootItem;
|
||||||
|
|
||||||
|
if (m_isSubcategoriesEnabled) {
|
||||||
|
QStringList expanded = BitTorrent::Session::expandCategory(categoryName);
|
||||||
|
if (expanded.count() > 1)
|
||||||
|
parent = findItem(expanded[expanded.count() - 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto item = new CategoryModelItem(
|
||||||
|
parent, m_isSubcategoriesEnabled ? shortName(categoryName) : categoryName);
|
||||||
|
|
||||||
|
QModelIndex i = index(item);
|
||||||
|
beginInsertRows(i.parent(), i.row(), i.row());
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::categoryRemoved(const QString &categoryName)
|
||||||
|
{
|
||||||
|
auto item = findItem(categoryName);
|
||||||
|
if (item) {
|
||||||
|
QModelIndex i = index(item);
|
||||||
|
beginRemoveRows(i.parent(), i.row(), i.row());
|
||||||
|
delete item;
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::torrentAdded(BitTorrent::TorrentHandle *const torrent)
|
||||||
|
{
|
||||||
|
CategoryModelItem *item = findItem(torrent->category());
|
||||||
|
Q_ASSERT(item);
|
||||||
|
|
||||||
|
item->increaseTorrentsCount();
|
||||||
|
m_rootItem->childAt(0)->increaseTorrentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent)
|
||||||
|
{
|
||||||
|
CategoryModelItem *item = findItem(torrent->category());
|
||||||
|
Q_ASSERT(item);
|
||||||
|
|
||||||
|
item->decreaseTorrentsCount();
|
||||||
|
m_rootItem->childAt(0)->decreaseTorrentsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory)
|
||||||
|
{
|
||||||
|
QModelIndex i;
|
||||||
|
|
||||||
|
auto item = findItem(oldCategory);
|
||||||
|
Q_ASSERT(item);
|
||||||
|
|
||||||
|
item->decreaseTorrentsCount();
|
||||||
|
i = index(item);
|
||||||
|
while (i.isValid()) {
|
||||||
|
emit dataChanged(i, i);
|
||||||
|
i = parent(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
item = findItem(torrent->category());
|
||||||
|
Q_ASSERT(item);
|
||||||
|
|
||||||
|
item->increaseTorrentsCount();
|
||||||
|
i = index(item);
|
||||||
|
while (i.isValid()) {
|
||||||
|
emit dataChanged(i, i);
|
||||||
|
i = parent(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::subcategoriesSupportChanged()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
populate();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterModel::populate()
|
||||||
|
{
|
||||||
|
m_rootItem->clear();
|
||||||
|
|
||||||
|
auto session = BitTorrent::Session::instance();
|
||||||
|
auto torrents = session->torrents();
|
||||||
|
m_isSubcategoriesEnabled = session->isSubcategoriesEnabled();
|
||||||
|
|
||||||
|
const QString UID_ALL;
|
||||||
|
const QString UID_UNCATEGORIZED(QChar(1));
|
||||||
|
|
||||||
|
// All torrents
|
||||||
|
m_rootItem->addChild(UID_ALL, new CategoryModelItem(nullptr, tr("All"), torrents.count()));
|
||||||
|
|
||||||
|
// Uncategorized torrents
|
||||||
|
using Torrent = BitTorrent::TorrentHandle;
|
||||||
|
m_rootItem->addChild(
|
||||||
|
UID_UNCATEGORIZED
|
||||||
|
, new CategoryModelItem(
|
||||||
|
nullptr, tr("Uncategorized")
|
||||||
|
, std::count_if(torrents.begin(), torrents.end()
|
||||||
|
, [](Torrent *torrent) { return torrent->category().isEmpty(); })));
|
||||||
|
|
||||||
|
using Torrent = BitTorrent::TorrentHandle;
|
||||||
|
foreach (const QString &category, session->categories()) {
|
||||||
|
if (m_isSubcategoriesEnabled) {
|
||||||
|
CategoryModelItem *parent = m_rootItem;
|
||||||
|
foreach (const QString &subcat, session->expandCategory(category)) {
|
||||||
|
const QString subcatName = shortName(subcat);
|
||||||
|
if (!parent->hasChild(subcatName)) {
|
||||||
|
new CategoryModelItem(
|
||||||
|
parent, subcatName
|
||||||
|
, std::count_if(torrents.begin(), torrents.end()
|
||||||
|
, [subcat](Torrent *torrent) { return torrent->category() == subcat; }));
|
||||||
|
}
|
||||||
|
parent = parent->child(subcatName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new CategoryModelItem(
|
||||||
|
m_rootItem, category
|
||||||
|
, std::count_if(torrents.begin(), torrents.end()
|
||||||
|
, [category](Torrent *torrent) { return torrent->belongsToCategory(category); }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryModelItem *CategoryFilterModel::findItem(const QString &fullName) const
|
||||||
|
{
|
||||||
|
if (fullName.isEmpty())
|
||||||
|
return m_rootItem->childAt(1); // "Uncategorized" item
|
||||||
|
|
||||||
|
if (!m_isSubcategoriesEnabled)
|
||||||
|
return m_rootItem->child(fullName);
|
||||||
|
|
||||||
|
CategoryModelItem *item = m_rootItem;
|
||||||
|
foreach (const QString &subcat, BitTorrent::Session::expandCategory(fullName)) {
|
||||||
|
const QString subcatName = shortName(subcat);
|
||||||
|
if (!item->hasChild(subcatName)) return nullptr;
|
||||||
|
item = item->child(subcatName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
79
src/gui/categoryfiltermodel.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CATEGORYFILTERMODEL_H
|
||||||
|
#define CATEGORYFILTERMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QModelIndex>
|
||||||
|
|
||||||
|
namespace BitTorrent
|
||||||
|
{
|
||||||
|
class TorrentHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CategoryModelItem;
|
||||||
|
|
||||||
|
class CategoryFilterModel: public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CategoryFilterModel(QObject *parent = nullptr);
|
||||||
|
~CategoryFilterModel();
|
||||||
|
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QModelIndex index(const QString &categoryName) const;
|
||||||
|
QString categoryName(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void categoryAdded(const QString &categoryName);
|
||||||
|
void categoryRemoved(const QString &categoryName);
|
||||||
|
void torrentAdded(BitTorrent::TorrentHandle *const torrent);
|
||||||
|
void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
|
||||||
|
void torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory);
|
||||||
|
void subcategoriesSupportChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void populate();
|
||||||
|
QModelIndex index(CategoryModelItem *item) const;
|
||||||
|
CategoryModelItem *findItem(const QString &fullName) const;
|
||||||
|
|
||||||
|
bool m_isSubcategoriesEnabled;
|
||||||
|
CategoryModelItem *m_rootItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CATEGORYFILTERMODEL_H
|
||||||
270
src/gui/categoryfilterwidget.cpp
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "categoryfilterwidget.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
|
#include "base/utils/misc.h"
|
||||||
|
#include "autoexpandabledialog.h"
|
||||||
|
#include "categoryfiltermodel.h"
|
||||||
|
#include "guiiconprovider.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QString getCategoryFilter(const CategoryFilterModel *const model, const QModelIndex &index)
|
||||||
|
{
|
||||||
|
QString categoryFilter; // Defaults to All
|
||||||
|
if (index.isValid()) {
|
||||||
|
if (!index.parent().isValid() && (index.row() == 1))
|
||||||
|
categoryFilter = ""; // Uncategorized
|
||||||
|
else if (index.parent().isValid() || (index.row() > 1))
|
||||||
|
categoryFilter = model->categoryName(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return categoryFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSpecialItem(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
// the first two items at first level are special items:
|
||||||
|
// 'All' and 'Uncategorized'
|
||||||
|
return (!index.parent().isValid() && (index.row() <= 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryFilterWidget::CategoryFilterWidget(QWidget *parent)
|
||||||
|
: QTreeView(parent)
|
||||||
|
{
|
||||||
|
setModel(new CategoryFilterModel(this));
|
||||||
|
setFrameShape(QFrame::NoFrame);
|
||||||
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
setUniformRowHeights(true);
|
||||||
|
setHeaderHidden(true);
|
||||||
|
setIconSize(Utils::Misc::smallIconSize());
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||||
|
#endif
|
||||||
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
setCurrentIndex(model()->index(0, 0));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(collapsed(QModelIndex)), SLOT(callUpdateGeometry()));
|
||||||
|
connect(this, SIGNAL(expanded(QModelIndex)), SLOT(callUpdateGeometry()));
|
||||||
|
connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showMenu(QPoint)));
|
||||||
|
connect(selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex))
|
||||||
|
, SLOT(onCurrentRowChanged(QModelIndex,QModelIndex)));
|
||||||
|
connect(model(), SIGNAL(modelReset()), SLOT(callUpdateGeometry()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CategoryFilterWidget::currentCategory() const
|
||||||
|
{
|
||||||
|
QModelIndex current;
|
||||||
|
auto selectedRows = selectionModel()->selectedRows();
|
||||||
|
if (!selectedRows.isEmpty())
|
||||||
|
current = selectedRows.first();
|
||||||
|
|
||||||
|
return getCategoryFilter(static_cast<CategoryFilterModel *>(model()), current);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||||
|
{
|
||||||
|
Q_UNUSED(previous);
|
||||||
|
|
||||||
|
emit categoryChanged(getCategoryFilter(static_cast<CategoryFilterModel *>(model()), current));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::showMenu(QPoint)
|
||||||
|
{
|
||||||
|
QMenu menu(this);
|
||||||
|
|
||||||
|
QAction *addAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("list-add")
|
||||||
|
, tr("Add category..."));
|
||||||
|
connect(addAct, SIGNAL(triggered()), SLOT(addCategory()));
|
||||||
|
|
||||||
|
auto selectedRows = selectionModel()->selectedRows();
|
||||||
|
if (!selectedRows.empty() && !isSpecialItem(selectedRows.first())) {
|
||||||
|
if (BitTorrent::Session::instance()->isSubcategoriesEnabled()) {
|
||||||
|
QAction *addSubAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("list-add")
|
||||||
|
, tr("Add subcategory..."));
|
||||||
|
connect(addSubAct, SIGNAL(triggered()), SLOT(addSubcategory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *removeAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("list-remove")
|
||||||
|
, tr("Remove category"));
|
||||||
|
connect(removeAct, SIGNAL(triggered()), SLOT(removeCategory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *removeUnusedAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("list-remove")
|
||||||
|
, tr("Remove unused categories"));
|
||||||
|
connect(removeUnusedAct, SIGNAL(triggered()), SLOT(removeUnusedCategories()));
|
||||||
|
|
||||||
|
menu.addSeparator();
|
||||||
|
|
||||||
|
QAction *startAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("media-playback-start")
|
||||||
|
, tr("Resume torrents"));
|
||||||
|
connect(startAct, SIGNAL(triggered()), SIGNAL(actionResumeTorrentsTriggered()));
|
||||||
|
|
||||||
|
QAction *pauseAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("media-playback-pause")
|
||||||
|
, tr("Pause torrents"));
|
||||||
|
connect(pauseAct, SIGNAL(triggered()), SIGNAL(actionPauseTorrentsTriggered()));
|
||||||
|
|
||||||
|
QAction *deleteTorrentsAct = menu.addAction(
|
||||||
|
GuiIconProvider::instance()->getIcon("edit-delete")
|
||||||
|
, tr("Delete torrents"));
|
||||||
|
connect(deleteTorrentsAct, SIGNAL(triggered()), SIGNAL(actionDeleteTorrentsTriggered()));
|
||||||
|
|
||||||
|
menu.exec(QCursor::pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::callUpdateGeometry()
|
||||||
|
{
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize CategoryFilterWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
#ifdef QBT_USES_QT5
|
||||||
|
return viewportSizeHint();
|
||||||
|
#else
|
||||||
|
int lastRow = model()->rowCount() - 1;
|
||||||
|
QModelIndex last = model()->index(lastRow, 0);
|
||||||
|
while ((lastRow >= 0) && isExpanded(last)) {
|
||||||
|
lastRow = model()->rowCount(last) - 1;
|
||||||
|
last = model()->index(lastRow, 0, last);
|
||||||
|
}
|
||||||
|
const QRect deepestRect = visualRect(last);
|
||||||
|
|
||||||
|
if (!deepestRect.isValid())
|
||||||
|
return viewport()->sizeHint();
|
||||||
|
|
||||||
|
return QSize(header()->length(), deepestRect.bottom() + 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize CategoryFilterWidget::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
QSize size = sizeHint();
|
||||||
|
size.setWidth(6);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||||
|
{
|
||||||
|
QTreeView::rowsInserted(parent, start, end);
|
||||||
|
|
||||||
|
// Expand all parents if the parent(s) of the node are not expanded.
|
||||||
|
QModelIndex p = parent;
|
||||||
|
while (p.isValid()) {
|
||||||
|
if (!isExpanded(p))
|
||||||
|
expand(p);
|
||||||
|
p = model()->parent(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CategoryFilterWidget::askCategoryName()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
QString category = "";
|
||||||
|
bool invalid;
|
||||||
|
do {
|
||||||
|
invalid = false;
|
||||||
|
category = AutoExpandableDialog::getText(
|
||||||
|
this, tr("New Category"), tr("Category:"), QLineEdit::Normal, category, &ok);
|
||||||
|
if (ok && !category.isEmpty()) {
|
||||||
|
if (!BitTorrent::Session::isValidCategoryName(category)) {
|
||||||
|
QMessageBox::warning(
|
||||||
|
this, tr("Invalid category name")
|
||||||
|
, tr("Category name must not contain '\\'.\n"
|
||||||
|
"Category name must not start/end with '/'.\n"
|
||||||
|
"Category name must not contain '//' sequence."));
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (invalid);
|
||||||
|
|
||||||
|
return ok ? category : QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::addCategory()
|
||||||
|
{
|
||||||
|
const QString category = askCategoryName();
|
||||||
|
if (category.isEmpty()) return;
|
||||||
|
|
||||||
|
if (BitTorrent::Session::instance()->categories().contains(category))
|
||||||
|
QMessageBox::warning(this, tr("Category exists"), tr("Category name already exists."));
|
||||||
|
else
|
||||||
|
BitTorrent::Session::instance()->addCategory(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::addSubcategory()
|
||||||
|
{
|
||||||
|
const QString subcat = askCategoryName();
|
||||||
|
if (subcat.isEmpty()) return;
|
||||||
|
|
||||||
|
const QString category = QString(QStringLiteral("%1/%2")).arg(currentCategory()).arg(subcat);
|
||||||
|
|
||||||
|
if (BitTorrent::Session::instance()->categories().contains(category))
|
||||||
|
QMessageBox::warning(this, tr("Category exists")
|
||||||
|
, tr("Subcategory name already exists in selected category."));
|
||||||
|
else
|
||||||
|
BitTorrent::Session::instance()->addCategory(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::removeCategory()
|
||||||
|
{
|
||||||
|
auto selectedRows = selectionModel()->selectedRows();
|
||||||
|
if (!selectedRows.empty() && !isSpecialItem(selectedRows.first())) {
|
||||||
|
BitTorrent::Session::instance()->removeCategory(
|
||||||
|
static_cast<CategoryFilterModel *>(model())->categoryName(selectedRows.first()));
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CategoryFilterWidget::removeUnusedCategories()
|
||||||
|
{
|
||||||
|
auto session = BitTorrent::Session::instance();
|
||||||
|
foreach (const QString &category, session->categories())
|
||||||
|
if (model()->data(static_cast<CategoryFilterModel *>(model())->index(category), Qt::UserRole) == 0)
|
||||||
|
session->removeCategory(category);
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
60
src/gui/categoryfilterwidget.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
class CategoryFilterWidget: public QTreeView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CategoryFilterWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
QString currentCategory() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void categoryChanged(const QString &categoryName);
|
||||||
|
void actionResumeTorrentsTriggered();
|
||||||
|
void actionPauseTorrentsTriggered();
|
||||||
|
void actionDeleteTorrentsTriggered();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
void showMenu(QPoint);
|
||||||
|
void callUpdateGeometry();
|
||||||
|
void addCategory();
|
||||||
|
void addSubcategory();
|
||||||
|
void removeCategory();
|
||||||
|
void removeUnusedCategories();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
QSize minimumSizeHint() const override;
|
||||||
|
void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||||
|
QString askCategoryName();
|
||||||
|
};
|
||||||
@@ -35,8 +35,9 @@
|
|||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include "ui_confirmdeletiondlg.h"
|
#include "ui_confirmdeletiondlg.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "guiiconprovider.h"
|
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
|
#include "base/utils/string.h"
|
||||||
|
#include "guiiconprovider.h"
|
||||||
|
|
||||||
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -45,7 +46,7 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
|||||||
DeletionConfirmationDlg(QWidget *parent, const int &size, const QString &name, bool defaultDeleteFiles): QDialog(parent) {
|
DeletionConfirmationDlg(QWidget *parent, const int &size, const QString &name, bool defaultDeleteFiles): QDialog(parent) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
label->setText(tr("Are you sure you want to delete '%1' from the transfer list?", "Are you sure you want to delete 'ubuntu-linux-iso' from the transfer list?").arg(name));
|
label->setText(tr("Are you sure you want to delete '%1' from the transfer list?", "Are you sure you want to delete 'ubuntu-linux-iso' from the transfer list?").arg(Utils::String::toHtmlEscaped(name)));
|
||||||
else
|
else
|
||||||
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
||||||
// Icons
|
// Icons
|
||||||
|
|||||||
@@ -96,9 +96,9 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
|||||||
QMessageBox::warning(0, tr("No URL entered"), tr("Please type at least one URL."));
|
QMessageBox::warning(0, tr("No URL entered"), tr("Please type at least one URL."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
close();
|
|
||||||
emit urlsReadyToBeDownloaded(url_list_cleaned);
|
emit urlsReadyToBeDownloaded(url_list_cleaned);
|
||||||
qDebug("Emitted urlsReadytobedownloaded signal");
|
qDebug("Emitted urlsReadytobedownloaded signal");
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_cancelButton_clicked() {
|
void on_cancelButton_clicked() {
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ HEADERS += \
|
|||||||
$$PWD/search/searchlistdelegate.h \
|
$$PWD/search/searchlistdelegate.h \
|
||||||
$$PWD/search/searchsortmodel.h \
|
$$PWD/search/searchsortmodel.h \
|
||||||
$$PWD/cookiesmodel.h \
|
$$PWD/cookiesmodel.h \
|
||||||
$$PWD/cookiesdialog.h
|
$$PWD/cookiesdialog.h \
|
||||||
|
$$PWD/categoryfiltermodel.h \
|
||||||
|
$$PWD/categoryfilterwidget.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/mainwindow.cpp \
|
$$PWD/mainwindow.cpp \
|
||||||
@@ -89,7 +91,9 @@ SOURCES += \
|
|||||||
$$PWD/search/searchlistdelegate.cpp \
|
$$PWD/search/searchlistdelegate.cpp \
|
||||||
$$PWD/search/searchsortmodel.cpp \
|
$$PWD/search/searchsortmodel.cpp \
|
||||||
$$PWD/cookiesmodel.cpp \
|
$$PWD/cookiesmodel.cpp \
|
||||||
$$PWD/cookiesdialog.cpp
|
$$PWD/cookiesdialog.cpp \
|
||||||
|
$$PWD/categoryfiltermodel.cpp \
|
||||||
|
$$PWD/categoryfilterwidget.cpp
|
||||||
|
|
||||||
win32|macx {
|
win32|macx {
|
||||||
HEADERS += $$PWD/programupdater.h
|
HEADERS += $$PWD/programupdater.h
|
||||||
|
|||||||
@@ -57,13 +57,22 @@ GuiIconProvider *GuiIconProvider::instance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QIcon GuiIconProvider::getIcon(const QString &iconId)
|
QIcon GuiIconProvider::getIcon(const QString &iconId)
|
||||||
|
{
|
||||||
|
return getIcon(iconId, iconId);
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon GuiIconProvider::getIcon(const QString &iconId, const QString &fallback)
|
||||||
{
|
{
|
||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||||
if (m_useSystemTheme) {
|
if (m_useSystemTheme) {
|
||||||
QIcon icon = QIcon::fromTheme(iconId, QIcon(IconProvider::getIconPath(iconId)));
|
QIcon icon = QIcon::fromTheme(iconId);
|
||||||
|
if (icon.name() != iconId)
|
||||||
|
icon = QIcon::fromTheme(fallback, QIcon(IconProvider::getIconPath(iconId)));
|
||||||
icon = generateDifferentSizes(icon);
|
icon = generateDifferentSizes(icon);
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
Q_UNUSED(fallback)
|
||||||
#endif
|
#endif
|
||||||
return QIcon(IconProvider::getIconPath(iconId));
|
return QIcon(IconProvider::getIconPath(iconId));
|
||||||
}
|
}
|
||||||
@@ -81,6 +90,13 @@ QIcon GuiIconProvider::getFlagIcon(const QString &countryIsoCode)
|
|||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||||
QIcon GuiIconProvider::generateDifferentSizes(const QIcon &icon)
|
QIcon GuiIconProvider::generateDifferentSizes(const QIcon &icon)
|
||||||
{
|
{
|
||||||
|
// if icon is loaded from SVG format, it already contains all the required sizes and we shall not resize it
|
||||||
|
// In that case it will be available in the following sizes:
|
||||||
|
// (QSize(16, 16), QSize(22, 22), QSize(32, 32), QSize(48, 48), QSize(64, 64), QSize(128, 128), QSize(256, 256))
|
||||||
|
|
||||||
|
if (icon.availableSizes(QIcon::Normal, QIcon::On).size() > 6)
|
||||||
|
return icon;
|
||||||
|
|
||||||
QIcon newIcon;
|
QIcon newIcon;
|
||||||
QList<QSize> requiredSizes;
|
QList<QSize> requiredSizes;
|
||||||
requiredSizes << QSize(16, 16) << QSize(24, 24) << QSize(32, 32);
|
requiredSizes << QSize(16, 16) << QSize(24, 24) << QSize(32, 32);
|
||||||
|
|||||||