mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 14:08:03 -06:00
Compare commits
512 Commits
release-5.
...
v4_1_x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8cb552804 | ||
|
|
304e831b0c | ||
|
|
f16d219646 | ||
|
|
22b0160eaa | ||
|
|
d4f49c3666 | ||
|
|
0b055d8fef | ||
|
|
21595fca9c | ||
|
|
64ac48ee11 | ||
|
|
5d98721593 | ||
|
|
598159552e | ||
|
|
eea38e7c9e | ||
|
|
5c933c9734 | ||
|
|
102b7fa78e | ||
|
|
b5ee908f6c | ||
|
|
7825d8627f | ||
|
|
b798c591e7 | ||
|
|
9e7d21d7aa | ||
|
|
38a15b27f0 | ||
|
|
cb31684a66 | ||
|
|
850cde19f7 | ||
|
|
fc5b3b4f70 | ||
|
|
73fd4d83af | ||
|
|
811b525b1d | ||
|
|
0f8def9a49 | ||
|
|
359b464958 | ||
|
|
b5b0d68dd9 | ||
|
|
f48c49c248 | ||
|
|
11ca744548 | ||
|
|
82e6fc700e | ||
|
|
59fd70c638 | ||
|
|
617bf767df | ||
|
|
55180e3598 | ||
|
|
56b62e6573 | ||
|
|
b37e7b0340 | ||
|
|
21aebaf16f | ||
|
|
5792465317 | ||
|
|
e98f44af63 | ||
|
|
40cf0203fb | ||
|
|
05a82afeb6 | ||
|
|
a456f1b0f9 | ||
|
|
4acc44a5b0 | ||
|
|
9c2a1146df | ||
|
|
807abeae87 | ||
|
|
dd2a0d0484 | ||
|
|
3f3400f43b | ||
|
|
334b57a89a | ||
|
|
00d6c83ee5 | ||
|
|
e8850c7a70 | ||
|
|
2ef96eb218 | ||
|
|
4682e31ab7 | ||
|
|
988f7e2ef8 | ||
|
|
6007913291 | ||
|
|
cdcc7a210b | ||
|
|
a466ff5057 | ||
|
|
e954835579 | ||
|
|
3e9be3a0e8 | ||
|
|
4ab32a76f6 | ||
|
|
bad60058df | ||
|
|
31a6ad1eb6 | ||
|
|
a8bfec081e | ||
|
|
ae21d0f1e2 | ||
|
|
c599976b6f | ||
|
|
bcee784097 | ||
|
|
697fc626cd | ||
|
|
2f15ea9b54 | ||
|
|
d03209a73d | ||
|
|
ac9ba255d8 | ||
|
|
9a7e79bd0e | ||
|
|
e8be3bf939 | ||
|
|
74e52746b1 | ||
|
|
8d26a221e0 | ||
|
|
3fdab88eb7 | ||
|
|
d376d912b3 | ||
|
|
e329c41ef2 | ||
|
|
01e4179555 | ||
|
|
06f503b5df | ||
|
|
e2f3dad7b8 | ||
|
|
377f31085c | ||
|
|
ec13d195f8 | ||
|
|
c01aed8d90 | ||
|
|
ad7b8a9bfa | ||
|
|
5bba1ed208 | ||
|
|
fe94e14bcc | ||
|
|
b0af479ab9 | ||
|
|
24ff369f29 | ||
|
|
979c9a7094 | ||
|
|
7b90ac52c1 | ||
|
|
ecfbda78bc | ||
|
|
9ba7470815 | ||
|
|
6394467cc7 | ||
|
|
f6d72fa79f | ||
|
|
32ed5f1c8e | ||
|
|
5026da5773 | ||
|
|
ef130e4438 | ||
|
|
4fbd52c2d5 | ||
|
|
8f29b70c1e | ||
|
|
9a4dd3ea9d | ||
|
|
fcd3bb6918 | ||
|
|
9f69fd8750 | ||
|
|
ea7e47d113 | ||
|
|
294bb26996 | ||
|
|
4b2e9dba51 | ||
|
|
1d9dcde99b | ||
|
|
32bf448725 | ||
|
|
732d5d6db9 | ||
|
|
3b325106da | ||
|
|
3aeca37c5d | ||
|
|
4253515736 | ||
|
|
e365d57063 | ||
|
|
df6df20969 | ||
|
|
4e5a85dda5 | ||
|
|
bad603454b | ||
|
|
7b006a47ba | ||
|
|
11da8b82e8 | ||
|
|
383a5f11bc | ||
|
|
76ab5f12c5 | ||
|
|
be74987084 | ||
|
|
8f6c305d14 | ||
|
|
e29b9655eb | ||
|
|
ae7fa9ea82 | ||
|
|
fee9030337 | ||
|
|
f48d057c47 | ||
|
|
f14573307c | ||
|
|
560ba8c0b8 | ||
|
|
4b2376c4fd | ||
|
|
76faed3818 | ||
|
|
62657d9fda | ||
|
|
5877308a49 | ||
|
|
24dcbe7d43 | ||
|
|
7649fe0a0e | ||
|
|
b3b334da77 | ||
|
|
03a55da260 | ||
|
|
1a9eadf8e6 | ||
|
|
7b3fb2a35a | ||
|
|
a55ea29919 | ||
|
|
264b689912 | ||
|
|
684cf82f89 | ||
|
|
3f0e0a319a | ||
|
|
0b4d9c72a7 | ||
|
|
ff71f6bcd9 | ||
|
|
7a5c5baad1 | ||
|
|
a18976d0b5 | ||
|
|
6d836ea49c | ||
|
|
2e97311147 | ||
|
|
57bc564b2c | ||
|
|
1295f1e31f | ||
|
|
4916ed0efb | ||
|
|
f15f99cb27 | ||
|
|
93365d3b20 | ||
|
|
c756ab021d | ||
|
|
34528dd544 | ||
|
|
9380209afb | ||
|
|
be2895ac6f | ||
|
|
e26d4642b8 | ||
|
|
f470972bd4 | ||
|
|
443378c041 | ||
|
|
e20dbe34a4 | ||
|
|
86bde47a06 | ||
|
|
e273c777c7 | ||
|
|
17845c6b25 | ||
|
|
27827ce16a | ||
|
|
b444ecc6af | ||
|
|
34995350ee | ||
|
|
73ceee52f8 | ||
|
|
85a3ba0eed | ||
|
|
86cce76e9d | ||
|
|
3358fd8e91 | ||
|
|
120965f823 | ||
|
|
e70ee9a5b6 | ||
|
|
a2d8e84e83 | ||
|
|
4a3648a693 | ||
|
|
baad45e638 | ||
|
|
d9cb00aab2 | ||
|
|
d703d98836 | ||
|
|
2f0646e7f0 | ||
|
|
1a8a6dcef7 | ||
|
|
990f961126 | ||
|
|
06f04dea19 | ||
|
|
8eced2ef1f | ||
|
|
1e486ea92e | ||
|
|
b47f38675e | ||
|
|
864f3393a0 | ||
|
|
cebef74326 | ||
|
|
e257b35cac | ||
|
|
1f33991e4b | ||
|
|
794053f212 | ||
|
|
3a130e1f74 | ||
|
|
3423f93230 | ||
|
|
2219167253 | ||
|
|
a0a32b89a6 | ||
|
|
59162bf426 | ||
|
|
dfd148f55f | ||
|
|
3af720b3bc | ||
|
|
11240d0837 | ||
|
|
e64fd9c544 | ||
|
|
50ef812427 | ||
|
|
bd4d2fa424 | ||
|
|
e2ee928017 | ||
|
|
62e71a15a4 | ||
|
|
c62127e9f1 | ||
|
|
2171d579ee | ||
|
|
6e5a969e2d | ||
|
|
bfbc7ef28a | ||
|
|
b1cefbf9b5 | ||
|
|
201638854e | ||
|
|
847ecdeedb | ||
|
|
acc159fa60 | ||
|
|
bb7e80a8a6 | ||
|
|
39973f1bb1 | ||
|
|
1e9151364a | ||
|
|
fd50d6e9af | ||
|
|
427acf0c46 | ||
|
|
f0a50424be | ||
|
|
aded9afc0e | ||
|
|
060b7480db | ||
|
|
7f2a01dcd6 | ||
|
|
fef0e70c9f | ||
|
|
9cc112aa4e | ||
|
|
44d4d41365 | ||
|
|
a21c386dbf | ||
|
|
1c4139906a | ||
|
|
1a21f45c75 | ||
|
|
0061b75200 | ||
|
|
420c93a99e | ||
|
|
93f1183cd7 | ||
|
|
b8fcc1fed2 | ||
|
|
2b91be1905 | ||
|
|
7c9ef96ef8 | ||
|
|
37b4b69199 | ||
|
|
fc18e6f8df | ||
|
|
4793a35e0b | ||
|
|
4599da3ce1 | ||
|
|
dec4e41fdd | ||
|
|
780ece0c25 | ||
|
|
aac8bfc398 | ||
|
|
1a06a18336 | ||
|
|
2d4f963d65 | ||
|
|
b54fe08201 | ||
|
|
d1d0300491 | ||
|
|
7fff06f07b | ||
|
|
3f9351042d | ||
|
|
9e01dbab0f | ||
|
|
d4a4b02cf6 | ||
|
|
1f2c7a6671 | ||
|
|
5a7b88c16c | ||
|
|
93351476e4 | ||
|
|
e1bfa95a63 | ||
|
|
7030cc08e7 | ||
|
|
a1da9812a5 | ||
|
|
8ebc0f529c | ||
|
|
e0d47649bc | ||
|
|
524d503860 | ||
|
|
cffafa8e9f | ||
|
|
0fda919268 | ||
|
|
7d98c34e17 | ||
|
|
93147e787b | ||
|
|
80435bae7e | ||
|
|
b367e5c197 | ||
|
|
5336c71da5 | ||
|
|
27f6db976d | ||
|
|
8223d61fa7 | ||
|
|
3eef12bd8f | ||
|
|
9e70a6c499 | ||
|
|
fec3a87421 | ||
|
|
59aac32eb9 | ||
|
|
5ef3917769 | ||
|
|
2f767d96d9 | ||
|
|
de24fdfdc2 | ||
|
|
3bb6a68c9d | ||
|
|
f2406eb2f3 | ||
|
|
4923ed7da0 | ||
|
|
82056355f6 | ||
|
|
f3bd2a295f | ||
|
|
cc96760839 | ||
|
|
ae95943f69 | ||
|
|
d3067f939e | ||
|
|
b6addd304c | ||
|
|
d1ae6e8d58 | ||
|
|
4445c2dab2 | ||
|
|
fcc1564a62 | ||
|
|
615eeb7144 | ||
|
|
855bb118b5 | ||
|
|
9f1eb3600a | ||
|
|
fb885d89c1 | ||
|
|
a846916beb | ||
|
|
a574c4a70a | ||
|
|
1e367f818d | ||
|
|
00599c8f02 | ||
|
|
332a836746 | ||
|
|
a1992acc16 | ||
|
|
c3f002a544 | ||
|
|
c28cbe0a74 | ||
|
|
435daaceed | ||
|
|
e29ab0087b | ||
|
|
aadd5a3312 | ||
|
|
7e354ffad3 | ||
|
|
ee6a071fb6 | ||
|
|
bc8b838953 | ||
|
|
5251d93b3d | ||
|
|
84f0dbecfe | ||
|
|
bba0c8b2cc | ||
|
|
2f90be8bd2 | ||
|
|
cb6b6296aa | ||
|
|
9d25fdce2a | ||
|
|
12b2732f1a | ||
|
|
8c9ece73ee | ||
|
|
a7db786387 | ||
|
|
e5bf65c9bd | ||
|
|
900e7d3a14 | ||
|
|
f1ff74a926 | ||
|
|
30bc4b837e | ||
|
|
050a4f8b23 | ||
|
|
487103d58f | ||
|
|
eeea69d4c1 | ||
|
|
00360ad418 | ||
|
|
a733253ae5 | ||
|
|
9788ee042b | ||
|
|
e9c9ea3bba | ||
|
|
312dfb989d | ||
|
|
75deafe5b1 | ||
|
|
4ca257a389 | ||
|
|
03375a78f2 | ||
|
|
423c7066d7 | ||
|
|
5cd5cc71a8 | ||
|
|
45d4d22055 | ||
|
|
916a92aa0d | ||
|
|
d1ebbcb35d | ||
|
|
2743d998a8 | ||
|
|
dbbfbaff9f | ||
|
|
0be8439cf6 | ||
|
|
66982c5524 | ||
|
|
85af8547f7 | ||
|
|
e26977ab2c | ||
|
|
ec1cc783a6 | ||
|
|
03b00ec045 | ||
|
|
5e90156e9e | ||
|
|
052206efa1 | ||
|
|
305d73180b | ||
|
|
80000bf0fd | ||
|
|
06ebe756e8 | ||
|
|
5fa3d9f19c | ||
|
|
5b4c6d3665 | ||
|
|
77bd0f17d1 | ||
|
|
03a702cfbd | ||
|
|
a932cd2ec1 | ||
|
|
8e5743380a | ||
|
|
8001eb0368 | ||
|
|
f214dc88fc | ||
|
|
5cff5ab135 | ||
|
|
82ba154b64 | ||
|
|
4ea44bbd2b | ||
|
|
a5e68a8725 | ||
|
|
70291014d1 | ||
|
|
1aabcfc30c | ||
|
|
aba80e2b1c | ||
|
|
be683fbcd3 | ||
|
|
2bcf09cfa5 | ||
|
|
697325af63 | ||
|
|
c21bd77be5 | ||
|
|
d5430adaaa | ||
|
|
9e99a0d3f5 | ||
|
|
d088ab6f43 | ||
|
|
820d510c12 | ||
|
|
676847fcd0 | ||
|
|
0204630ee6 | ||
|
|
b515c7eda4 | ||
|
|
73fcecac76 | ||
|
|
a7b82ebcb5 | ||
|
|
f8598b010d | ||
|
|
93779bcc4b | ||
|
|
938f5b9dd9 | ||
|
|
3b4d9f49d5 | ||
|
|
171c93af50 | ||
|
|
6f81e40106 | ||
|
|
e19b5cb2ce | ||
|
|
2c69faca58 | ||
|
|
9272151d0a | ||
|
|
d45ebf5a43 | ||
|
|
8074be7644 | ||
|
|
c99ac99a99 | ||
|
|
976e2450ec | ||
|
|
7e4db8fafd | ||
|
|
115a409d92 | ||
|
|
c203ab3d16 | ||
|
|
5dff96496d | ||
|
|
f813935011 | ||
|
|
2be719449f | ||
|
|
2094c870d5 | ||
|
|
4fe93ae8b8 | ||
|
|
fff1103cf4 | ||
|
|
8cede43a45 | ||
|
|
9b1fa3a5af | ||
|
|
409e73c074 | ||
|
|
c893729d62 | ||
|
|
945466968c | ||
|
|
54f080b755 | ||
|
|
bfad14d552 | ||
|
|
2972e1596d | ||
|
|
987d2aae88 | ||
|
|
4707d34fad | ||
|
|
2ffc09d097 | ||
|
|
afa8d6bb8f | ||
|
|
a37ead98e8 | ||
|
|
c73cd8d618 | ||
|
|
800a3aa61e | ||
|
|
ebd815be75 | ||
|
|
ef669acf89 | ||
|
|
ac6426eab1 | ||
|
|
b107b745f2 | ||
|
|
3d851a448f | ||
|
|
ce133f01aa | ||
|
|
492d378537 | ||
|
|
7ece484423 | ||
|
|
be5ad63e21 | ||
|
|
bdac8f8db8 | ||
|
|
bb893e70c5 | ||
|
|
57ec9db532 | ||
|
|
0287481001 | ||
|
|
0167496ecb | ||
|
|
d86cf193a0 | ||
|
|
246cad1108 | ||
|
|
23bf86a8a8 | ||
|
|
6ce4c885b9 | ||
|
|
faf84e483a | ||
|
|
576004c840 | ||
|
|
c93b05c293 | ||
|
|
55c3813fac | ||
|
|
725c6857be | ||
|
|
86767c9ab4 | ||
|
|
46aa631d2b | ||
|
|
7c61a937c9 | ||
|
|
b8d65dcc45 | ||
|
|
b9ab83eaf2 | ||
|
|
8b7b563992 | ||
|
|
b813a878d7 | ||
|
|
54e486c389 | ||
|
|
12d0a3acc1 | ||
|
|
6ad2a13386 | ||
|
|
2a9c401db9 | ||
|
|
ea5a29018f | ||
|
|
c8d0a715e8 | ||
|
|
2cfc6514ab | ||
|
|
1d78bc7206 | ||
|
|
e5577e43f8 | ||
|
|
17c0463906 | ||
|
|
4168772904 | ||
|
|
44f2186749 | ||
|
|
0c918bcc3a | ||
|
|
0a8925dc75 | ||
|
|
a446597597 | ||
|
|
54354a2732 | ||
|
|
d94b8f08ab | ||
|
|
0d8189efeb | ||
|
|
00c886e426 | ||
|
|
551fc35439 | ||
|
|
9ff17c8d9d | ||
|
|
ec37732e99 | ||
|
|
8a414f32a8 | ||
|
|
bac06acb49 | ||
|
|
ae1e3c2a81 | ||
|
|
67940eb0f9 | ||
|
|
007aa8480e | ||
|
|
dedec10c58 | ||
|
|
75219e21be | ||
|
|
10f5964f8e | ||
|
|
a4a64d51c0 | ||
|
|
1014313d88 | ||
|
|
e486bb4c29 | ||
|
|
5c3d9ffb46 | ||
|
|
2e474fd8db | ||
|
|
b2b110ae1f | ||
|
|
68a34e0738 | ||
|
|
38fa575958 | ||
|
|
6cfeefe054 | ||
|
|
8007971a53 | ||
|
|
d66bd30fae | ||
|
|
3fa59b1b12 | ||
|
|
20e7aff393 | ||
|
|
4b7ce87f57 | ||
|
|
2075533468 | ||
|
|
a4ad5c8d11 | ||
|
|
35f2f56757 | ||
|
|
e6f4aa6a2f | ||
|
|
92fc62bb0d | ||
|
|
44b57a59f5 | ||
|
|
97b8e02bf5 | ||
|
|
5df42420cb | ||
|
|
0ede11a1b7 | ||
|
|
7d9c282db9 | ||
|
|
bc0e0813a4 | ||
|
|
f3aebb3001 | ||
|
|
800f966df9 | ||
|
|
e33df4dd8c | ||
|
|
96d9d810fd | ||
|
|
8707a1bc86 | ||
|
|
0c988a5fd4 | ||
|
|
b396ca771d | ||
|
|
a37dfcf961 | ||
|
|
31989740cd | ||
|
|
501191289b | ||
|
|
8971e92d78 | ||
|
|
0c96e79d0d | ||
|
|
0704c0f5e6 | ||
|
|
9cb190ebe7 | ||
|
|
667f84995c | ||
|
|
7a93fae6e4 | ||
|
|
0d6deca15c | ||
|
|
f54d7d46f2 | ||
|
|
8cf00ba5e1 | ||
|
|
ecc9c6bbd9 | ||
|
|
e11199f988 | ||
|
|
e9ed621178 |
@@ -45,8 +45,7 @@ before_build:
|
|||||||
- CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
|
- CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
|
||||||
- SET PATH=%PATH%;c:\qbt\qt5_32\bin;%CACHE_DIR%\jom;
|
- SET PATH=%PATH%;c:\qbt\qt5_32\bin;%CACHE_DIR%\jom;
|
||||||
# setup project
|
# setup project
|
||||||
- COPY /Y "%CACHE_DIR%\winconf.pri" "%REPO_DIR%"
|
- COPY /Y "%CACHE_DIR%\conf.pri" "%REPO_DIR%"
|
||||||
- COPY /Y "%CACHE_DIR%\winconf-msvc.pri" "%REPO_DIR%"
|
|
||||||
# workarounds
|
# workarounds
|
||||||
- MKLINK /J "c:\qbt\base" "%CACHE_DIR%\base"
|
- MKLINK /J "c:\qbt\base" "%CACHE_DIR%\base"
|
||||||
|
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,6 +22,7 @@ qrc_*.cpp
|
|||||||
ui_*.h
|
ui_*.h
|
||||||
*.moc
|
*.moc
|
||||||
src/lang/qbittorrent_*.qm
|
src/lang/qbittorrent_*.qm
|
||||||
|
src/webui/www/translations/webui_*.qm
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.qmake.stash
|
.qmake.stash
|
||||||
src/qbittorrent.app
|
src/qbittorrent.app
|
||||||
|
|||||||
79
.travis.yml
79
.travis.yml
@@ -3,7 +3,8 @@ language: cpp
|
|||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
osx_image: xcode7.3
|
|
||||||
|
dist: xenial
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -38,11 +39,6 @@ cache:
|
|||||||
directories:
|
directories:
|
||||||
- $HOME/hombebrew_cache
|
- $HOME/hombebrew_cache
|
||||||
|
|
||||||
# opt-in Ubuntu Trusty
|
|
||||||
dist: trusty
|
|
||||||
# container-based builds
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
coverity_scan:
|
coverity_scan:
|
||||||
project:
|
project:
|
||||||
@@ -54,34 +50,30 @@ addons:
|
|||||||
notification_email: sledgehammer999@qbittorrent.org
|
notification_email: sledgehammer999@qbittorrent.org
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
# sources list: https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
|
# sources list: https://github.com/travis-ci/apt-source-safelist/blob/master/ubuntu.json
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
#- boost-latest
|
|
||||||
- sourceline: 'ppa:qbittorrent-team/qbittorrent-stable'
|
- sourceline: 'ppa:qbittorrent-team/qbittorrent-stable'
|
||||||
- sourceline: 'ppa:beineri/opt-qt551-trusty'
|
|
||||||
- sourceline: 'ppa:adrozdoff/cmake'
|
|
||||||
packages:
|
packages:
|
||||||
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
# packages list: https://github.com/travis-ci/apt-package-safelist/blob/master/ubuntu-trusty
|
||||||
- [autoconf, automake, colormake]
|
- [autoconf, automake, colormake]
|
||||||
- [cmake, ninja-build]
|
- [ninja-build]
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
- [libboost-dev, libboost-system-dev]
|
- [libboost-dev, libboost-system-dev]
|
||||||
- libtorrent-rasterbar-dev
|
- libtorrent-rasterbar-dev
|
||||||
- [qt55base, qt55svg, qt55tools]
|
- [qtbase5-dev, qttools5-dev-tools, libqt5svg5-dev]
|
||||||
- [gcc-6, g++-6]
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
# only allow specific build for coverity scan, others will stop
|
# only allow specific build for coverity scan, others will stop
|
||||||
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" = "RC_1_0" -a "$gui" = true -a "$build_system" = "qmake" ]; then exit ; fi
|
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" = "RC_1_0" -a "$gui" = true -a "$build_system" = "qmake" ]; then exit ; fi
|
||||||
|
|
||||||
- shopt -s expand_aliases
|
- shopt -s expand_aliases
|
||||||
- alias make="colormake -j3" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
- alias make="colormake -j2" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
||||||
- qbt_path="$HOME/qbt_install"
|
- qbt_path="$HOME/qbt_install"
|
||||||
- |
|
- |
|
||||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
|
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
else
|
else
|
||||||
qbtconf="$qbtconf --prefix="$qbt_path""
|
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedefs -Wno-inconsistent-missing-override"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# options for specific branches
|
# options for specific branches
|
||||||
@@ -90,14 +82,6 @@ before_install:
|
|||||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
# setup virtual display for after_success target
|
# setup virtual display for after_success target
|
||||||
if [ "$gui" = true ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi ;
|
if [ "$gui" = true ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi ;
|
||||||
|
|
||||||
# Qt 5
|
|
||||||
PATH=/opt/qt55/bin:${PATH}
|
|
||||||
|
|
||||||
if [ "$build_system" = "cmake" ]; then
|
|
||||||
COMPILER_VERSION=6
|
|
||||||
export CXX="${CXX}-${COMPILER_VERSION}" CC="${CC}-${COMPILER_VERSION}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# print settings
|
# print settings
|
||||||
@@ -121,41 +105,24 @@ install:
|
|||||||
# dependencies
|
# dependencies
|
||||||
brew update > /dev/null
|
brew update > /dev/null
|
||||||
brew outdated "pkg-config" || brew upgrade "pkg-config"
|
brew outdated "pkg-config" || brew upgrade "pkg-config"
|
||||||
brew install colormake ccache zlib qt
|
brew install colormake ccache zlib qt openssl libtorrent-rasterbar
|
||||||
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
||||||
brew link --force zlib qt
|
brew link --force zlib qt
|
||||||
|
|
||||||
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.1.7+git20180422.3ede0b9c20+patched-configure.el_capitan.bottle.tar.gz
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy custom libtorrent bottle to homebrew's cache so it can find and install it
|
|
||||||
# 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.1.7+git20180422.3ede0b9c20+patched-configure.el_capitan.bottle.tar.gz" "$(brew --cache)"
|
|
||||||
brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb"
|
|
||||||
|
|
||||||
if [ "$build_system" = "cmake" ]; then
|
if [ "$build_system" = "cmake" ]; then
|
||||||
brew outdated cmake || brew upgrade cmake
|
brew outdated cmake || brew upgrade cmake
|
||||||
brew install ninja
|
brew install ninja
|
||||||
|
|
||||||
ln -s /usr/local/opt/qt/mkspecs /usr/local/mkspecs
|
sudo ln -s /usr/local/opt/qt/mkspecs /usr/local/mkspecs
|
||||||
ln -s /usr/local/opt/qt/plugins /usr/local/plugins
|
sudo ln -s /usr/local/opt/qt/plugins /usr/local/plugins
|
||||||
|
|
||||||
|
MY_CMAKE_OPENSSL_HINT="-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MY_CMAKE_OPENSSL_HINT="-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/"
|
|
||||||
fi
|
fi
|
||||||
- |
|
- |
|
||||||
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
|
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
|
||||||
export use_ccache=true
|
export use_ccache=true
|
||||||
|
ccache -M 512M
|
||||||
ccache -V && ccache --show-stats && ccache --zero-stats
|
ccache -V && ccache --show-stats && ccache --zero-stats
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -166,21 +133,15 @@ script:
|
|||||||
if [ "$build_system" = "cmake" ]; then
|
if [ "$build_system" = "cmake" ]; then
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -DGUI=${gui} -DCMAKE_INSTALL_PREFIX="$qbt_path" "$MY_CMAKE_OPENSSL_HINT" \
|
if [ "$gui" = "false" ]; then
|
||||||
|
DISABLE_GUI_OPTION="-DCMAKE_DISABLE_FIND_PACKAGE_Qt5Widgets=ON"
|
||||||
|
fi
|
||||||
|
cmake $DISABLE_GUI_OPTION -DCMAKE_INSTALL_PREFIX="$qbt_path" "$MY_CMAKE_OPENSSL_HINT" \
|
||||||
-G "Ninja" -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE ..
|
-G "Ninja" -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE ..
|
||||||
BUILD_TOOL="ninja"
|
BUILD_TOOL="ninja"
|
||||||
fi
|
fi
|
||||||
if [ "$build_system" = "qmake" ]; then
|
if [ "$build_system" = "qmake" ]; then
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$CXXFLAGS"
|
||||||
# For some reason for RC_1_1 we need to also specify the OpenSSL compiler/linker flags
|
|
||||||
# Homebrew doesn't symlink OpenSSL for security reasons
|
|
||||||
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --cflags openssl)" LDFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --libs openssl)"
|
|
||||||
sed -i "" -e "s/^\(CC.*&&\).*$/\1 $CC/" src/Makefile # workaround for Qt & ccache: https://bugreports.qt.io/browse/QTBUG-31034
|
|
||||||
sed -i "" -e "s/^\(CXX.*&&\).*$/\1 $CXX/" src/Makefile
|
|
||||||
sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs -Wno-inconsistent-missing-override/' src/Makefile
|
|
||||||
else
|
|
||||||
./bootstrap.sh && ./configure $qbtconf
|
|
||||||
fi
|
|
||||||
BUILD_TOOL="make"
|
BUILD_TOOL="make"
|
||||||
fi
|
fi
|
||||||
- $BUILD_TOOL && $BUILD_TOOL install
|
- $BUILD_TOOL && $BUILD_TOOL install
|
||||||
|
|||||||
12
.tx/config
12
.tx/config
@@ -10,10 +10,18 @@ type = QT
|
|||||||
minimum_perc = 23
|
minimum_perc = 23
|
||||||
mode = developer
|
mode = developer
|
||||||
|
|
||||||
|
|
||||||
[qbittorrent.qbittorrentdesktop_master]
|
[qbittorrent.qbittorrentdesktop_master]
|
||||||
source_file = src/icons/qBittorrent.desktop
|
source_file = dist/unix/org.qbittorrent.qBittorrent.desktop
|
||||||
source_lang = en
|
source_lang = en
|
||||||
type = DESKTOP
|
type = DESKTOP
|
||||||
minimum_perc = 23
|
minimum_perc = 23
|
||||||
mode = developer
|
mode = developer
|
||||||
|
|
||||||
|
[qbittorrent.qbittorrent_webui]
|
||||||
|
file_filter = src/webui/www/translations/webui_<lang>.ts
|
||||||
|
lang_map = pt: pt_PT
|
||||||
|
source_file = src/webui/www/translations/webui_en.ts
|
||||||
|
source_lang = en
|
||||||
|
type = QT
|
||||||
|
minimum_perc = 23
|
||||||
|
mode = developer
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||||
cmake_policy(VERSION 3.5)
|
|
||||||
|
message(AUTHOR_WARNING "If the build fails, please try the autotools/qmake method.")
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
|
||||||
include(FunctionReadVersion)
|
include(FunctionReadVersion)
|
||||||
@@ -25,32 +26,29 @@ add_definitions(-DQBT_VERSION_BUILD=${VER_BUILD})
|
|||||||
add_definitions(-DQBT_VERSION="v${PROJECT_VERSION}")
|
add_definitions(-DQBT_VERSION="v${PROJECT_VERSION}")
|
||||||
add_definitions(-DQBT_VERSION_2="${PROJECT_VERSION}")
|
add_definitions(-DQBT_VERSION_2="${PROJECT_VERSION}")
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
include(GNUInstallDirs)
|
||||||
include(GNUInstallDirs)
|
include(FeatureSummary)
|
||||||
endif (UNIX AND NOT APPLE)
|
|
||||||
|
# version requirements
|
||||||
|
set(requiredBoostVersion 1.35)
|
||||||
|
set(requiredQtVersion 5.5.1)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
include(winconf)
|
include(winconf)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
# we need options here, because they are used not only in "src" subdir, but in the "dist" dir too
|
|
||||||
include(CMakeDependentOption)
|
|
||||||
|
|
||||||
option(SYSTEM_QTSINGLEAPPLICATION
|
# we need options here, at the top level, because they are used not only in "src" subdir, but in the "dist" dir too
|
||||||
"Use the system qtsingleapplication library or shipped one otherwise")
|
include(CompileFeature)
|
||||||
|
|
||||||
option(GUI "Allows to disable GUI for headless running. Disables QtDBus and the GeoIP Database" ON)
|
|
||||||
|
|
||||||
option(WEBUI "Allows to disable the WebUI." ON)
|
|
||||||
|
|
||||||
option(STACKTRACE "Enable stacktrace feature" ON)
|
|
||||||
|
|
||||||
if (UNIX)
|
|
||||||
cmake_dependent_option(SYSTEMD "Install the systemd service file (headless only)" OFF
|
|
||||||
"NOT GUI" OFF)
|
|
||||||
cmake_dependent_option(DBUS "Enable use of QtDBus (GUI only)" ON "GUI" OFF)
|
|
||||||
endif(UNIX)
|
|
||||||
|
|
||||||
|
optional_compile_definitions(COUNTRIES_RESOLUTION FEATURE DESCRIPTION "Enable resolving peers IP addresses to countries"
|
||||||
|
DEFAULT ON DISABLED DISABLE_COUNTRIES_RESOLUTION)
|
||||||
|
optional_compile_definitions(STACKTRACE FEATURE DESCRIPTION "Enable stacktraces"
|
||||||
|
DEFAULT ON ENABLED STACKTRACE)
|
||||||
|
optional_compile_definitions(WEBUI FEATURE DESCRIPTION "Enables built-in HTTP server for headless use"
|
||||||
|
DEFAULT ON DISABLED DISABLE_WEBUI)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(dist)
|
add_subdirectory(dist)
|
||||||
|
|
||||||
|
feature_summary(DESCRIPTION "\nConfiguration results:" WHAT ALL)
|
||||||
|
|||||||
@@ -6,6 +6,31 @@ For programming languages other than C++ (e.g. JavaScript) used in this reposito
|
|||||||
**Note 2:** You can use the `uncrustify` program/tool to clean up any source file. Use it with the `uncrustify.cfg` configuration file found in the root folder.
|
**Note 2:** You can use the `uncrustify` program/tool to clean up any source file. Use it with the `uncrustify.cfg` configuration file found in the root folder.
|
||||||
**Note 3:** There is also a style for QtCreator but it doesn't cover all cases. In QtCreator `Tools->Options...->C++->Code Style->Import...` and choose the `codingStyleQtCreator.xml` file found in the root folder.
|
**Note 3:** There is also a style for QtCreator but it doesn't cover all cases. In QtCreator `Tools->Options...->C++->Code Style->Import...` and choose the `codingStyleQtCreator.xml` file found in the root folder.
|
||||||
|
|
||||||
|
### Table Of Contents
|
||||||
|
|
||||||
|
* [1. New lines & curly braces](#1-new-lines--curly-braces)
|
||||||
|
* [a. Function blocks, class/struct definitions, namespaces](#a-function-blocks-classstruct-definitions-namespaces)
|
||||||
|
* [b. Other code blocks](#b-other-code-blocks)
|
||||||
|
* [c. Blocks in switch's case labels](#c-blocks-in-switchs-case-labels)
|
||||||
|
* [d. If-else statements](#d-if-else-statements)
|
||||||
|
* [e. Single statement if blocks](#e-single-statement-if-blocks)
|
||||||
|
* [f. Acceptable conditions to omit braces](#f-acceptable-conditions-to-omit-braces)
|
||||||
|
* [g. Brace enclosed initializers](#g-brace-enclosed-initializers)
|
||||||
|
* [2. Indentation](#2-indentation)
|
||||||
|
* [3. File encoding and line endings](#3-file-encoding-and-line-endings)
|
||||||
|
* [4. Initialization lists](#4-initialization-lists)
|
||||||
|
* [5. Enums](#5-enums)
|
||||||
|
* [6. Names](#6-names)
|
||||||
|
* [a. Type names and namespaces](#a-type-names-and-namespaces)
|
||||||
|
* [b. Variable names](#b-variable-names)
|
||||||
|
* [c. Private member variable names](#c-private-member-variable-names)
|
||||||
|
* [7. Header inclusion order](#7-header-inclusion-order)
|
||||||
|
* [8. Include guard](#8-include-guard)
|
||||||
|
* [9. Misc](#9-misc)
|
||||||
|
* [10. Git commit message](#10-git-commit-message)
|
||||||
|
* [11. Not covered above](#11-not-covered-above)
|
||||||
|
---
|
||||||
|
|
||||||
### 1. New lines & curly braces ###
|
### 1. New lines & curly braces ###
|
||||||
|
|
||||||
#### a. Function blocks, class/struct definitions, namespaces ####
|
#### a. Function blocks, class/struct definitions, namespaces ####
|
||||||
@@ -165,11 +190,11 @@ QVariantMap map {{"key1", 5}, {"key2", 10}};
|
|||||||
### 2. Indentation ###
|
### 2. Indentation ###
|
||||||
4 spaces.
|
4 spaces.
|
||||||
|
|
||||||
### 3. File encoding and line endings. ###
|
### 3. File encoding and line endings ###
|
||||||
|
|
||||||
UTF-8 and Unix-like line ending (LF). Unless some platform specific files need other encodings/line endings.
|
UTF-8 and Unix-like line ending (LF). Unless some platform specific files need other encodings/line endings.
|
||||||
|
|
||||||
### 4. Initialization lists. ###
|
### 4. Initialization lists ###
|
||||||
Initialization lists should be vertical. This will allow for more easily readable diffs. The initialization colon should be indented and in its own line along with first argument. The rest of the arguments should be indented too and have the comma prepended.
|
Initialization lists should be vertical. This will allow for more easily readable diffs. The initialization colon should be indented and in its own line along with first argument. The rest of the arguments should be indented too and have the comma prepended.
|
||||||
```c++
|
```c++
|
||||||
myClass::myClass(int a, int b, int c, int d)
|
myClass::myClass(int a, int b, int c, int d)
|
||||||
@@ -182,7 +207,7 @@ myClass::myClass(int a, int b, int c, int d)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Enums. ###
|
### 5. Enums ###
|
||||||
Enums should be vertical. This will allow for more easily readable diffs. The members should be indented.
|
Enums should be vertical. This will allow for more easily readable diffs. The members should be indented.
|
||||||
```c++
|
```c++
|
||||||
enum Days
|
enum Days
|
||||||
@@ -197,7 +222,7 @@ enum Days
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Names. ###
|
### 6. Names ###
|
||||||
All names should be camelCased.
|
All names should be camelCased.
|
||||||
|
|
||||||
#### a. Type names and namespaces ####
|
#### a. Type names and namespaces ####
|
||||||
@@ -231,7 +256,7 @@ class MyClass
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7. Header inclusion order. ###
|
### 7. Header inclusion order ###
|
||||||
The headers should be placed in the following group order:
|
The headers should be placed in the following group order:
|
||||||
1. Module header (in .cpp)
|
1. Module header (in .cpp)
|
||||||
2. C++ Standard Library headers
|
2. C++ Standard Library headers
|
||||||
@@ -239,11 +264,11 @@ The headers should be placed in the following group order:
|
|||||||
4. Boost library headers
|
4. Boost library headers
|
||||||
5. Libtorrent headers
|
5. Libtorrent headers
|
||||||
6. Qt headers
|
6. Qt headers
|
||||||
7. qBittorrent own headers, starting from *base* headers.
|
7. qBittorrent's own headers, starting from the *base* headers.
|
||||||
|
|
||||||
The headers should be ordered alphabetically within each group.
|
The headers should be ordered alphabetically within each group.
|
||||||
If there are conditionals for the same header group, then put them at the bottom of the respective group.
|
If there are conditionals for the same header group, then put them at the bottom of the respective group.
|
||||||
If there are conditionals for the different header groups, then put them above of the "qBittorrent own headers" group.
|
If there are conditionals that contain headers from several different header groups, then put them above the "qBittorrent's own headers" group.
|
||||||
|
|
||||||
One exception is the header containing the library version (for example, QtGlobal), this particular header isn't constrained by the aforementioned order.
|
One exception is the header containing the library version (for example, QtGlobal), this particular header isn't constrained by the aforementioned order.
|
||||||
|
|
||||||
@@ -285,19 +310,19 @@ Example:
|
|||||||
#include <QFont>
|
#include <QFont>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// conditional for the different header groups
|
// conditional that contains headers from several different header groups
|
||||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// qBittorrent own headers
|
// qBittorrent's own headers
|
||||||
#include "base/bittorrent/infohash.h"
|
#include "base/bittorrent/infohash.h"
|
||||||
#include "anothermodule.h"
|
#include "anothermodule.h"
|
||||||
#include "ui_examplewidget.h"
|
#include "ui_examplewidget.h"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. Include guard. ###
|
### 8. Include guard ###
|
||||||
`#pragma once` should be used instead of "include guard" in new code:
|
`#pragma once` should be used instead of "include guard" in new code:
|
||||||
```c++
|
```c++
|
||||||
// examplewidget.h
|
// examplewidget.h
|
||||||
@@ -313,7 +338,7 @@ class ExampleWidget : public QWidget
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9. Misc. ###
|
### 9. Misc ###
|
||||||
|
|
||||||
* Line breaks for long lines with operation:
|
* Line breaks for long lines with operation:
|
||||||
|
|
||||||
|
|||||||
273
Changelog
273
Changelog
@@ -1,3 +1,276 @@
|
|||||||
|
* Thu Oct 31 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.9.1
|
||||||
|
- WINDOWS: Fix a problem with bigger dialogs due to wrong DPI reported by the system (Chocobo1)
|
||||||
|
|
||||||
|
* Sun Oct 27 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.9
|
||||||
|
- BUGFIX: Preserve relative order when moving to top/bottom in queue (Chocobo1)
|
||||||
|
- WINDOWS: Use real physical screen DPI (Chocobo1)
|
||||||
|
- WEBUI: Bump Web API version
|
||||||
|
|
||||||
|
* Mon Sep 23 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.8
|
||||||
|
- BUGFIX: Fix filename validation on non-Windows OS (Chocobo1)
|
||||||
|
- BUGFIX: ScanFolders/FileSystemWatcher now detect magnet files with case insensitivity in filename (Chocobo1)
|
||||||
|
- BUGFIX: Fix failed seeding after creating a torrent and auto-adding it to the session (Chocobo1)
|
||||||
|
|
||||||
|
* Sun Aug 04 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.7
|
||||||
|
- FEATURE: Add 12 hour and 24 hour speed graphs (dzmat)
|
||||||
|
- FEATURE: Change "Add new torrent" dialog to horizontal layout (Evgeny Lensky)
|
||||||
|
- BUGFIX: Fix messed up symbols in log (Chocobo1)
|
||||||
|
- BUGFIX: Fix incomplete file extension not applied for new torrents (Chocobo1)
|
||||||
|
- BUGFIX: Save updated resume data for completed torrents (Vladimir Golovnev (Glassez))
|
||||||
|
- BUGFIX: Fix requested torrent resume data handling (Vladimir Golovnev (Glassez))
|
||||||
|
- BUGFIX: Prevent command injection via "Run external program" function (Chocobo1)
|
||||||
|
- BUGFIX: Avoid race conditions when adding torrent (Vladimir Golovnev (Glassez))
|
||||||
|
- BUGFIX: Fix torrent checking issues (Vladimir Golovnev (Glassez))
|
||||||
|
- BUGFIX: Use proper log message when there are no error (Chocobo1)
|
||||||
|
- BUGFIX: Fix torrent properties not saved for paused torrents (Chocobo1)
|
||||||
|
- BUGFIX: Some improvements on qtsingleapplication code (Chocobo1)
|
||||||
|
- BUGFIX: Remove limits of "Disk cache expiry interval" setting (Chocobo1)
|
||||||
|
- BUGFIX: Remove upper limit of "Disk cache" setting (Chocobo1)
|
||||||
|
- BUGFIX: Fix crash when removing phantom tags (Chocobo1)
|
||||||
|
- BUGFIX: Improve handleFileErrorAlert error message (Chocobo1)
|
||||||
|
- BUGFIX: Fix updated save path not saved for paused torrents (Chocobo1)
|
||||||
|
- BUGFIX: Log save_resume_data_failed_alert (Chocobo1)
|
||||||
|
- BUGFIX: Don't remove parent directories (Chocobo1)
|
||||||
|
- BUGFIX: Properly remove empty leftover folders after rename (Chocobo1)
|
||||||
|
- BUGFIX: Focus behavior row in Options dialog (silverqx)
|
||||||
|
- BUGFIX: Fix unable to rename folder on Windows when same is used in different case(Chocobo1)
|
||||||
|
- BUGFIX: Fix unable to control add torrent dialogs when opened simultaneously (Chocobo1)
|
||||||
|
- BUGFIX: Disable "Upload mode" when start preloaded torrent (Vladimir Golovnev (Glassez))
|
||||||
|
- BUGFIX: Fix wrong comparison result when sorting items(Chocobo1)
|
||||||
|
- BUGFIX: Fix sequential downloading when redirected (Vladimir Golovnev (Glassez))
|
||||||
|
- BUGFIX: Fix typos (Chocobo1)
|
||||||
|
- BUGFIX: Fix assertion fail (Chocobo1)
|
||||||
|
- BUGFIX: Change number of time axis divisions from 5 to 6 for convenience (dzmat)
|
||||||
|
- BUGFIX: Don't turn window blank when closed to system tray (Ekin Dursun)
|
||||||
|
- WEBUI: Fix WebUI encoding of special characters (Thomas Piccirello)
|
||||||
|
- WEBUI: Change the speed unit from Bytes/s to KiB/s for the rate limiter(jerrymakesjelly)
|
||||||
|
- WEBUI: Fix '+' char not decoded to space correctly (Chocobo1)
|
||||||
|
- RSS: Ignore RSS articles with non-unique identifiers (Vladimir Golovnev (Glassez))
|
||||||
|
- RSS: Perform more RSS parsing in working thread (Vladimir Golovnev (Glassez))
|
||||||
|
- RSS: Download RSS enclosure element if no proper MIME type is found (Matan Bareket)
|
||||||
|
|
||||||
|
* Sun May 05 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.6
|
||||||
|
- BUGFIX: Force recheck multiple torrents one by one in all possible cases. Closes #9120 (glassez)
|
||||||
|
- BUGFIX: Don't query Google for tracker favicons, for privacy reasons (sledgehammer999)
|
||||||
|
- BUGFIX: Work around the crash occurred in QTimer. Closes #9985 (Chocobo1)
|
||||||
|
- BUGFIX: Increase the .torrent file download size limit to 100 MiB (thalieht)
|
||||||
|
- BUGFIX: Disable downloading tracker favicons by default. Works around reported crashes in Linux. Closes #9667 (Chocobo1)
|
||||||
|
- WEBUI: Separate URL components before percent-decoding. Allow special characters in query string parameters. Closes #9116 (glassez)
|
||||||
|
- WEBUI: Prevent login credential appearing in URL. Closes #10221 (Chocobo1)
|
||||||
|
- WEBUI: Display warning when Javascript is disabled (Chocobo1)
|
||||||
|
- WEBUI: Fix translatable strings (Chocobo1)
|
||||||
|
- WEBUI: Correctly handle '+' sign in x-www-form-urlencoded data. Closes #10451 (Chocobo1)
|
||||||
|
- WEBUI: Remove closed connections immediately. Closes #10487 (Chocobo1)
|
||||||
|
- WEBUI: Fix "Create subfolder" option is not working. Closes ##10392 (Chocobo1)
|
||||||
|
- SEARCH: Make num enter key work the same as return in searchjobwidget (thalieht)
|
||||||
|
- LINUX: Make window title bar icon work in Wayland (Peter Eszlari)
|
||||||
|
- LINUX: Update appdata.xml file (Chocobo1)
|
||||||
|
- MACOS: Fix progress bar drawing by using different style than native (Nick Korotysh)
|
||||||
|
- MACOS: Updated and cleaned up fields in Info.plist (Nick Korotysh)
|
||||||
|
- OTHER: Mention more translators in the about tab. Closes #10043 (sledgehammer999)
|
||||||
|
|
||||||
|
* Mon Dec 24 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.5
|
||||||
|
- FEATURE: Add checking_mem_usage option to AdvancedSettings (FranciscoPombal)
|
||||||
|
- FEATURE: Save torrents queue in separate file. Now a new file named 'queue' is created, saving on each line the infohash of each queued torrent in sorted order. (glassez)
|
||||||
|
- BUGFIX: Fix regression on resuming torrents without metadata (thalieht)
|
||||||
|
- BUGFIX: Reorder and rename Tracker list context menu option (Thomas Piccirello)
|
||||||
|
- BUGFIX: Rename Tracker List columns (Thomas Piccirello)
|
||||||
|
- BUGFIX: Show error message when Session failed to start (glassez)
|
||||||
|
- BUGFIX: Embedded tracker: Use ip parameter from tracker request if provided (Chocobo1)
|
||||||
|
- BUGFIX: Fix weekday names translations (Chocobo1)
|
||||||
|
- BUGFIX: Fix strings not translated (Chocobo1)
|
||||||
|
- WEBUI: Change qBittorrent exit message to HTML5 (Chocobo1)
|
||||||
|
- WEBUI: Revise CSP header (Chocobo1)
|
||||||
|
- WEBUI: Enforce referrer-policy in WebUI (Chocobo1)
|
||||||
|
- WEBUI: Add torrent name filtering to WebUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Send numeric status without translation (Thomas Piccirello)
|
||||||
|
- WEBUI: Add WebUI Trackers context menu (Thomas Piccirello)
|
||||||
|
- WEBUI: Add DHT, PeX, and LSD to WebUI Tracker list (Thomas Piccirello)
|
||||||
|
- WEBUI: Add additional Tracker columns to WebUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Bump Web API version
|
||||||
|
- WEBUI: Fix display bugs in WebUI Files tab. Remove <IE9 support (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix incorrect priority value sent from WebUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Set priority for multiple files in one WebAPI request (Thomas Piccirello)
|
||||||
|
- WEBUI: Match WebUI Peers table column order to GUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Fetch data less frequently when torrents tab isn't visible (Thomas Piccirello)
|
||||||
|
- WEBUI: Add Search tab to WebUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Add ability to pass urls to the webui download page (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix JavaScript error (Tom Piccirello)
|
||||||
|
- WEBUI: Disallow setting a blank alternative WebUI location (Thomas Piccirello)
|
||||||
|
- WEBUI: Add slow torrent options (Thomas Piccirello)
|
||||||
|
- WEBUI: Add "Use alternative Web UI" option (Thomas Piccirello)
|
||||||
|
- WEBUI: Add "Apply rate limit to peers on LAN" option (Thomas Piccirello)
|
||||||
|
- WEBUI: Add email "From" option (Thomas Piccirello)
|
||||||
|
- WEBUI: Set WebUI download options using set preferences (Thomas Piccirello)
|
||||||
|
- WEBUI: Show list of categories on WebUI download page (Thomas Piccirello)
|
||||||
|
- WEBUI: Hide WebUI text input for custom monitor save locations (Thomas Piccirello)
|
||||||
|
- WEBUI: Add "When adding a torrent" options (Thomas Piccirello)
|
||||||
|
- WEBUI: Add WebUI Auto TMM options (Thomas Piccirello)
|
||||||
|
- WEBUI: Add speed limit icons to WebUI Speed options (Thomas Piccirello)
|
||||||
|
- WEBUI: Add WebUI Random port button and proxy unencrypted password notice (Thomas Piccirello)
|
||||||
|
- WEBUI: Replace WebUI Options fixed-width labels (Thomas Piccirello)
|
||||||
|
- WEBUI: Reorder WebUI options to match GUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Allow WebUI sidebar to be collapsed (Thomas Piccirello)
|
||||||
|
- WEBUI: Show ellipsis when WebUI sidebar is too narrow (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix WebUI bug on override of Start Download option.Closes #9855. (Tom Piccirello)
|
||||||
|
- WEBUI: Fix missing words in WebUI (Chocobo1)
|
||||||
|
- WEBUI: Add SameSite attribute to WebUI session cookie (Thomas Piccirello)
|
||||||
|
- WEBUI: Put WebUI security related options into a groupbox (Chocobo1)
|
||||||
|
- WEBUI: Add option for WebUI Host header validation (Chocobo1)
|
||||||
|
- WEBUI: Show icon in WebUI sorted column (Thomas Piccirello)
|
||||||
|
- RSS: Keep track of REPACK/PROPER downloads. Closes #9898. (Stephen Dawkins)
|
||||||
|
- SEARCH: Only instantiate SearchPluginManager as needed (Thomas Piccirello)
|
||||||
|
- MACOS: Make file icon look like other macOS icons (Nick Korotysh)
|
||||||
|
- MACOS: Save option to start minimized in Mac (thalieht)
|
||||||
|
|
||||||
|
* Mon Nov 19 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.4
|
||||||
|
- FEATURE: Recognize *.ts files as previewable (silver)
|
||||||
|
- FEATURE: Allow to disable speed graphs (dzmat)
|
||||||
|
- FEATURE: Clear LineEdit on ESC (silverqx)
|
||||||
|
- BUGFIX: Fix divide-by-zero crash (Chocobo1)
|
||||||
|
- BUGFIX: Remove speed limit checkbox in Options dialog (Chocobo1)
|
||||||
|
- BUGFIX: Fix speed graph "high speeds" bug (dzmat)
|
||||||
|
- BUGFIX: Don't update torrent status unnecessarily (glassez)
|
||||||
|
- BUGFIX: Improve force recheck of paused torrent (glassez)
|
||||||
|
- BUGFIX: Restore torrent in two steps (glassez)
|
||||||
|
- BUGFIX: Improve scaling of speed graphs (dzmat)
|
||||||
|
- BUGFIX: Add isNetworkFileSystem() detection on Windows. This allows network mounts to be monitored correctly by polling timer. (Chocobo1)
|
||||||
|
- BUGFIX: Reduce horizontal graphs resolution. Improves perfomance. (dzmat)
|
||||||
|
- BUGFIX: Don't recheck just checked torrent (mj-p, glassez)
|
||||||
|
- BUGFIX: Add SMB2 magic number (Chocobo1)
|
||||||
|
- BUGFIX: Restore startup perfomance to v4.1.2 times. Needs at least libtorrent 1.1.10 (sledgehammer999)
|
||||||
|
- BUGFIX: Make strings actually translatable (sledgehammer999)
|
||||||
|
- WEBUI: Handle downloading .torrent file as success (Tom Piccirello)
|
||||||
|
- WEBUI: Fix Alternative Web UI to be available (glassez)
|
||||||
|
- WEBUI: Consider empty locale setting as not set (glassez)
|
||||||
|
- WEBUI: Add free disk space to WebUI status bar (Thomas Piccirello)
|
||||||
|
- WEBUI: Add WebUI search API controller (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix WebUI Auto TMM context menu bug (Thomas Piccirello)
|
||||||
|
- WEBUI: Use independent translation for WebUI (glassez)
|
||||||
|
- WEBUI: Add categories WebAPI (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix minor JavaScript defects (Thomas Piccirello)
|
||||||
|
- WEBUI: Add locale to js file path (Thomas Piccirello)
|
||||||
|
- WEBUI: Translate WebUI torrents Status column (Thomas Piccirello)
|
||||||
|
- WEBUI: Bump Web API version
|
||||||
|
- RSS: Allow to disable downloading REPACK/PROPER matches (Stephen Dawkins)
|
||||||
|
- RSS: Improve RSS Feed updating (glassez)
|
||||||
|
- SEARCH: Allow resizing search filter in search job (thalieht)
|
||||||
|
- SEARCH: Improve parser for search engine versions.txt (Chocobo1)
|
||||||
|
- SEARCH: Update Python URLs (Chocobo1)
|
||||||
|
- SEARCH: Fix asking to install Python (Chocobo1)
|
||||||
|
- SEARCH: Reformat python code to be compliant with PEP8 (Chocobo1)
|
||||||
|
- OTHER: cmake: restore out-of-source build (Eugene Shalygin)
|
||||||
|
- OTHER: cmake: cmake: use C++14 when available (Eugene Shalygin)
|
||||||
|
|
||||||
|
* Tue Sep 18 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.3
|
||||||
|
- FEATURE: Preselect name without extension when renaming files (thalieht)
|
||||||
|
- FEATURE: Allow setting seq & first/last from context menu without metadata (thalieht)
|
||||||
|
- BUGFIX: Show "N/A" if there is no scrape (thalieht)
|
||||||
|
- BUGFIX: Save option about tracker favicons under correct key (sledgehammer999)
|
||||||
|
- BUGFIX: When file data are unreachable pause torrent and show "Missing Files" status (temporary fix) (sledgehammer999)
|
||||||
|
- BUGFIX: Don't disable DHT when using force proxy (Thomas Piccirello)
|
||||||
|
- BUGFIX: Correctly save torrent queue position/state/priority changes in fastresume (glassez, thalieht, sledgehammer999)
|
||||||
|
- BUGFIX: Fix icon height/width ratio (Chocobo1)
|
||||||
|
- BUGFIX: Fix values sorted wrong in "Last Activity" column (Chocobo1)
|
||||||
|
- BUGFIX: Replace png icons with svg (Chocobo1)
|
||||||
|
- WEBUI: Allow WebUI sidebar filters to be hidden (Thomas Piccirello)
|
||||||
|
- WEBUI: Increase WebUI Options initial height (Thomas Piccirello)
|
||||||
|
- WEBUI: Adjust WebUI Options form alignment (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix WebUI unreachable issue (Chocobo1)
|
||||||
|
- WEBUI: Require torrent category creation to be explicit (Thomas Piccirello)
|
||||||
|
- WEBUI: Include category save path in web api sync data (Thomas Piccirello)
|
||||||
|
- WEBUI: Add save path and editing to WebUI new category dialog (Thomas Piccirello)
|
||||||
|
- WEBUI: Bump Web API version
|
||||||
|
- SEARCH: Refactor in searchjob to always color visited entries (thalieht)
|
||||||
|
- SEARCH: Set "enter" as shortcut to download the selected torrents in search job (thalieht)
|
||||||
|
- SEARCH: Add regex option in the search filter's context menu (thalieht)
|
||||||
|
- LINUX: Fix GUI scaling issue on Linux (Chocobo1)
|
||||||
|
- LINUX: Fix regression that broke installing desktop file (Eli Schwartz)
|
||||||
|
- OPENBSD: Better filesystem support for filewatcher (Elias M. Mariani)
|
||||||
|
|
||||||
|
* Sun Aug 12 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.2
|
||||||
|
- FEATURE: New options for "inhibit sleep" (Lukas Greib)
|
||||||
|
- FEATURE: Add option for regexps in the transferlist search filter's context menu (thalieht)
|
||||||
|
- FEATURE: Add async io threads option to AdvancedSettings (tjjh89017)
|
||||||
|
- FEATURE: Allow save resume interval to be disabled (Chocobo1)
|
||||||
|
- FEATURE: Add checkbox for recursive download dialog (Chocobo1)
|
||||||
|
- FEATURE: Add changelog link in program updater (Chocobo1)
|
||||||
|
- BUGFIX: Avoid allocating large memory when loading a .torrent file (Couchy)
|
||||||
|
- BUGFIX: Notify users on 1st time close/minimize to tray (sledgehammer999)
|
||||||
|
- BUGFIX: Fix I/O error after fetching magnet metadata (Chocobo1)
|
||||||
|
- BUGFIX: Never save resume data for already paused torrents (glassez)
|
||||||
|
- BUGFIX: Make ProgramUpdater upgrade to 64-bit qbt when running on 64-bit Windows (Chocobo1)
|
||||||
|
- BUGFIX: Put temporary files in qbt own temp folder (Chocobo1)
|
||||||
|
- BUGFIX: Avoid potentially setting the wrong piece priorities (Chocobo1)
|
||||||
|
- BUGFIX: Various code refactorings/improvements (Chocobo1, thalieht, glassez)
|
||||||
|
- BUGFIX: Add options "Download in sequential order" and "Download first and last pieces first" in AddNewTorrentDialog (Chocobo1)
|
||||||
|
- BUGFIX: Download favicon using appropriate protocol (glassez)
|
||||||
|
- BUGFIX: Apply proxy settings on DownloadManager creation (glassez)
|
||||||
|
- BUGFIX: Improve torrent initialization (glassez)
|
||||||
|
- BUGFIX: Save resume data on torrent change events (glassez)
|
||||||
|
- BUGFIX: Increase default resume data save interval (Chocobo1)
|
||||||
|
- BUGFIX: Work around crash when procesing recursive download. Closes #9086 (Chocobo1)
|
||||||
|
- BUGFIX: Reduce queries to python version (Chocobo1)
|
||||||
|
- BUGFIX: Disable certain mouse wheel events in Options dialog (Chocobo1)
|
||||||
|
- WEBUI: Send all rechecks in one request (Thomas Piccirello)
|
||||||
|
- WEBUI: Add WebUI Force Reannounce option (Thomas Piccirello)
|
||||||
|
- WEBUI: Create non-existing path in setLocationAction() (Goshik)
|
||||||
|
- WEBUI: Add WebUI support for Mac ⌘ (Command) key (Thomas Piccirello)
|
||||||
|
- WEBUI: Show current save path in 'Set location' window (Goshik)
|
||||||
|
- WEBUI: Fix WebUI cache behavior for css files (Chocobo1)
|
||||||
|
- WEBUI: Send Cache-Control header in WebUI responses (Chocobo1)
|
||||||
|
- WEBUI: Add form-action to CSP (Thomas Piccirello)
|
||||||
|
- WEBUI: Add upgrade-insecure-requests to CSP when HTTPS is enabled (Thomas Piccirello)
|
||||||
|
- WEBUI: Reset WebUI ban counter on login success (Chocobo1)
|
||||||
|
- WEBUI: Add logging messages in WebUI login action (Chocobo1)
|
||||||
|
- WEBUI: Add option to control CSRF protection (Chocobo1)
|
||||||
|
- WEBUI: Add option to control WebUI clickjacking protection (Chocobo1)
|
||||||
|
- RSS: Implement "Sequential downloading" feature. Closes #6835 (glassez)
|
||||||
|
- RSS: Don't use RSS feed URLs as base for file names. Closes #8399 (glassez)
|
||||||
|
- SEARCH: Add a name filter for search results (thalieht)
|
||||||
|
- SEARCH: Fix python version detection (Chocobo1)
|
||||||
|
- SEARCH: Clear python cache conditionally (Chocobo1)
|
||||||
|
- SEARCH: Properly normalize version string before parsing it (hannsen)
|
||||||
|
- WINDOWS: Turn on Control Flow Guard for MSVC builds (Chocobo1)
|
||||||
|
- MACOS: Replace deprecated function IOPMAssertionCreate() on macOS (Chocobo1)
|
||||||
|
- OTHER: Fix CMake build with QtSingleApplication. Fixes #9196 (Eugene Shalygin)
|
||||||
|
|
||||||
|
* Sun May 27 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.1
|
||||||
|
- FEATURE: Add 'Moving' state for torrents being relocated/moved (sledgehammer999)
|
||||||
|
- FEATURE: Show rechecking progress (sledgehammer999)
|
||||||
|
- FEATURE: Add option to remember last used save path (glassez)
|
||||||
|
- FEATURE: Torrent name is also renamed if the content was renamed in the "Add New Torrent" dialog (glassez)
|
||||||
|
- FEATURE: Relax behavior of "Download first and last piece first". It applies to all files and not only to the previewable. (Chocobo1)
|
||||||
|
- BUGFIX: Fix issues with translatable strings (Chocobo1)
|
||||||
|
- BUGFIX: Fix displayed tracker messages (Chocobo1)
|
||||||
|
- BUGFIX: Make settings file recovery more robust (Chocobo1)
|
||||||
|
- BUGFIX: Retry saving settings when operation failed (Chocobo1)
|
||||||
|
- BUGFIX: Log successful torrent move (sledgehammer999)
|
||||||
|
- BUGFIX: Fix deletion of old logs (sledgehammer999)
|
||||||
|
- BUGFIX: Delete non-commited fastresume files (sledgehammer999)
|
||||||
|
- BUGFIX: Don't migrate torrents that have newer fastresumes (sledgehammer999)
|
||||||
|
- BUGFIX: Fix adding multiple torrents at once from WebUI (glassez)
|
||||||
|
- BUGFIX: Improve "Run External Program" behavior. On Windows, a backslash isn't appended to paths from path variables (Chocobo1)
|
||||||
|
- BUGFIX: Suppress multiple I/O errors for the same torrent (sledgehammer999)
|
||||||
|
- BUGFIX: Replace raster qbt logo with vector version (Chocobo1)
|
||||||
|
- WEBUI: Fix wrong API method names (glassez)
|
||||||
|
- WEBUI: Filter torrent info endpoint by hashes (Marcel Petersen)
|
||||||
|
- WEBUI: Fix invalid API calls in WebUI (glassez)
|
||||||
|
- WEBUI: Improve legacy API params handling (glassez)
|
||||||
|
- WEBUI: Fix params handling for some legacy API methods (glassez)
|
||||||
|
- WEBUI: Apply locale changes immediately in WebUI (Chocobo1)
|
||||||
|
- WEBUI: Use 32px icons for favicon (Chocobo1)
|
||||||
|
- WEBUI/RSS: Properly set RSS settings via API (glassez)
|
||||||
|
- RSS: Fix auto-downloading rule when Smart filter with regular Episode filter are used (glassez)
|
||||||
|
- RSS: Make "Ignoring days" to behave like other filters (glassez)
|
||||||
|
- RSS: Place "Use Smart Episode Filter" more correctly (glassez)
|
||||||
|
- RSS: Use RSS feed update time as a fallback (glassez)
|
||||||
|
- COSMETIC: Fix Stats dialog size (sledgehammer999)
|
||||||
|
- MACOS: Fix GUI scaling factor on macOS (Chocobo1)
|
||||||
|
- WINDOWS: Update icons (adem4ik)
|
||||||
|
- LINUX: Fix open destination folder with Nautilus > 3.28 (Evgeny Lensky)
|
||||||
|
- OTHER: Code improvements and refactoring (thalieht, Nick Korotysh, Chocobo1)
|
||||||
|
|
||||||
* Sat May 05 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.0
|
* Sat May 05 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.0
|
||||||
- FEATURE: Add "Coalesce reads & writes" checkbox in advanced options (Chocobo1)
|
- FEATURE: Add "Coalesce reads & writes" checkbox in advanced options (Chocobo1)
|
||||||
- FEATURE: Smart Filter for RSS (Stephen Dawkins)
|
- FEATURE: Smart Filter for RSS (Stephen Dawkins)
|
||||||
|
|||||||
49
INSTALL
49
INSTALL
@@ -1,54 +1,49 @@
|
|||||||
qBittorrent - A BitTorrent client in C++ / Qt4
|
qBittorrent - A BitTorrent client in C++ / Qt
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
1) Compile and install qBittorrent with Qt4 Graphical Interface
|
1) Compile and install qBittorrent with Qt graphical interface
|
||||||
|
|
||||||
$ ./configure
|
$ ./configure
|
||||||
$ make && make install
|
$ make && make install
|
||||||
$ qbittorrent
|
$ qbittorrent
|
||||||
|
|
||||||
will install and execute qBittorrent hopefully without any problems.
|
will install and execute qBittorrent.
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- Qt >= 4.6.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional)
|
- Qt >= 5.5.1
|
||||||
|
|
||||||
- pkg-config executable
|
- pkg-config
|
||||||
|
|
||||||
- libtorrent-rasterbar by Arvid Norberg (>= 1.0.6)
|
- libtorrent-rasterbar >= 1.0.6 (by Arvid Norberg)
|
||||||
-> http://www.libtorrent.net
|
* https://www.libtorrent.org/
|
||||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
* Be careful: another library (the one used by rTorrent) uses a similar name
|
||||||
|
|
||||||
- libboost >= 1.35.x (libboost-system)
|
- Boost >= 1.35
|
||||||
|
|
||||||
- python >= 2.3 (needed by search engine)
|
- Python >= 2.7.9 / 3.3.0 (optional, runtime only)
|
||||||
* Run time only dependency
|
* Required by the internal search engine
|
||||||
|
|
||||||
- geoip-database (optional)
|
2) Compile and install qBittorrent without Qt graphical interface
|
||||||
* If qBittorrent cannot find this database, it will try to resolve countries using the Internet but it will be a lot slower.
|
|
||||||
* Run time only dependency
|
|
||||||
|
|
||||||
2) Compile and install qBittorrent without Qt4 Graphical interface
|
|
||||||
|
|
||||||
$ ./configure --disable-gui
|
$ ./configure --disable-gui
|
||||||
$ make && make install
|
$ make && make install
|
||||||
$ qbittorrent
|
$ qbittorrent-nox
|
||||||
|
|
||||||
will install and execute qBittorrent hopefully without any problems.
|
will install and execute qBittorrent.
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- Qt >= 4.4.0 (libqt-devel, libqtcore, libqtnetwork)
|
- Qt >= 5.5.1
|
||||||
|
|
||||||
- pkg-config executable
|
- pkg-config
|
||||||
|
|
||||||
- libtorrent-rasterbar by Arvid Norberg (>= v1.0.6)
|
- libtorrent-rasterbar >= 1.0.6 (by Arvid Norberg)
|
||||||
-> http://www.libtorrent.net
|
* https://www.libtorrent.org/
|
||||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
* Be careful: another library (the one used by rTorrent) uses a similar name
|
||||||
|
|
||||||
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
|
|
||||||
|
|
||||||
|
- Boost >= 1.35
|
||||||
|
|
||||||
DOCUMENTATION:
|
DOCUMENTATION:
|
||||||
Please note that there is a documentation with a "compiling howto" at http://wiki.qbittorrent.org.
|
Please note that there is a "Compilation" section at http://wiki.qbittorrent.org.
|
||||||
|
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
Christophe Dumez <chris@qbittorrent.org>
|
sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ It aims to be a good alternative to all other bittorrent clients
|
|||||||
out there. qBittorrent is fast, stable and provides unicode
|
out there. qBittorrent is fast, stable and provides unicode
|
||||||
support as well as many features.
|
support as well as many features.
|
||||||
|
|
||||||
This product includes GeoLite data created by MaxMind, available from
|
The free [IP to Country Lite database](https://db-ip.com/db/download/ip-to-country-lite) by [DB-IP](https://db-ip.com/) is used for resolving the countries of peers. The database is licensed under the [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).
|
||||||
https://www.maxmind.com/
|
|
||||||
|
|
||||||
### Installation:
|
### Installation:
|
||||||
For installation, follow the instructions from INSTALL file, but simple:
|
For installation, follow the instructions from INSTALL file, but simple:
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Wrapper for compilers which do not understand '-c -o'.
|
# Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
|
||||||
scriptversion=2012-10-14.11; # UTC
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
|
||||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC
|
|||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
@@ -255,7 +255,8 @@ EOF
|
|||||||
echo "compile $scriptversion"
|
echo "compile $scriptversion"
|
||||||
exit $?
|
exit $?
|
||||||
;;
|
;;
|
||||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||||
|
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||||
func_cl_wrapper "$@" # Doesn't return...
|
func_cl_wrapper "$@" # Doesn't return...
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -339,9 +340,9 @@ exit $ret
|
|||||||
# Local Variables:
|
# Local Variables:
|
||||||
# mode: shell-script
|
# mode: shell-script
|
||||||
# sh-indentation: 2
|
# sh-indentation: 2
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
# time-stamp-start: "scriptversion="
|
# time-stamp-start: "scriptversion="
|
||||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
# time-stamp-time-zone: "UTC"
|
# time-stamp-time-zone: "UTC0"
|
||||||
# time-stamp-end: "; # UTC"
|
# time-stamp-end: "; # UTC"
|
||||||
# End:
|
# End:
|
||||||
|
|||||||
966
build-aux/config.guess
vendored
966
build-aux/config.guess
vendored
File diff suppressed because it is too large
Load Diff
2770
build-aux/config.sub
vendored
2770
build-aux/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# install - install a program, script, or datafile
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
scriptversion=2013-12-25.23; # UTC
|
scriptversion=2018-03-11.20; # UTC
|
||||||
|
|
||||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
@@ -271,15 +271,18 @@ do
|
|||||||
fi
|
fi
|
||||||
dst=$dst_arg
|
dst=$dst_arg
|
||||||
|
|
||||||
# If destination is a directory, append the input filename; won't work
|
# If destination is a directory, append the input filename.
|
||||||
# if double slashes aren't ignored.
|
|
||||||
if test -d "$dst"; then
|
if test -d "$dst"; then
|
||||||
if test "$is_target_a_directory" = never; then
|
if test "$is_target_a_directory" = never; then
|
||||||
echo "$0: $dst_arg: Is a directory" >&2
|
echo "$0: $dst_arg: Is a directory" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
dstdir=$dst
|
dstdir=$dst
|
||||||
dst=$dstdir/`basename "$src"`
|
dstbase=`basename "$src"`
|
||||||
|
case $dst in
|
||||||
|
*/) dst=$dst$dstbase;;
|
||||||
|
*) dst=$dst/$dstbase;;
|
||||||
|
esac
|
||||||
dstdir_status=0
|
dstdir_status=0
|
||||||
else
|
else
|
||||||
dstdir=`dirname "$dst"`
|
dstdir=`dirname "$dst"`
|
||||||
@@ -288,6 +291,11 @@ do
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
*/) dstdirslash=$dstdir;;
|
||||||
|
*) dstdirslash=$dstdir/;;
|
||||||
|
esac
|
||||||
|
|
||||||
obsolete_mkdir_used=false
|
obsolete_mkdir_used=false
|
||||||
|
|
||||||
if test $dstdir_status != 0; then
|
if test $dstdir_status != 0; then
|
||||||
@@ -324,34 +332,43 @@ do
|
|||||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
# Note that $RANDOM variable is not portable (e.g. dash); Use it
|
||||||
|
# here however when possible just to lower collision chance.
|
||||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
|
||||||
|
|
||||||
|
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||||
|
|
||||||
|
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||||
|
# directly in world-writeable /tmp, make sure that the '$tmpdir'
|
||||||
|
# directory is successfully created first before we actually test
|
||||||
|
# 'mkdir -p' feature.
|
||||||
if (umask $mkdir_umask &&
|
if (umask $mkdir_umask &&
|
||||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||||
then
|
then
|
||||||
if test -z "$dir_arg" || {
|
if test -z "$dir_arg" || {
|
||||||
# Check for POSIX incompatibilities with -m.
|
# Check for POSIX incompatibilities with -m.
|
||||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
# other-writable bit of parent directory when it shouldn't.
|
# other-writable bit of parent directory when it shouldn't.
|
||||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
test_tmpdir="$tmpdir/a"
|
||||||
|
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||||
case $ls_ld_tmpdir in
|
case $ls_ld_tmpdir in
|
||||||
d????-?r-*) different_mode=700;;
|
d????-?r-*) different_mode=700;;
|
||||||
d????-?--*) different_mode=755;;
|
d????-?--*) different_mode=755;;
|
||||||
*) false;;
|
*) false;;
|
||||||
esac &&
|
esac &&
|
||||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
then posix_mkdir=:
|
then posix_mkdir=:
|
||||||
fi
|
fi
|
||||||
rmdir "$tmpdir/d" "$tmpdir"
|
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||||
else
|
else
|
||||||
# Remove any dirs left behind by ancient mkdir implementations.
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||||
fi
|
fi
|
||||||
trap '' 0;;
|
trap '' 0;;
|
||||||
esac;;
|
esac;;
|
||||||
@@ -427,8 +444,8 @@ do
|
|||||||
else
|
else
|
||||||
|
|
||||||
# Make a couple of temp file names in the proper directory.
|
# Make a couple of temp file names in the proper directory.
|
||||||
dsttmp=$dstdir/_inst.$$_
|
dsttmp=${dstdirslash}_inst.$$_
|
||||||
rmtmp=$dstdir/_rm.$$_
|
rmtmp=${dstdirslash}_rm.$$_
|
||||||
|
|
||||||
# Trap to clean up those temp files at exit.
|
# Trap to clean up those temp files at exit.
|
||||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
@@ -493,9 +510,9 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Local variables:
|
# Local variables:
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
# time-stamp-start: "scriptversion="
|
# time-stamp-start: "scriptversion="
|
||||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
# time-stamp-time-zone: "UTC"
|
# time-stamp-time-zone: "UTC0"
|
||||||
# time-stamp-end: "; # UTC"
|
# time-stamp-end: "; # UTC"
|
||||||
# End:
|
# End:
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Common wrapper for a few potentially missing GNU programs.
|
# Common wrapper for a few potentially missing GNU programs.
|
||||||
|
|
||||||
scriptversion=2013-10-28.13; # UTC
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,7 +17,7 @@ scriptversion=2013-10-28.13; # UTC
|
|||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
@@ -101,9 +101,9 @@ else
|
|||||||
exit $st
|
exit $st
|
||||||
fi
|
fi
|
||||||
|
|
||||||
perl_URL=http://www.perl.org/
|
perl_URL=https://www.perl.org/
|
||||||
flex_URL=http://flex.sourceforge.net/
|
flex_URL=https://github.com/westes/flex
|
||||||
gnu_software_URL=http://www.gnu.org/software
|
gnu_software_URL=https://www.gnu.org/software
|
||||||
|
|
||||||
program_details ()
|
program_details ()
|
||||||
{
|
{
|
||||||
@@ -207,9 +207,9 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
|||||||
exit $st
|
exit $st
|
||||||
|
|
||||||
# Local variables:
|
# Local variables:
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
# time-stamp-start: "scriptversion="
|
# time-stamp-start: "scriptversion="
|
||||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
# time-stamp-time-zone: "UTC"
|
# time-stamp-time-zone: "UTC0"
|
||||||
# time-stamp-end: "; # UTC"
|
# time-stamp-end: "; # UTC"
|
||||||
# End:
|
# End:
|
||||||
|
|||||||
22
cmake/Modules/CompileFeature.cmake
Normal file
22
cmake/Modules/CompileFeature.cmake
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Helper function for coupling add_feature_info(), option(), and add_definitions()
|
||||||
|
|
||||||
|
function(optional_compile_definitions _name)
|
||||||
|
set(options FEATURE)
|
||||||
|
set(oneValueArgs DESCRIPTION DEFAULT)
|
||||||
|
set(multiValueArgs ENABLED DISABLED)
|
||||||
|
cmake_parse_arguments(OCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
option(${_name} "${OCD_DESCRIPTION}" ${OCD_DEFAULT})
|
||||||
|
if (${${_name}})
|
||||||
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY COMPILE_DEFINITIONS ${OCD_ENABLED})
|
||||||
|
else()
|
||||||
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY COMPILE_DEFINITIONS ${OCD_DISABLED})
|
||||||
|
endif()
|
||||||
|
if(${OCD_FEATURE})
|
||||||
|
add_feature_info(${_name} ${_name} "${OCD_DESCRIPTION}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
macro(feature_option _name _description _default)
|
||||||
|
option(${_name} "${_description}" ${_default})
|
||||||
|
add_feature_info(${_name} ${_name} "${_description}")
|
||||||
|
endmacro()
|
||||||
@@ -99,6 +99,7 @@ list(FIND LibtorrentRasterbar_DEFINITIONS -DTORRENT_USE_OPENSSL LibtorrentRaster
|
|||||||
if(LibtorrentRasterbar_ENCRYPTION_INDEX GREATER -1)
|
if(LibtorrentRasterbar_ENCRYPTION_INDEX GREATER -1)
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||||
|
list(APPEND LibtorrentRasterbar_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}")
|
||||||
set(LibtorrentRasterbar_OPENSSL_ENABLED ON)
|
set(LibtorrentRasterbar_OPENSSL_ENABLED ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -113,10 +114,10 @@ mark_as_advanced(LibtorrentRasterbar_INCLUDE_DIR LibtorrentRasterbar_LIBRARY
|
|||||||
LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES
|
LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES
|
||||||
LibtorrentRasterbar_ENCRYPTION_INDEX)
|
LibtorrentRasterbar_ENCRYPTION_INDEX)
|
||||||
|
|
||||||
if (LibtorrentRasterbar_FOUND AND NOT TARGET LibtorrentRasterbar::LibTorrent)
|
if (LibtorrentRasterbar_FOUND AND NOT TARGET LibtorrentRasterbar::torrent-rasterbar)
|
||||||
add_library(LibtorrentRasterbar::LibTorrent UNKNOWN IMPORTED)
|
add_library(LibtorrentRasterbar::torrent-rasterbar UNKNOWN IMPORTED)
|
||||||
|
|
||||||
set_target_properties(LibtorrentRasterbar::LibTorrent PROPERTIES
|
set_target_properties(LibtorrentRasterbar::torrent-rasterbar PROPERTIES
|
||||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
||||||
IMPORTED_LOCATION "${LibtorrentRasterbar_LIBRARY}"
|
IMPORTED_LOCATION "${LibtorrentRasterbar_LIBRARY}"
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${LibtorrentRasterbar_INCLUDE_DIRS}"
|
INTERFACE_INCLUDE_DIRECTORIES "${LibtorrentRasterbar_INCLUDE_DIRS}"
|
||||||
|
|||||||
@@ -1,94 +1,79 @@
|
|||||||
# - Try to find the QtSingleApplication includes and library
|
# - Try to find the QtSingleApplication includes and library
|
||||||
# which defines
|
# which defines
|
||||||
#
|
#
|
||||||
# QTSINGLEAPPLICATION_FOUND - system has QtSingleApplication
|
# QtSingleApplication_FOUND - system has QtSingleApplication
|
||||||
# QTSINGLEAPPLICATION_INCLUDE_DIR - where to find header QtSingleApplication
|
# QtSingleApplication_INCLUDE_DIR - where to find header QtSingleApplication
|
||||||
# QTSINGLEAPPLICATION_LIBRARIES - the libraries to link against to use QtSingleApplication
|
# QtSingleApplication_LIBRARIES - the libraries to link against to use QtSingleApplication
|
||||||
# QTSINGLEAPPLICATION_LIBRARY - where to find the QtSingleApplication library (not for general use)
|
# QtSingleApplication_LIBRARY - where to find the QtSingleApplication library (not for general use)
|
||||||
|
|
||||||
# copyright (c) 2013 TI_Eugene ti.eugene@gmail.com
|
# copyright (c) 2013 TI_Eugene ti.eugene@gmail.com
|
||||||
#
|
#
|
||||||
# Redistribution and use is allowed according to the terms of the FreeBSD license.
|
# Redistribution and use is allowed according to the terms of the FreeBSD license.
|
||||||
|
|
||||||
SET(QTSINGLEAPPLICATION_FOUND FALSE)
|
SET(QtSingleApplication_FOUND FALSE)
|
||||||
|
|
||||||
IF(QT4_FOUND)
|
if (Qt5Widgets_FOUND)
|
||||||
message(STATUS "Looking for Qt4 single application library")
|
set(_includeFileName qtsingleapplication.h)
|
||||||
FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication
|
else()
|
||||||
# standard locations
|
set(_includeFileName qtsinglecoreapplication.h)
|
||||||
/usr/include
|
endif()
|
||||||
/usr/include/QtSolutions
|
|
||||||
# qt4 location except mac's frameworks
|
|
||||||
"${QT_INCLUDE_DIR}/QtSolutions"
|
|
||||||
# mac's frameworks
|
|
||||||
${FRAMEWORK_INCLUDE_DIR}/QtSolutions
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(QTSINGLEAPPLICATION_NAMES ${QTSINGLEAPPLICATION_NAMES}
|
FOREACH(TOP_INCLUDE_PATH in ${Qt5Core_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR})
|
||||||
QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6)
|
FIND_PATH(QtSingleApplication_INCLUDE_DIR ${_includeFileName} ${TOP_INCLUDE_PATH}/QtSolutions)
|
||||||
FIND_LIBRARY(QTSINGLEAPPLICATION_LIBRARY
|
|
||||||
NAMES ${QTSINGLEAPPLICATION_NAMES}
|
|
||||||
PATHS ${QT_LIBRARY_DIR}
|
|
||||||
)
|
|
||||||
ELSEIF(Qt5Core_FOUND)
|
|
||||||
message(STATUS "Looking for Qt5 single application library")
|
|
||||||
FOREACH(TOP_INCLUDE_PATH in ${Qt5Core_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR})
|
|
||||||
FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication ${TOP_INCLUDE_PATH}/QtSolutions)
|
|
||||||
|
|
||||||
IF(QTSINGLEAPPLICATION_INCLUDE_DIR)
|
IF(QtSingleApplication_INCLUDE_DIR)
|
||||||
BREAK()
|
BREAK()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
|
|
||||||
SET(QTSINGLEAPPLICATION_NAMES ${QTSINGLEAPPLICATION_NAMES}
|
SET(QtSingleApplication_NAMES ${QtSingleApplication_NAMES}
|
||||||
Qt5Solutions_SingleApplication-2.6 libQt5Solutions_SingleApplication-2.6
|
Qt5Solutions_SingleApplication-2.6 libQt5Solutions_SingleApplication-2.6
|
||||||
QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6)
|
QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6)
|
||||||
GET_TARGET_PROPERTY(_QT5_CORELIBRARY Qt5::Core LOCATION)
|
GET_TARGET_PROPERTY(_QT5_CORELIBRARY Qt5::Core LOCATION)
|
||||||
GET_FILENAME_COMPONENT(_QT5_CORELIBRARYPATH ${_QT5_CORELIBRARY} PATH)
|
GET_FILENAME_COMPONENT(_QT5_CORELIBRARYPATH ${_QT5_CORELIBRARY} PATH)
|
||||||
|
|
||||||
FIND_LIBRARY(QTSINGLEAPPLICATION_LIBRARY
|
FIND_LIBRARY(QtSingleApplication_LIBRARY
|
||||||
NAMES ${QTSINGLEAPPLICATION_NAMES}
|
NAMES ${QtSingleApplication_NAMES}
|
||||||
PATHS ${_QT5_CORELIBRARYPATH}
|
PATHS ${_QT5_CORELIBRARYPATH}
|
||||||
)
|
)
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF (QTSINGLEAPPLICATION_LIBRARY AND QTSINGLEAPPLICATION_INCLUDE_DIR)
|
IF (QtSingleApplication_LIBRARY AND QtSingleApplication_INCLUDE_DIR)
|
||||||
|
|
||||||
SET(QTSINGLEAPPLICATION_LIBRARIES ${QTSINGLEAPPLICATION_LIBRARY})
|
SET(QtSingleApplication_LIBRARIES ${QtSingleApplication_LIBRARY})
|
||||||
SET(QTSINGLEAPPLICATION_FOUND TRUE)
|
SET(QtSingleApplication_FOUND TRUE)
|
||||||
|
|
||||||
IF (CYGWIN)
|
IF (CYGWIN)
|
||||||
IF(BUILD_SHARED_LIBS)
|
IF(BUILD_SHARED_LIBS)
|
||||||
# No need to define QTSINGLEAPPLICATION_USE_DLL here, because it's default for Cygwin.
|
# No need to define QtSingleApplication_USE_DLL here, because it's default for Cygwin.
|
||||||
ELSE(BUILD_SHARED_LIBS)
|
ELSE(BUILD_SHARED_LIBS)
|
||||||
SET (QTSINGLEAPPLICATION_DEFINITIONS -DQTSINGLEAPPLICATION_STATIC)
|
SET (QtSingleApplication_DEFINITIONS -DQTSINGLEAPPLICATION_STATIC)
|
||||||
ENDIF(BUILD_SHARED_LIBS)
|
ENDIF(BUILD_SHARED_LIBS)
|
||||||
ENDIF (CYGWIN)
|
ENDIF (CYGWIN)
|
||||||
|
|
||||||
ENDIF (QTSINGLEAPPLICATION_LIBRARY AND QTSINGLEAPPLICATION_INCLUDE_DIR)
|
ENDIF (QtSingleApplication_LIBRARY AND QtSingleApplication_INCLUDE_DIR)
|
||||||
|
|
||||||
IF (QTSINGLEAPPLICATION_FOUND)
|
IF (QtSingleApplication_FOUND)
|
||||||
IF (NOT QtSingleApplication_FIND_QUIETLY)
|
IF (NOT QtSingleApplication_FIND_QUIETLY)
|
||||||
MESSAGE(STATUS "Found QtSingleApplication: ${QTSINGLEAPPLICATION_LIBRARY}")
|
MESSAGE(STATUS "Found QtSingleApplication: ${QtSingleApplication_LIBRARY}")
|
||||||
MESSAGE(STATUS " includes: ${QTSINGLEAPPLICATION_INCLUDE_DIR}")
|
MESSAGE(STATUS " includes: ${QtSingleApplication_INCLUDE_DIR}")
|
||||||
ENDIF (NOT QtSingleApplication_FIND_QUIETLY)
|
ENDIF (NOT QtSingleApplication_FIND_QUIETLY)
|
||||||
ELSE (QTSINGLEAPPLICATION_FOUND)
|
if(NOT TARGET QtSingleApplication::QtSingleApplication)
|
||||||
|
add_library(QtSingleApplication::QtSingleApplication UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${QtSingleApplication_INCLUDE_DIR}"
|
||||||
|
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${QtSingleApplication_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
if(EXISTS "${QtSingleApplication_LIBRARY}")
|
||||||
|
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
||||||
|
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
||||||
|
IMPORTED_LOCATION "${QtSingleApplication_LIBRARY}")
|
||||||
|
endif()
|
||||||
|
endif(NOT TARGET QtSingleApplication::QtSingleApplication)
|
||||||
|
|
||||||
|
ELSE (QtSingleApplication_FOUND)
|
||||||
IF (QtSingleApplication_FIND_REQUIRED)
|
IF (QtSingleApplication_FIND_REQUIRED)
|
||||||
MESSAGE(FATAL_ERROR "Could not find QtSingleApplication library")
|
MESSAGE(FATAL_ERROR "Could not find QtSingleApplication library")
|
||||||
ENDIF (QtSingleApplication_FIND_REQUIRED)
|
ENDIF (QtSingleApplication_FIND_REQUIRED)
|
||||||
ENDIF (QTSINGLEAPPLICATION_FOUND)
|
ENDIF (QtSingleApplication_FOUND)
|
||||||
|
|
||||||
MARK_AS_ADVANCED(QTSINGLEAPPLICATION_INCLUDE_DIR QTSINGLEAPPLICATION_LIBRARY)
|
MARK_AS_ADVANCED(QtSingleApplication_INCLUDE_DIR QtSingleApplication_LIBRARY)
|
||||||
|
|
||||||
if(NOT TARGET QtSingleApplication::QtSingleApplication)
|
|
||||||
add_library(QtSingleApplication::QtSingleApplication UNKNOWN IMPORTED)
|
|
||||||
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}"
|
|
||||||
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}"
|
|
||||||
)
|
|
||||||
if(EXISTS "${QTSINGLEAPPLICATION_LIBRARY}")
|
|
||||||
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
|
||||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
|
||||||
IMPORTED_LOCATION "${QTSINGLEAPPLICATION_LIBRARY}")
|
|
||||||
endif()
|
|
||||||
endif(NOT TARGET QtSingleApplication::QtSingleApplication)
|
|
||||||
|
|||||||
@@ -11,18 +11,17 @@ macro(qbt_set_compiler_options)
|
|||||||
#-Wshadow -Wconversion ?
|
#-Wshadow -Wconversion ?
|
||||||
set(_GCC_COMMON_C_AND_CXX_FLAGS "-Wall -Wextra"
|
set(_GCC_COMMON_C_AND_CXX_FLAGS "-Wall -Wextra"
|
||||||
"-Wfloat-equal -Wcast-qual -Wcast-align"
|
"-Wfloat-equal -Wcast-qual -Wcast-align"
|
||||||
"-Wsign-conversion -Winvalid-pch -Werror=return-type -Wno-long-long"
|
"-Wsign-conversion -Winvalid-pch -Wno-long-long"
|
||||||
# -fstack-protector-all
|
#"-fstack-protector-all"
|
||||||
"-Werror -Wno-error=deprecated-declarations"
|
#"-Werror -Wno-error=deprecated-declarations"
|
||||||
)
|
)
|
||||||
set (_GCC_COMMON_CXX_FLAGS "-fexceptions -frtti"
|
set(_GCC_COMMON_CXX_FLAGS "-fexceptions -frtti"
|
||||||
"-Woverloaded-virtual -Wold-style-cast"
|
"-Woverloaded-virtual -Wold-style-cast"
|
||||||
"-Wnon-virtual-dtor -Wfloat-equal -Wcast-qual -Wcast-align"
|
"-Wnon-virtual-dtor -Wfloat-equal -Wcast-qual -Wcast-align"
|
||||||
"-Werror=overloaded-virtual"
|
#"-Weffc++"
|
||||||
# "-Weffc++"
|
#"-Werror -Wno-error=cpp"
|
||||||
"-Werror -Wno-error=cpp"
|
|
||||||
# we should modify code to make these ones obsolete
|
# we should modify code to make these ones obsolete
|
||||||
"-Wno-error=sign-conversion -Wno-error=float-equal"
|
#"-Wno-error=sign-conversion -Wno-error=float-equal"
|
||||||
)
|
)
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
# a helper function which appends source to the main qBt target
|
# a helper function which appends source to the target
|
||||||
# sources file names are relative to the the ${qBittorrent_SOURCE_DIR}
|
# sources file names are relative to the the target source dir
|
||||||
|
|
||||||
function (qbt_target_sources)
|
function (qbt_target_sources _target _scope)
|
||||||
set (_sources_rel "")
|
get_target_property(targetSourceDir ${_target} SOURCE_DIR)
|
||||||
foreach (_source IN ITEMS ${ARGN})
|
set(sourcesRelative "")
|
||||||
if (IS_ABSOLUTE "${_source}")
|
foreach(source IN ITEMS ${ARGN})
|
||||||
set(source_abs "${_source}")
|
if(IS_ABSOLUTE "${source}")
|
||||||
|
set(sourceAbsolutePath "${source}")
|
||||||
else()
|
else()
|
||||||
get_filename_component(_source_abs "${_source}" ABSOLUTE)
|
get_filename_component(sourceAbsolutePath "${source}" ABSOLUTE)
|
||||||
endif()
|
endif()
|
||||||
file (RELATIVE_PATH _source_rel "${qbt_executable_SOURCE_DIR}" "${_source_abs}")
|
file(RELATIVE_PATH sourceRelativePath "${targetSourceDir}" "${sourceAbsolutePath}")
|
||||||
list (APPEND _sources_rel "${_source_rel}")
|
list(APPEND sourcesRelative "${sourceRelativePath}")
|
||||||
endforeach()
|
endforeach()
|
||||||
target_sources (qBittorrent PRIVATE "${_sources_rel}")
|
target_sources(${_target} ${_scope} "${sourcesRelative}")
|
||||||
endfunction (qbt_target_sources)
|
endfunction(qbt_target_sources)
|
||||||
|
|||||||
48
cmake/Modules/QbtTranslations.cmake
Normal file
48
cmake/Modules/QbtTranslations.cmake
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# macros to handle translation files
|
||||||
|
|
||||||
|
# qbt_add_translations(<target> QRC_FILE <filename> TS_FILES <filenames>)
|
||||||
|
# handles out of source builds for Qt resource files that include translations
|
||||||
|
# The function generates translations out of the supplied list of .ts files in the build directory,
|
||||||
|
# copies the .qrc file there, calls qt5_add_resources() adds its output to the target sources list.
|
||||||
|
function(qbt_add_translations _target)
|
||||||
|
set(oneValueArgs QRC_FILE)
|
||||||
|
set(multiValueArgs TS_FILES)
|
||||||
|
cmake_parse_arguments(QBT_TR "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
get_target_property(_binaryDir ${_target} BINARY_DIR)
|
||||||
|
|
||||||
|
if (NOT QBT_TR_QRC_FILE)
|
||||||
|
message(FATAL_ERROR "QRC file is empty")
|
||||||
|
endif()
|
||||||
|
if (NOT QBT_TR_TS_FILES)
|
||||||
|
message(FATAL_ERROR "TS_FILES files are empty")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(IS_ABSOLUTE "${QBT_TR_QRC_FILE}")
|
||||||
|
file(RELATIVE_PATH _qrcToTs "${CMAKE_CURRENT_SOURCE_DIR}" "${QBT_TR_QRC_FILE}")
|
||||||
|
else()
|
||||||
|
set(_qrcToTs "${QBT_TR_QRC_FILE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(_qrcToTsDir "${_qrcToTs}" DIRECTORY)
|
||||||
|
|
||||||
|
get_filename_component(_qmFilesBinaryDir "${CMAKE_CURRENT_BINARY_DIR}/${_qrcToTsDir}" ABSOLUTE)
|
||||||
|
# to make qt5_add_translation() work as we need
|
||||||
|
set_source_files_properties(${QBT_TR_TS_FILES} PROPERTIES OUTPUT_LOCATION "${_qmFilesBinaryDir}")
|
||||||
|
qt5_add_translation(_qmFiles ${QBT_TR_TS_FILES})
|
||||||
|
|
||||||
|
set(_qrc_dest_dir "${_binaryDir}/${_qrcToTsDir}")
|
||||||
|
set(_qrc_dest_file "${_binaryDir}/${QBT_TR_QRC_FILE}")
|
||||||
|
|
||||||
|
message(STATUS "copying ${QBT_TR_QRC_FILE} to ${_qrc_dest_dir}")
|
||||||
|
file(COPY ${QBT_TR_QRC_FILE} DESTINATION ${_qrc_dest_dir})
|
||||||
|
|
||||||
|
set_source_files_properties("${_qrc_dest_file}" PROPERTIES
|
||||||
|
GENERATED True
|
||||||
|
OBJECT_DEPENDS "${_qmFiles}")
|
||||||
|
|
||||||
|
# With AUTORCC enabled rcc is ran by cmake before language files are generated,
|
||||||
|
# and thus we call rcc explicitly
|
||||||
|
qt5_add_resources(_resources "${_qrc_dest_file}")
|
||||||
|
target_sources(${_target} PRIVATE "${_resources}")
|
||||||
|
endfunction()
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
if (STACKTRACE_WIN)
|
if (STACKTRACE)
|
||||||
if ("${WINXXBITS}" NOT STREQUAL "Win64")
|
if ("${WINXXBITS}" NOT STREQUAL "Win64")
|
||||||
add_compile_options(-fno-omit-frame-pointer)
|
add_compile_options(-fno-omit-frame-pointer)
|
||||||
endif ("${WINXXBITS}" NOT STREQUAL "Win64")
|
endif ("${WINXXBITS}" NOT STREQUAL "Win64")
|
||||||
link_libraries(libdbghelp -Wl,--export-all-symbols)
|
link_libraries(libdbghelp -Wl,--export-all-symbols)
|
||||||
endif (STACKTRACE_WIN)
|
endif (STACKTRACE)
|
||||||
|
|
||||||
if (("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") OR ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo"))
|
if (("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") OR ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo"))
|
||||||
link_libraries(-Wl,--dynamicbase)
|
link_libraries(-Wl,--dynamicbase)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
if (STACKTRACE_WIN)
|
if (STACKTRACE)
|
||||||
if ("${WINXXBITS}" STREQUAL "Win64")
|
if ("${WINXXBITS}" STREQUAL "Win64")
|
||||||
add_compile_options(-Zi)
|
add_compile_options(-Zi)
|
||||||
else ("${WINXXBITS}" STREQUAL "Win64")
|
else ("${WINXXBITS}" STREQUAL "Win64")
|
||||||
@@ -6,7 +6,7 @@ if (STACKTRACE_WIN)
|
|||||||
add_compile_options(-Oy-)
|
add_compile_options(-Oy-)
|
||||||
endif ("${WINXXBITS}" STREQUAL "Win64")
|
endif ("${WINXXBITS}" STREQUAL "Win64")
|
||||||
link_libraries(dbghelp.lib)
|
link_libraries(dbghelp.lib)
|
||||||
endif (STACKTRACE_WIN)
|
endif (STACKTRACE)
|
||||||
|
|
||||||
# Enable Wide characters
|
# Enable Wide characters
|
||||||
add_definitions(-DTORRENT_USE_WPATH)
|
add_definitions(-DTORRENT_USE_WPATH)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ BINDIR = @EXPAND_BINDIR@
|
|||||||
DATADIR = @EXPAND_DATADIR@
|
DATADIR = @EXPAND_DATADIR@
|
||||||
MANPREFIX = @EXPAND_MANDIR@
|
MANPREFIX = @EXPAND_MANDIR@
|
||||||
|
|
||||||
|
QMAKE_CC = @QBT_CC@
|
||||||
|
QMAKE_CXX = @QBT_CXX@
|
||||||
QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@
|
QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@
|
||||||
|
|
||||||
EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@
|
EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ DEFINES += BOOST_USE_WINAPI_VERSION=0x0501
|
|||||||
#DEFINES += BOOST_ASIO_SEPARATE_COMPILATION
|
#DEFINES += BOOST_ASIO_SEPARATE_COMPILATION
|
||||||
# Enable if building against libtorrent 1.0.x (RC_1_0) (dynamic linking)
|
# Enable if building against libtorrent 1.0.x (RC_1_0) (dynamic linking)
|
||||||
#DEFINES += BOOST_ASIO_DYN_LINK
|
#DEFINES += BOOST_ASIO_DYN_LINK
|
||||||
|
# Enable if encountered build error with boost version <= 1.59
|
||||||
|
#DEFINES += BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
|
||||||
# Enable if building against libtorrent 1.1.x (RC_1_1)
|
# Enable if building against libtorrent 1.1.x (RC_1_1)
|
||||||
# built with this flag defined
|
# built with this flag defined
|
||||||
@@ -58,4 +60,10 @@ DEFINES += BOOST_USE_WINAPI_VERSION=0x0501
|
|||||||
#DEFINES += TORRENT_LINKING_SHARED
|
#DEFINES += TORRENT_LINKING_SHARED
|
||||||
|
|
||||||
# Enable stack trace support
|
# Enable stack trace support
|
||||||
CONFIG += strace_win
|
CONFIG += stacktrace
|
||||||
|
|
||||||
|
win32-msvc* {
|
||||||
|
QMAKE_CXXFLAGS += "/guard:cf"
|
||||||
|
QMAKE_LFLAGS += "/guard:cf"
|
||||||
|
QMAKE_LFLAGS_RELEASE += "/OPT:REF /OPT:ICF"
|
||||||
|
}
|
||||||
|
|||||||
493
configure
vendored
493
configure
vendored
@@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for qbittorrent v4.1.0alpha.
|
# Generated by GNU Autoconf 2.69 for qbittorrent v4.1.9.1.
|
||||||
#
|
#
|
||||||
# Report bugs to <bugs.qbittorrent.org>.
|
# Report bugs to <bugs.qbittorrent.org>.
|
||||||
#
|
#
|
||||||
@@ -580,8 +580,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='qbittorrent'
|
PACKAGE_NAME='qbittorrent'
|
||||||
PACKAGE_TARNAME='qbittorrent'
|
PACKAGE_TARNAME='qbittorrent'
|
||||||
PACKAGE_VERSION='v4.1.0alpha'
|
PACKAGE_VERSION='v4.1.9.1'
|
||||||
PACKAGE_STRING='qbittorrent v4.1.0alpha'
|
PACKAGE_STRING='qbittorrent v4.1.9.1'
|
||||||
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
||||||
PACKAGE_URL='https://www.qbittorrent.org/'
|
PACKAGE_URL='https://www.qbittorrent.org/'
|
||||||
|
|
||||||
@@ -595,6 +595,8 @@ QBT_REMOVE_CONFIG
|
|||||||
QBT_ADD_CONFIG
|
QBT_ADD_CONFIG
|
||||||
QBT_CONF_EXTRA_CFLAGS
|
QBT_CONF_EXTRA_CFLAGS
|
||||||
QBT_CONF_INCLUDES
|
QBT_CONF_INCLUDES
|
||||||
|
QBT_CXX
|
||||||
|
QBT_CC
|
||||||
EXPAND_MANDIR
|
EXPAND_MANDIR
|
||||||
EXPAND_DATADIR
|
EXPAND_DATADIR
|
||||||
EXPAND_BINDIR
|
EXPAND_BINDIR
|
||||||
@@ -626,7 +628,6 @@ am__nodep
|
|||||||
AMDEPBACKSLASH
|
AMDEPBACKSLASH
|
||||||
AMDEP_FALSE
|
AMDEP_FALSE
|
||||||
AMDEP_TRUE
|
AMDEP_TRUE
|
||||||
am__quote
|
|
||||||
am__include
|
am__include
|
||||||
DEPDIR
|
DEPDIR
|
||||||
am__untar
|
am__untar
|
||||||
@@ -709,7 +710,8 @@ PACKAGE_VERSION
|
|||||||
PACKAGE_TARNAME
|
PACKAGE_TARNAME
|
||||||
PACKAGE_NAME
|
PACKAGE_NAME
|
||||||
PATH_SEPARATOR
|
PATH_SEPARATOR
|
||||||
SHELL'
|
SHELL
|
||||||
|
am__quote'
|
||||||
ac_subst_files=''
|
ac_subst_files=''
|
||||||
ac_user_opts='
|
ac_user_opts='
|
||||||
enable_option_checking
|
enable_option_checking
|
||||||
@@ -1297,7 +1299,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures qbittorrent v4.1.0alpha to adapt to many kinds of systems.
|
\`configure' configures qbittorrent v4.1.9.1 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1368,7 +1370,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of qbittorrent v4.1.0alpha:";;
|
short | recursive ) echo "Configuration of qbittorrent v4.1.9.1:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1503,7 +1505,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
qbittorrent configure v4.1.0alpha
|
qbittorrent configure v4.1.9.1
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@@ -1642,7 +1644,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by qbittorrent $as_me v4.1.0alpha, which was
|
It was created by qbittorrent $as_me v4.1.9.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -3274,7 +3276,7 @@ IFS=$ac_save_IFS
|
|||||||
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
|
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
|
||||||
|
|
||||||
|
|
||||||
am__api_version='1.15'
|
am__api_version='1.16'
|
||||||
|
|
||||||
# Find a good install program. We prefer a C program (faster),
|
# Find a good install program. We prefer a C program (faster),
|
||||||
# so one script is as good as another. But avoid the broken or
|
# so one script is as good as another. But avoid the broken or
|
||||||
@@ -3700,45 +3702,45 @@ DEPDIR="${am__leading_dot}deps"
|
|||||||
|
|
||||||
ac_config_commands="$ac_config_commands depfiles"
|
ac_config_commands="$ac_config_commands depfiles"
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
|
||||||
am_make=${MAKE-make}
|
$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
|
||||||
cat > confinc << 'END'
|
cat > confinc.mk << 'END'
|
||||||
am__doit:
|
am__doit:
|
||||||
@echo this is the am__doit target
|
@echo this is the am__doit target >confinc.out
|
||||||
.PHONY: am__doit
|
.PHONY: am__doit
|
||||||
END
|
END
|
||||||
# If we don't find an include directive, just comment out the code.
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
|
|
||||||
$as_echo_n "checking for style of include used by $am_make... " >&6; }
|
|
||||||
am__include="#"
|
am__include="#"
|
||||||
am__quote=
|
am__quote=
|
||||||
_am_result=none
|
# BSD make does it like this.
|
||||||
# First try GNU make style include.
|
echo '.include "confinc.mk" # ignored' > confmf.BSD
|
||||||
echo "include confinc" > confmf
|
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
|
||||||
# Ignore all kinds of additional output from 'make'.
|
echo 'include confinc.mk # ignored' > confmf.GNU
|
||||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
_am_result=no
|
||||||
*the\ am__doit\ target*)
|
for s in GNU BSD; do
|
||||||
am__include=include
|
{ echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
|
||||||
am__quote=
|
(${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
|
||||||
_am_result=GNU
|
ac_status=$?
|
||||||
;;
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
esac
|
(exit $ac_status); }
|
||||||
# Now try BSD make style include.
|
case $?:`cat confinc.out 2>/dev/null` in #(
|
||||||
if test "$am__include" = "#"; then
|
'0:this is the am__doit target') :
|
||||||
echo '.include "confinc"' > confmf
|
case $s in #(
|
||||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
BSD) :
|
||||||
*the\ am__doit\ target*)
|
am__include='.include' am__quote='"' ;; #(
|
||||||
am__include=.include
|
*) :
|
||||||
am__quote="\""
|
am__include='include' am__quote='' ;;
|
||||||
_am_result=BSD
|
esac ;; #(
|
||||||
|
*) :
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
if test "$am__include" != "#"; then
|
||||||
|
_am_result="yes ($s style)"
|
||||||
|
break
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
|
fi
|
||||||
$as_echo "$_am_result" >&6; }
|
done
|
||||||
rm -f confinc confmf
|
rm -f confinc.* confmf.*
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
|
||||||
|
$as_echo "${_am_result}" >&6; }
|
||||||
|
|
||||||
# Check whether --enable-dependency-tracking was given.
|
# Check whether --enable-dependency-tracking was given.
|
||||||
if test "${enable_dependency_tracking+set}" = set; then :
|
if test "${enable_dependency_tracking+set}" = set; then :
|
||||||
@@ -3820,7 +3822,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='qbittorrent'
|
PACKAGE='qbittorrent'
|
||||||
VERSION='v4.1.0alpha'
|
VERSION='v4.1.9.1'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@@ -3850,8 +3852,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
|
|||||||
|
|
||||||
# For better backward compatibility. To be removed once Automake 1.9.x
|
# For better backward compatibility. To be removed once Automake 1.9.x
|
||||||
# dies out for good. For more background, see:
|
# dies out for good. For more background, see:
|
||||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||||
mkdir_p='$(MKDIR_P)'
|
mkdir_p='$(MKDIR_P)'
|
||||||
|
|
||||||
# We need awk for the "check" target (and possibly the TAP driver). The
|
# We need awk for the "check" target (and possibly the TAP driver). The
|
||||||
@@ -4158,7 +4160,7 @@ END
|
|||||||
Aborting the configuration process, to ensure you take notice of the issue.
|
Aborting the configuration process, to ensure you take notice of the issue.
|
||||||
|
|
||||||
You can download and install GNU coreutils to get an 'rm' implementation
|
You can download and install GNU coreutils to get an 'rm' implementation
|
||||||
that behaves properly: <http://www.gnu.org/software/coreutils/>.
|
that behaves properly: <https://www.gnu.org/software/coreutils/>.
|
||||||
|
|
||||||
If you want to complete the configuration process using your problematic
|
If you want to complete the configuration process using your problematic
|
||||||
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
|
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
|
||||||
@@ -4170,11 +4172,12 @@ END
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# use compiler from env variables if available
|
||||||
|
QBT_CC="$CC"
|
||||||
|
QBT_CXX="$CXX"
|
||||||
|
|
||||||
# Define --wth-* and --enable-* arguments
|
# Define --wth-* and --enable-* arguments
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-qtsingleapplication was given.
|
# Check whether --with-qtsingleapplication was given.
|
||||||
if test "${with_qtsingleapplication+set}" = set; then :
|
if test "${with_qtsingleapplication+set}" = set; then :
|
||||||
withval=$with_qtsingleapplication;
|
withval=$with_qtsingleapplication;
|
||||||
@@ -4745,7 +4748,9 @@ fi
|
|||||||
case ${host_cpu} in #(
|
case ${host_cpu} in #(
|
||||||
x86_64) :
|
x86_64) :
|
||||||
libsubdirs="lib64 libx32 lib lib64" ;; #(
|
libsubdirs="lib64 libx32 lib lib64" ;; #(
|
||||||
ppc64|s390x|sparc64|aarch64|ppc64le) :
|
mips*64*) :
|
||||||
|
libsubdirs="lib64 lib32 lib lib64" ;; #(
|
||||||
|
ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64) :
|
||||||
libsubdirs="lib64 lib lib64" ;; #(
|
libsubdirs="lib64 lib lib64" ;; #(
|
||||||
*) :
|
*) :
|
||||||
libsubdirs="lib"
|
libsubdirs="lib"
|
||||||
@@ -4997,10 +5002,10 @@ $as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;}
|
|||||||
$as_echo "#define HAVE_BOOST /**/" >>confdefs.h
|
$as_echo "#define HAVE_BOOST /**/" >>confdefs.h
|
||||||
|
|
||||||
# execute ACTION-IF-FOUND (if present):
|
# execute ACTION-IF-FOUND (if present):
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\"
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&5
|
||||||
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
|
$as_echo "$as_me: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&6;}
|
||||||
$as_echo "$as_me: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\"
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
|
||||||
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
|
$as_echo "$as_me: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
CPPFLAGS="$CPPFLAGS_SAVED"
|
||||||
@@ -5011,9 +5016,31 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
|
||||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
||||||
|
|
||||||
|
# add workaround for problematic boost version
|
||||||
|
# taken from ax_boost_base.m4
|
||||||
|
|
||||||
|
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
#include <boost/version.hpp>
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < (106000))]));
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
else
|
||||||
|
QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-boost-system was given.
|
# Check whether --with-boost-system was given.
|
||||||
@@ -5245,7 +5272,7 @@ fi
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
if test "x$ax_lib" = "x"; then
|
if test "x$ax_lib" = "x"; then
|
||||||
as_fn_error $? "Could not find a version of the library!" "$LINENO" 5
|
as_fn_error $? "Could not find a version of the Boost::System library!" "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
if test "x$link_system" = "xno"; then
|
if test "x$link_system" = "xno"; then
|
||||||
as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5
|
as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5
|
||||||
@@ -5366,7 +5393,7 @@ else
|
|||||||
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
$as_echo "yes" >&6; }
|
$as_echo "yes" >&6; }
|
||||||
CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS"
|
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
|
||||||
LIBS="$libtorrent_LIBS $LIBS"
|
LIBS="$libtorrent_LIBS $LIBS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -5459,10 +5486,116 @@ else
|
|||||||
zlib_LIBS=$pkg_cv_zlib_LIBS
|
zlib_LIBS=$pkg_cv_zlib_LIBS
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
$as_echo "yes" >&6; }
|
$as_echo "yes" >&6; }
|
||||||
CPPFLAGS="$zlib_CFLAGS $CPPFLAGS"
|
CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
|
||||||
LIBS="$zlib_LIBS $LIBS"
|
LIBS="$zlib_LIBS $LIBS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if already in >= C++11 mode because of the flags returned by one of the above packages
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler is using C++11 or later mode" >&5
|
||||||
|
$as_echo_n "checking if compiler is using C++11 or later mode... " >&6; }
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
#endif
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
QBT_CXX11_FOUND="yes"
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
QBT_CXX11_FOUND="no"
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
# In case of no, check if the compiler can support at least C++11
|
||||||
|
# and if yes, enable it leaving a warning to the user
|
||||||
|
if test "x$QBT_CXX11_FOUND" = "xno"; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports C++11" >&5
|
||||||
|
$as_echo_n "checking if compiler supports C++11... " >&6; }
|
||||||
|
TMP_CXXFLAGS="$CXXFLAGS"
|
||||||
|
CXXFLAGS="$CXXFLAGS -std=c++11"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
#endif
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++11 is disabled by the set compiler flags" >&5
|
||||||
|
$as_echo_n "checking if C++11 is disabled by the set compiler flags... " >&6; }
|
||||||
|
# prepend the flag so it won't override conflicting user defined flags
|
||||||
|
CXXFLAGS="-std=c++11 $TMP_CXXFLAGS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
#endif
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
CXXFLAGS="$TMP_CXXFLAGS -std=c++11"
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C++11 mode is now force enabled.
|
||||||
|
Make sure you use the same C++ mode for qBittorrent and its dependencies.
|
||||||
|
To explicitly set qBittorrent to a later mode use CXXFLAGS.
|
||||||
|
Example: \`CXXFLAGS=\"\$CXXFLAGS -std=c++14\" ./configure\`" >&5
|
||||||
|
$as_echo "$as_me: WARNING: C++11 mode is now force enabled.
|
||||||
|
Make sure you use the same C++ mode for qBittorrent and its dependencies.
|
||||||
|
To explicitly set qBittorrent to a later mode use CXXFLAGS.
|
||||||
|
Example: \`CXXFLAGS=\"\$CXXFLAGS -std=c++14\" ./configure\`" >&2;}
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
as_fn_error $? "The compiler supports C++11 but the user or a dependency has explicitly enabled a lower mode." "$LINENO" 5
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
as_fn_error $? "A compiler supporting C++11 is required." "$LINENO" 5
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
# These are required because autoconf doesn't expand these **particular**
|
# These are required because autoconf doesn't expand these **particular**
|
||||||
# vars automatically. And qmake cannot autoexpand them.
|
# vars automatically. And qmake cannot autoexpand them.
|
||||||
|
|
||||||
@@ -5549,15 +5682,15 @@ extract() {
|
|||||||
for i in $string; do
|
for i in $string; do
|
||||||
case "$(echo "$i" | cut -c1)" in
|
case "$(echo "$i" | cut -c1)" in
|
||||||
'') ;;
|
'') ;;
|
||||||
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";;
|
D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
|
||||||
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";;
|
I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
|
||||||
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";;
|
*) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
IFS=$SAVEIFS
|
IFS=$SAVEIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
|
extract "$CFLAGS $CXXFLAGS"
|
||||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||||
|
|
||||||
# Substitute the values of these vars in conf.pri.in
|
# Substitute the values of these vars in conf.pri.in
|
||||||
@@ -5568,6 +5701,8 @@ QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ac_config_files="$ac_config_files conf.pri"
|
ac_config_files="$ac_config_files conf.pri"
|
||||||
|
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
@@ -6140,7 +6275,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by qbittorrent $as_me v4.1.0alpha, which was
|
This file was extended by qbittorrent $as_me v4.1.9.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -6198,7 +6333,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
qbittorrent config.status v4.1.0alpha
|
qbittorrent config.status v4.1.9.1
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
@@ -6306,7 +6441,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
|||||||
#
|
#
|
||||||
# INIT-COMMANDS
|
# INIT-COMMANDS
|
||||||
#
|
#
|
||||||
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
|
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
@@ -6751,29 +6886,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
|
|||||||
# Older Autoconf quotes --file arguments for eval, but not when files
|
# Older Autoconf quotes --file arguments for eval, but not when files
|
||||||
# are listed without --file. Let's play safe and only enable the eval
|
# are listed without --file. Let's play safe and only enable the eval
|
||||||
# if we detect the quoting.
|
# if we detect the quoting.
|
||||||
case $CONFIG_FILES in
|
# TODO: see whether this extra hack can be removed once we start
|
||||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
# requiring Autoconf 2.70 or later.
|
||||||
*) set x $CONFIG_FILES ;;
|
case $CONFIG_FILES in #(
|
||||||
esac
|
*\'*) :
|
||||||
|
eval set x "$CONFIG_FILES" ;; #(
|
||||||
|
*) :
|
||||||
|
set x $CONFIG_FILES ;; #(
|
||||||
|
*) :
|
||||||
|
;;
|
||||||
|
esac
|
||||||
shift
|
shift
|
||||||
for mf
|
# Used to flag and report bootstrapping failures.
|
||||||
|
am_rc=0
|
||||||
|
for am_mf
|
||||||
do
|
do
|
||||||
# Strip MF so we end up with the name of the file.
|
# Strip MF so we end up with the name of the file.
|
||||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
|
||||||
# Check whether this is an Automake generated Makefile or not.
|
# Check whether this is an Automake generated Makefile which includes
|
||||||
# We used to match only the files named 'Makefile.in', but
|
# dependency-tracking related rules and includes.
|
||||||
# some people rename them; so instead we look at the file content.
|
# Grep'ing the whole file directly is not great: AIX grep has a line
|
||||||
# Grep'ing the first line is not enough: some people post-process
|
|
||||||
# each Makefile.in and add a new line on top of each file to say so.
|
|
||||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
|
||||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||||
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
|
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|
||||||
dirpart=`$as_dirname -- "$mf" ||
|
|| continue
|
||||||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
am_dirpart=`$as_dirname -- "$am_mf" ||
|
||||||
X"$mf" : 'X\(//\)[^/]' \| \
|
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||||
X"$mf" : 'X\(//\)$' \| \
|
X"$am_mf" : 'X\(//\)[^/]' \| \
|
||||||
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
|
X"$am_mf" : 'X\(//\)$' \| \
|
||||||
$as_echo X"$mf" |
|
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
|
$as_echo X"$am_mf" |
|
||||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
@@ -6791,53 +6932,48 @@ $as_echo X"$mf" |
|
|||||||
q
|
q
|
||||||
}
|
}
|
||||||
s/.*/./; q'`
|
s/.*/./; q'`
|
||||||
else
|
am_filepart=`$as_basename -- "$am_mf" ||
|
||||||
continue
|
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
|
||||||
fi
|
X"$am_mf" : 'X\(//\)$' \| \
|
||||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
# from the Makefile without running 'make'.
|
$as_echo X/"$am_mf" |
|
||||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
sed '/^.*\/\([^/][^/]*\)\/*$/{
|
||||||
test -z "$DEPDIR" && continue
|
|
||||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
|
||||||
test -z "$am__include" && continue
|
|
||||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
|
||||||
# Find all dependency output files, they are included files with
|
|
||||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
|
||||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
|
||||||
# expansion.
|
|
||||||
for file in `sed -n "
|
|
||||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
|
||||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
|
|
||||||
# Make sure the directory exists.
|
|
||||||
test -f "$dirpart/$file" && continue
|
|
||||||
fdir=`$as_dirname -- "$file" ||
|
|
||||||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
|
||||||
X"$file" : 'X\(//\)[^/]' \| \
|
|
||||||
X"$file" : 'X\(//\)$' \| \
|
|
||||||
X"$file" : 'X\(/\)' \| . 2>/dev/null ||
|
|
||||||
$as_echo X"$file" |
|
|
||||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
/^X\(\/\/\)[^/].*/{
|
/^X\/\(\/\/\)$/{
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
/^X\(\/\/\)$/{
|
/^X\/\(\/\).*/{
|
||||||
s//\1/
|
|
||||||
q
|
|
||||||
}
|
|
||||||
/^X\(\/\).*/{
|
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
s/.*/./; q'`
|
s/.*/./; q'`
|
||||||
as_dir=$dirpart/$fdir; as_fn_mkdir_p
|
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
|
||||||
# echo "creating $dirpart/$file"
|
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||||
echo '# dummy' > "$dirpart/$file"
|
| $MAKE -f - am--depfiles" >&5
|
||||||
done
|
(cd "$am_dirpart" \
|
||||||
|
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||||
|
| $MAKE -f - am--depfiles) >&5 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } || am_rc=$?
|
||||||
done
|
done
|
||||||
|
if test $am_rc -ne 0; then
|
||||||
|
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
|
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
|
as_fn_error $? "Something went wrong bootstrapping makefile fragments
|
||||||
|
for automatic dependency tracking. Try re-running configure with the
|
||||||
|
'--disable-dependency-tracking' option to at least be able to build
|
||||||
|
the package (albeit without support for automatic dependency tracking).
|
||||||
|
See \`config.log' for more details" "$LINENO" 5; }
|
||||||
|
fi
|
||||||
|
{ am_dirpart=; unset am_dirpart;}
|
||||||
|
{ am_filepart=; unset am_filepart;}
|
||||||
|
{ am_mf=; unset am_mf;}
|
||||||
|
{ am_rc=; unset am_rc;}
|
||||||
|
rm -f conftest-deps.mk
|
||||||
}
|
}
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -7455,7 +7591,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by qbittorrent $as_me v4.1.0alpha, which was
|
This file was extended by qbittorrent $as_me v4.1.9.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -7513,7 +7649,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
qbittorrent config.status v4.1.0alpha
|
qbittorrent config.status v4.1.9.1
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
@@ -7621,7 +7757,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
|||||||
#
|
#
|
||||||
# INIT-COMMANDS
|
# INIT-COMMANDS
|
||||||
#
|
#
|
||||||
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
|
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
@@ -8067,29 +8203,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
|
|||||||
# Older Autoconf quotes --file arguments for eval, but not when files
|
# Older Autoconf quotes --file arguments for eval, but not when files
|
||||||
# are listed without --file. Let's play safe and only enable the eval
|
# are listed without --file. Let's play safe and only enable the eval
|
||||||
# if we detect the quoting.
|
# if we detect the quoting.
|
||||||
case $CONFIG_FILES in
|
# TODO: see whether this extra hack can be removed once we start
|
||||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
# requiring Autoconf 2.70 or later.
|
||||||
*) set x $CONFIG_FILES ;;
|
case $CONFIG_FILES in #(
|
||||||
esac
|
*\'*) :
|
||||||
|
eval set x "$CONFIG_FILES" ;; #(
|
||||||
|
*) :
|
||||||
|
set x $CONFIG_FILES ;; #(
|
||||||
|
*) :
|
||||||
|
;;
|
||||||
|
esac
|
||||||
shift
|
shift
|
||||||
for mf
|
# Used to flag and report bootstrapping failures.
|
||||||
|
am_rc=0
|
||||||
|
for am_mf
|
||||||
do
|
do
|
||||||
# Strip MF so we end up with the name of the file.
|
# Strip MF so we end up with the name of the file.
|
||||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
|
||||||
# Check whether this is an Automake generated Makefile or not.
|
# Check whether this is an Automake generated Makefile which includes
|
||||||
# We used to match only the files named 'Makefile.in', but
|
# dependency-tracking related rules and includes.
|
||||||
# some people rename them; so instead we look at the file content.
|
# Grep'ing the whole file directly is not great: AIX grep has a line
|
||||||
# Grep'ing the first line is not enough: some people post-process
|
|
||||||
# each Makefile.in and add a new line on top of each file to say so.
|
|
||||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
|
||||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||||
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
|
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|
||||||
dirpart=`$as_dirname -- "$mf" ||
|
|| continue
|
||||||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
am_dirpart=`$as_dirname -- "$am_mf" ||
|
||||||
X"$mf" : 'X\(//\)[^/]' \| \
|
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||||
X"$mf" : 'X\(//\)$' \| \
|
X"$am_mf" : 'X\(//\)[^/]' \| \
|
||||||
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
|
X"$am_mf" : 'X\(//\)$' \| \
|
||||||
$as_echo X"$mf" |
|
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
|
$as_echo X"$am_mf" |
|
||||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
@@ -8107,53 +8249,48 @@ $as_echo X"$mf" |
|
|||||||
q
|
q
|
||||||
}
|
}
|
||||||
s/.*/./; q'`
|
s/.*/./; q'`
|
||||||
else
|
am_filepart=`$as_basename -- "$am_mf" ||
|
||||||
continue
|
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
|
||||||
fi
|
X"$am_mf" : 'X\(//\)$' \| \
|
||||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
# from the Makefile without running 'make'.
|
$as_echo X/"$am_mf" |
|
||||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
sed '/^.*\/\([^/][^/]*\)\/*$/{
|
||||||
test -z "$DEPDIR" && continue
|
|
||||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
|
||||||
test -z "$am__include" && continue
|
|
||||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
|
||||||
# Find all dependency output files, they are included files with
|
|
||||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
|
||||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
|
||||||
# expansion.
|
|
||||||
for file in `sed -n "
|
|
||||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
|
||||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
|
|
||||||
# Make sure the directory exists.
|
|
||||||
test -f "$dirpart/$file" && continue
|
|
||||||
fdir=`$as_dirname -- "$file" ||
|
|
||||||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
|
||||||
X"$file" : 'X\(//\)[^/]' \| \
|
|
||||||
X"$file" : 'X\(//\)$' \| \
|
|
||||||
X"$file" : 'X\(/\)' \| . 2>/dev/null ||
|
|
||||||
$as_echo X"$file" |
|
|
||||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
/^X\(\/\/\)[^/].*/{
|
/^X\/\(\/\/\)$/{
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
/^X\(\/\/\)$/{
|
/^X\/\(\/\).*/{
|
||||||
s//\1/
|
|
||||||
q
|
|
||||||
}
|
|
||||||
/^X\(\/\).*/{
|
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
s/.*/./; q'`
|
s/.*/./; q'`
|
||||||
as_dir=$dirpart/$fdir; as_fn_mkdir_p
|
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
|
||||||
# echo "creating $dirpart/$file"
|
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||||
echo '# dummy' > "$dirpart/$file"
|
| $MAKE -f - am--depfiles" >&5
|
||||||
done
|
(cd "$am_dirpart" \
|
||||||
|
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||||
|
| $MAKE -f - am--depfiles) >&5 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } || am_rc=$?
|
||||||
done
|
done
|
||||||
|
if test $am_rc -ne 0; then
|
||||||
|
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
|
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
|
as_fn_error $? "Something went wrong bootstrapping makefile fragments
|
||||||
|
for automatic dependency tracking. Try re-running configure with the
|
||||||
|
'--disable-dependency-tracking' option to at least be able to build
|
||||||
|
the package (albeit without support for automatic dependency tracking).
|
||||||
|
See \`config.log' for more details" "$LINENO" 5; }
|
||||||
|
fi
|
||||||
|
{ am_dirpart=; unset am_dirpart;}
|
||||||
|
{ am_filepart=; unset am_filepart;}
|
||||||
|
{ am_mf=; unset am_mf;}
|
||||||
|
{ am_rc=; unset am_rc;}
|
||||||
|
rm -f conftest-deps.mk
|
||||||
}
|
}
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|||||||
67
configure.ac
67
configure.ac
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([qbittorrent], [v4.1.0alpha], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
|
AC_INIT([qbittorrent], [v4.1.9.1], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
@@ -8,7 +8,9 @@ AC_LANG(C++)
|
|||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
|
|
||||||
|
# use compiler from env variables if available
|
||||||
|
QBT_CC="$CC"
|
||||||
|
QBT_CXX="$CXX"
|
||||||
|
|
||||||
# Define --wth-* and --enable-* arguments
|
# Define --wth-* and --enable-* arguments
|
||||||
|
|
||||||
@@ -162,12 +164,21 @@ AS_CASE(["x$enable_qt_dbus"],
|
|||||||
|
|
||||||
|
|
||||||
AX_BOOST_BASE([1.35],
|
AX_BOOST_BASE([1.35],
|
||||||
[AC_MSG_NOTICE([Boost CPPFLAGS: "$BOOST_CPPFLAGS"
|
[AC_MSG_NOTICE([Boost CXXFLAGS: "$BOOST_CPPFLAGS"])
|
||||||
Boost LDFLAGS: "$BOOST_LDFLAGS"])],
|
AC_MSG_NOTICE([Boost LDFLAGS: "$BOOST_LDFLAGS"])],
|
||||||
[AC_MSG_ERROR([Could not find Boost])])
|
[AC_MSG_ERROR([Could not find Boost])])
|
||||||
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
|
||||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
||||||
|
|
||||||
|
# add workaround for problematic boost version
|
||||||
|
# taken from ax_boost_base.m4
|
||||||
|
m4_define([DETECT_BOOST_VERSION_PROGRAM],
|
||||||
|
[AC_LANG_PROGRAM([[#include <boost/version.hpp>]],
|
||||||
|
[[(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))]));]])])
|
||||||
|
|
||||||
|
AC_COMPILE_IFELSE([DETECT_BOOST_VERSION_PROGRAM(106000)], [],
|
||||||
|
[QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"])
|
||||||
|
|
||||||
AX_BOOST_SYSTEM()
|
AX_BOOST_SYSTEM()
|
||||||
AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"])
|
AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"])
|
||||||
LIBS="$BOOST_SYSTEM_LIB $LIBS"
|
LIBS="$BOOST_SYSTEM_LIB $LIBS"
|
||||||
@@ -185,14 +196,46 @@ AS_CASE(["x$with_qtsingleapplication"],
|
|||||||
|
|
||||||
PKG_CHECK_MODULES(libtorrent,
|
PKG_CHECK_MODULES(libtorrent,
|
||||||
[libtorrent-rasterbar >= 1.0.6],
|
[libtorrent-rasterbar >= 1.0.6],
|
||||||
[CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS"
|
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
|
||||||
LIBS="$libtorrent_LIBS $LIBS"])
|
LIBS="$libtorrent_LIBS $LIBS"])
|
||||||
|
|
||||||
PKG_CHECK_MODULES(zlib,
|
PKG_CHECK_MODULES(zlib,
|
||||||
[zlib >= 1.2.5.2],
|
[zlib >= 1.2.5.2],
|
||||||
[CPPFLAGS="$zlib_CFLAGS $CPPFLAGS"
|
[CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
|
||||||
LIBS="$zlib_LIBS $LIBS"])
|
LIBS="$zlib_LIBS $LIBS"])
|
||||||
|
|
||||||
|
# Check if already in >= C++11 mode because of the flags returned by one of the above packages
|
||||||
|
AC_MSG_CHECKING([if compiler is using C++11 or later mode])
|
||||||
|
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
QBT_CXX11_FOUND="yes"],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
QBT_CXX11_FOUND="no"])
|
||||||
|
|
||||||
|
# In case of no, check if the compiler can support at least C++11
|
||||||
|
# and if yes, enable it leaving a warning to the user
|
||||||
|
AS_IF([test "x$QBT_CXX11_FOUND" = "xno"],
|
||||||
|
[AC_MSG_CHECKING([if compiler supports C++11])
|
||||||
|
TMP_CXXFLAGS="$CXXFLAGS"
|
||||||
|
CXXFLAGS="$CXXFLAGS -std=c++11"
|
||||||
|
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
AC_MSG_CHECKING([if C++11 is disabled by the set compiler flags])
|
||||||
|
# prepend the flag so it won't override conflicting user defined flags
|
||||||
|
CXXFLAGS="-std=c++11 $TMP_CXXFLAGS"
|
||||||
|
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
CXXFLAGS="$TMP_CXXFLAGS -std=c++11"
|
||||||
|
AC_MSG_WARN([C++11 mode is now force enabled.
|
||||||
|
Make sure you use the same C++ mode for qBittorrent and its dependencies.
|
||||||
|
To explicitly set qBittorrent to a later mode use CXXFLAGS.
|
||||||
|
Example: `CXXFLAGS="\$CXXFLAGS -std=c++14" ./configure`])],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
AC_MSG_ERROR([The compiler supports C++11 but the user or a dependency has explicitly enabled a lower mode.])])],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
AC_MSG_ERROR([A compiler supporting C++11 is required.])])
|
||||||
|
])
|
||||||
|
|
||||||
# These are required because autoconf doesn't expand these **particular**
|
# These are required because autoconf doesn't expand these **particular**
|
||||||
# vars automatically. And qmake cannot autoexpand them.
|
# vars automatically. And qmake cannot autoexpand them.
|
||||||
AX_DEFINE_DIR([EXPAND_PREFIX], [prefix])
|
AX_DEFINE_DIR([EXPAND_PREFIX], [prefix])
|
||||||
@@ -219,18 +262,20 @@ extract() {
|
|||||||
for i in $string; do
|
for i in $string; do
|
||||||
case "$(echo "$i" | cut -c1)" in
|
case "$(echo "$i" | cut -c1)" in
|
||||||
'') ;;
|
'') ;;
|
||||||
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";;
|
D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
|
||||||
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";;
|
I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
|
||||||
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";;
|
*) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
IFS=$SAVEIFS
|
IFS=$SAVEIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
|
extract "$CFLAGS $CXXFLAGS"
|
||||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||||
|
|
||||||
# Substitute the values of these vars in conf.pri.in
|
# Substitute the values of these vars in conf.pri.in
|
||||||
|
AC_SUBST(QBT_CC)
|
||||||
|
AC_SUBST(QBT_CXX)
|
||||||
AC_SUBST(QBT_CONF_INCLUDES)
|
AC_SUBST(QBT_CONF_INCLUDES)
|
||||||
AC_SUBST(QBT_CONF_EXTRA_CFLAGS)
|
AC_SUBST(QBT_CONF_EXTRA_CFLAGS)
|
||||||
AC_SUBST(QBT_ADD_CONFIG)
|
AC_SUBST(QBT_ADD_CONFIG)
|
||||||
|
|||||||
2
dist/CMakeLists.txt
vendored
2
dist/CMakeLists.txt
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
find_package(Qt5Widgets ${requiredQtVersion}) # to conditionally install desktop-related files
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
add_subdirectory(mac)
|
add_subdirectory(mac)
|
||||||
else (APPLE)
|
else (APPLE)
|
||||||
|
|||||||
22
dist/mac/Info.plist
vendored
22
dist/mac/Info.plist
vendored
@@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>qBittorrent</string>
|
||||||
<key>CFBundleDocumentTypes</key>
|
<key>CFBundleDocumentTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -21,6 +25,10 @@
|
|||||||
<array>
|
<array>
|
||||||
<string>org.bittorrent.torrent</string>
|
<string>org.bittorrent.torrent</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>NSExportableTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>org.bittorrent.torrent</string>
|
||||||
|
</array>
|
||||||
<key>LSIsAppleDefaultForType</key>
|
<key>LSIsAppleDefaultForType</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -28,6 +36,8 @@
|
|||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>magnet</string>
|
<string>magnet</string>
|
||||||
@@ -45,21 +55,19 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.1.0</string>
|
<string>4.1.9</string>
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>qBit</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>@EXECUTABLE@</string>
|
<string>@EXECUTABLE@</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>org.qbittorrent</string>
|
<string>org.qbittorrent.qBittorrent</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string>NSApplication</string>
|
<string>NSApplication</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
|
||||||
<string>True</string>
|
|
||||||
<key>NSAppleScriptEnabled</key>
|
<key>NSAppleScriptEnabled</key>
|
||||||
<string>YES</string>
|
<string>YES</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2006-2018 The qBittorrent project</string>
|
<string>Copyright © 2006-2019 The qBittorrent project</string>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
BIN
dist/mac/qBitTorrentDocument.icns
vendored
BIN
dist/mac/qBitTorrentDocument.icns
vendored
Binary file not shown.
34
dist/unix/CMakeLists.txt
vendored
34
dist/unix/CMakeLists.txt
vendored
@@ -1,36 +1,42 @@
|
|||||||
if (SYSTEMD)
|
if (NOT Qt5Widgets_FOUND)
|
||||||
find_package(Systemd)
|
feature_option(SYSTEMD "Install systemd service file (headless only)" OFF)
|
||||||
if (SYSTEMD_FOUND)
|
if (SYSTEMD)
|
||||||
|
if (NOT Systemd_SERVICES_INSTALL_DIR)
|
||||||
|
find_package(Systemd)
|
||||||
|
if (NOT Systemd_FOUND)
|
||||||
|
message(FATAL_ERROR "Could not locate systemd services install dir."
|
||||||
|
" Either pass -DSystemd_SERVICES_INSTALL_DIR=/path/to/systemd/services option or install systemd pkg-config")
|
||||||
|
endif(NOT Systemd_FOUND)
|
||||||
|
endif(NOT Systemd_SERVICES_INSTALL_DIR)
|
||||||
set(EXPAND_BINDIR ${CMAKE_INSTALL_FULL_BINDIR})
|
set(EXPAND_BINDIR ${CMAKE_INSTALL_FULL_BINDIR})
|
||||||
configure_file(systemd/qbittorrent-nox@.service.in ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service @ONLY)
|
configure_file(systemd/qbittorrent-nox@.service.in ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service @ONLY)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service
|
||||||
DESTINATION ${SYSTEMD_SERVICES_INSTALL_DIR}
|
DESTINATION ${Systemd_SERVICES_INSTALL_DIR}
|
||||||
COMPONENT data)
|
COMPONENT data)
|
||||||
endif(SYSTEMD_FOUND)
|
endif(SYSTEMD)
|
||||||
endif(SYSTEMD)
|
endif()
|
||||||
|
|
||||||
|
if (Qt5Widgets_FOUND)
|
||||||
if (GUI)
|
|
||||||
list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent.1)
|
list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent.1)
|
||||||
else (GUI)
|
else (Qt5Widgets_FOUND)
|
||||||
list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent-nox.1)
|
list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent-nox.1)
|
||||||
endif (GUI)
|
endif (Qt5Widgets_FOUND)
|
||||||
|
|
||||||
install(FILES ${MAN_FILES}
|
install(FILES ${MAN_FILES}
|
||||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
||||||
COMPONENT doc)
|
COMPONENT doc)
|
||||||
|
|
||||||
if (GUI)
|
if (Qt5Widgets_FOUND)
|
||||||
install(DIRECTORY menuicons/
|
install(DIRECTORY menuicons/
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor
|
||||||
FILES_MATCHING PATTERN "*.png")
|
FILES_MATCHING PATTERN "*.png")
|
||||||
|
|
||||||
install(FILES ${qBittorrent_SOURCE_DIR}/src/icons/qbittorrent.desktop
|
install(FILES org.qbittorrent.qBittorrent.desktop
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/
|
||||||
COMPONENT data)
|
COMPONENT data)
|
||||||
|
|
||||||
install(FILES qbittorrent.appdata.xml
|
install(FILES org.qbittorrent.qBittorrent.appdata.xml
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/appdata/
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/
|
||||||
COMPONENT data)
|
COMPONENT data)
|
||||||
|
|
||||||
install(FILES
|
install(FILES
|
||||||
|
|||||||
75
dist/unix/org.qbittorrent.qBittorrent.appdata.xml
vendored
Normal file
75
dist/unix/org.qbittorrent.qBittorrent.appdata.xml
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Copyright 2014 sledgehammer999 <sledgehammer999@qbittorrent.org> -->
|
||||||
|
<component type="desktop">
|
||||||
|
<id>org.qbittorrent.qBittorrent</id>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-2.0 and OpenSSL</project_license>
|
||||||
|
<name>qBittorrent</name>
|
||||||
|
<summary>An open-source Bittorrent client</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
The qBittorrent project aims to provide an open-source software alternative to µTorrent.
|
||||||
|
Additionally, qBittorrent runs and provides the same features on all major platforms (FreeBSD, Linux, macOS, OS/2, Windows).
|
||||||
|
qBittorrent is based on the Qt toolkit and libtorrent-rasterbar library.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Polished µTorrent-like User Interface</li>
|
||||||
|
<li>
|
||||||
|
Well-integrated and extensible Search Engine
|
||||||
|
<ul>
|
||||||
|
<li>Simultaneous search in many Torrent search sites</li>
|
||||||
|
<li>Category-specific search requests (e.g. Books, Music, Software)</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>RSS feed support with advanced download filters (incl. regex)</li>
|
||||||
|
<li>
|
||||||
|
Many Bittorrent extensions supported:
|
||||||
|
<ul>
|
||||||
|
<li>Magnet links</li>
|
||||||
|
<li>Distributed hash table (DHT), peer exchange protocol (PEX), local peer discovery (LSD)</li>
|
||||||
|
<li>Private torrents</li>
|
||||||
|
<li>Encrypted connections</li>
|
||||||
|
<li>and many more...</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Remote control through Web user interface, written with AJAX</li>
|
||||||
|
<li>Sequential downloading (Download in order)</li>
|
||||||
|
<li>
|
||||||
|
Advanced control over torrents, trackers and peers
|
||||||
|
<ul>
|
||||||
|
<li>Torrents queueing and prioritizing</li>
|
||||||
|
<li>Torrent content selection and prioritizing</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Bandwidth scheduler</li>
|
||||||
|
<li>Torrent creation tool</li>
|
||||||
|
<li>IP Filtering (eMule & PeerGuardian format compatible)</li>
|
||||||
|
<li>IPv6 compliant</li>
|
||||||
|
<li>UPnP / NAT-PMP port forwarding support</li>
|
||||||
|
<li>Available on all platforms: Windows, Linux, macOS, FreeBSD, OS/2</li>
|
||||||
|
<li>Available in ~70 languages</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<launchable type="desktop-id">org.qbittorrent.qBittorrent.desktop</launchable>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_01.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_02.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_03.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_04.png</image>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<update_contact>sledgehammer999@qbittorrent.org</update_contact>
|
||||||
|
<developer_name>The qBittorrent Project</developer_name>
|
||||||
|
<url type="homepage">https://www.qbittorrent.org/</url>
|
||||||
|
<url type="bugtracker">http://bugs.qbittorrent.org/</url>
|
||||||
|
<url type="donation">https://www.qbittorrent.org/donate</url>
|
||||||
|
<url type="help">http://forum.qbittorrent.org/</url>
|
||||||
|
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
|
||||||
|
</component>
|
||||||
66
dist/unix/qbittorrent.appdata.xml
vendored
66
dist/unix/qbittorrent.appdata.xml
vendored
@@ -1,66 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!-- Copyright 2014 sledgehammer999 <sledgehammer999@qbittorrent.org> -->
|
|
||||||
<component type="desktop">
|
|
||||||
<id>qbittorrent.desktop</id>
|
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
|
||||||
<project_license>GPL-2.0 and OpenSSL</project_license>
|
|
||||||
<name>qBittorrent</name>
|
|
||||||
<summary>A Bittorrent Client</summary>
|
|
||||||
<description>
|
|
||||||
<p>
|
|
||||||
Aiming to be a good alternative to all other bittorrent clients out
|
|
||||||
there, qBittorrent is fast, stable and provides unicode support as well
|
|
||||||
as many other features. Additionally, qBittorrent runs and provides those
|
|
||||||
same features on all major platforms (Linux, Mac OS X, Windows, FreeBSD).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
It is programmed in C++ / Qt and uses libtorrent (sometimes called
|
|
||||||
libtorrent-rasterbar) by Arvid Norberg. GeoLite data, created by MaxMind,
|
|
||||||
are included in qBittorrent. Its features include:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>Polished µTorrent-like User Interface</li>
|
|
||||||
<li>Well-integrated and extensible Search Engine</li>
|
|
||||||
<li>All Bittorrent extensions (DHT, Peer Exchange, Full encryption, Magnet/BitComet URIs, ...)</li>
|
|
||||||
<li>Remote control through a Web user interface</li>
|
|
||||||
<li>Advanced control over trackers, peers and torrents</li>
|
|
||||||
<li>UPnP / NAT-PMP port forwarding support</li>
|
|
||||||
<li>Available in ~25 languages (Unicode support)</li>
|
|
||||||
<li>Torrent creation tool</li>
|
|
||||||
<li>Advanced RSS support with download filters (inc. regex)</li>
|
|
||||||
<li>Bandwidth scheduler</li>
|
|
||||||
<li>IP Filtering (eMule and PeerGuardian compatible)</li>
|
|
||||||
<li>IPv6 compliant</li>
|
|
||||||
<li>Sequential downloading (aka "Download in order")</li>
|
|
||||||
</ul>
|
|
||||||
</description>
|
|
||||||
<screenshots>
|
|
||||||
<screenshot type="default">
|
|
||||||
<image height="675" width="1200">
|
|
||||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_01.png
|
|
||||||
</image>
|
|
||||||
</screenshot>
|
|
||||||
<screenshot>
|
|
||||||
<image height="675" width="1200">
|
|
||||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_02.png
|
|
||||||
</image>
|
|
||||||
</screenshot>
|
|
||||||
<screenshot>
|
|
||||||
<image height="675" width="1200">
|
|
||||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_03.png
|
|
||||||
</image>
|
|
||||||
</screenshot>
|
|
||||||
<screenshot>
|
|
||||||
<image height="675" width="1200">
|
|
||||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_04.png
|
|
||||||
</image>
|
|
||||||
</screenshot>
|
|
||||||
</screenshots>
|
|
||||||
<url type="homepage">https://www.qbittorrent.org/</url>
|
|
||||||
<update_contact>sledgehammer999@qbittorrent.org</update_contact>
|
|
||||||
<developer_name>The qBittorrent Project</developer_name>
|
|
||||||
<url type="bugtracker">http://bugs.qbittorrent.org/</url>
|
|
||||||
<url type="donation">https://www.qbittorrent.org/donate</url>
|
|
||||||
<url type="help">http://forum.qbittorrent.org/</url>
|
|
||||||
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
|
|
||||||
</component>
|
|
||||||
6
dist/windows/options.nsi
vendored
6
dist/windows/options.nsi
vendored
@@ -27,7 +27,7 @@ XPStyle on
|
|||||||
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
||||||
|
|
||||||
; Program specific
|
; Program specific
|
||||||
!define PROG_VERSION "4.1.0"
|
!define PROG_VERSION "4.1.9.1"
|
||||||
|
|
||||||
!define MUI_FINISHPAGE_RUN
|
!define MUI_FINISHPAGE_RUN
|
||||||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
||||||
@@ -50,11 +50,11 @@ XPStyle on
|
|||||||
;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-2018 The qBittorrent project"
|
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2019 The qBittorrent project"
|
||||||
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
||||||
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
||||||
|
|
||||||
VIProductVersion "${PROG_VERSION}.0"
|
VIProductVersion "${PROG_VERSION}.1"
|
||||||
|
|
||||||
; The default installation directory. It changes depending if we install in the 64bit dir or not.
|
; The default installation directory. It changes depending if we install in the 64bit dir or not.
|
||||||
; A caveat of this is if a user has installed a 32bit version and then runs the 64bit installer
|
; A caveat of this is if a user has installed a 32bit version and then runs the 64bit installer
|
||||||
|
|||||||
@@ -33,7 +33,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 42
|
#serial 47
|
||||||
|
|
||||||
# example boost program (need to pass version)
|
# example boost program (need to pass version)
|
||||||
m4_define([_AX_BOOST_BASE_PROGRAM],
|
m4_define([_AX_BOOST_BASE_PROGRAM],
|
||||||
@@ -113,7 +113,8 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
|
|||||||
dnl are found, e.g. when only header-only libraries are installed!
|
dnl are found, e.g. when only header-only libraries are installed!
|
||||||
AS_CASE([${host_cpu}],
|
AS_CASE([${host_cpu}],
|
||||||
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
|
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
|
||||||
[ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
|
[mips*64*],[libsubdirs="lib64 lib32 lib lib64"],
|
||||||
|
[ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"],
|
||||||
[libsubdirs="lib"]
|
[libsubdirs="lib"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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 19
|
#serial 20
|
||||||
|
|
||||||
AC_DEFUN([AX_BOOST_SYSTEM],
|
AC_DEFUN([AX_BOOST_SYSTEM],
|
||||||
[
|
[
|
||||||
@@ -108,7 +108,7 @@ AC_DEFUN([AX_BOOST_SYSTEM],
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
if test "x$ax_lib" = "x"; then
|
if test "x$ax_lib" = "x"; then
|
||||||
AC_MSG_ERROR(Could not find a version of the library!)
|
AC_MSG_ERROR(Could not find a version of the Boost::System library!)
|
||||||
fi
|
fi
|
||||||
if test "x$link_system" = "xno"; then
|
if test "x$link_system" = "xno"; then
|
||||||
AC_MSG_ERROR(Could not link against $ax_lib !)
|
AC_MSG_ERROR(Could not link against $ax_lib !)
|
||||||
|
|||||||
@@ -36,3 +36,16 @@ AC_DEFUN([FIND_QTDBUS],
|
|||||||
[AC_MSG_RESULT([not found])
|
[AC_MSG_RESULT([not found])
|
||||||
HAVE_QTDBUS=[false]])
|
HAVE_QTDBUS=[false]])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# DETECT_CPP11_PROGRAM()
|
||||||
|
# Detects if at least C++11 mode is enabled.
|
||||||
|
# --------------------------------------
|
||||||
|
AC_DEFUN([DETECT_CPP11_PROGRAM],
|
||||||
|
[AC_LANG_PROGRAM([[
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
#endif]],
|
||||||
|
[[]])
|
||||||
|
])
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ TEMPLATE = subdirs
|
|||||||
SUBDIRS += src
|
SUBDIRS += src
|
||||||
|
|
||||||
include(version.pri)
|
include(version.pri)
|
||||||
include(qm_gen.pri)
|
|
||||||
|
|
||||||
# Make target to create release tarball. Use 'make tarball'
|
# Make target to create release tarball. Use 'make tarball'
|
||||||
tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ &&
|
tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ &&
|
||||||
@@ -18,6 +17,10 @@ tarball.commands += rm -fR $${PROJECT_NAME}-$${PROJECT_VERSION}
|
|||||||
|
|
||||||
QMAKE_EXTRA_TARGETS += tarball
|
QMAKE_EXTRA_TARGETS += tarball
|
||||||
|
|
||||||
|
# Translations included here (at top level) is to avoid regenerating the .qm files
|
||||||
|
# every time when src.pro is processed
|
||||||
|
include(src/lang/lang.pri)
|
||||||
|
|
||||||
# For Qt Creator beautifier
|
# For Qt Creator beautifier
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
uncrustify.cfg
|
uncrustify.cfg
|
||||||
|
|||||||
21
qm_gen.pri
21
qm_gen.pri
@@ -1,21 +0,0 @@
|
|||||||
TS_IN = $$fromfile(src/src.pro,TRANSLATIONS)
|
|
||||||
TS_IN_NOEXT = $$replace(TS_IN,".ts","")
|
|
||||||
|
|
||||||
isEmpty(QMAKE_LRELEASE) {
|
|
||||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
|
||||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
|
||||||
unix {
|
|
||||||
equals(QT_MAJOR_VERSION, 5) {
|
|
||||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt5 }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message("Building translations")
|
|
||||||
for(L,TS_IN_NOEXT) {
|
|
||||||
message("Processing $${L}")
|
|
||||||
system("$$QMAKE_LRELEASE -silent src/$${L}.ts -qm src/$${L}.qm")
|
|
||||||
!exists("src/$${L}.qm"):error("Building translations failed, cannot continue")
|
|
||||||
}
|
|
||||||
@@ -1,40 +1,53 @@
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
set(CMAKE_CXX_STANDARD "11")
|
|
||||||
add_definitions(-DBOOST_NO_CXX11_RVALUE_REFERENCES)
|
# If C++14 is available, use it as libtorent ABI depends on 11/14 version
|
||||||
|
if (cxx_std_14 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||||
|
message(STATUS "Building in C++14 mode")
|
||||||
|
set(CMAKE_CXX_STANDARD "14")
|
||||||
|
else()
|
||||||
|
message(STATUS "Building in C++11 mode")
|
||||||
|
set(CMAKE_CXX_STANDARD "11")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(MacroQbtCompilerSettings)
|
include(MacroQbtCompilerSettings)
|
||||||
qbt_set_compiler_options()
|
qbt_set_compiler_options()
|
||||||
|
|
||||||
include(MacroLinkQtComponents)
|
|
||||||
include(QbtTargetSources)
|
include(QbtTargetSources)
|
||||||
|
|
||||||
|
find_package(Boost ${requiredBoostVersion} REQUIRED)
|
||||||
find_package(LibtorrentRasterbar REQUIRED)
|
find_package(LibtorrentRasterbar REQUIRED)
|
||||||
|
|
||||||
# Qt
|
if (Boost_VERSION VERSION_LESS 106000)
|
||||||
list(APPEND QBT_QT_COMPONENTS Core Network Xml)
|
add_definitions(-DBOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
if (GUI)
|
endif()
|
||||||
list (APPEND QBT_QT_COMPONENTS Gui Svg Widgets)
|
|
||||||
if (WIN32)
|
|
||||||
list (APPEND QBT_QT_COMPONENTS WinExtras)
|
|
||||||
endif(WIN32)
|
|
||||||
if (APPLE)
|
|
||||||
list (APPEND QBT_GUI_OPTIONAL_LINK_LIBRARIES objc)
|
|
||||||
list (APPEND QBT_QT_COMPONENTS MacExtras)
|
|
||||||
endif (APPLE)
|
|
||||||
endif (GUI)
|
|
||||||
if (DBUS)
|
|
||||||
list (APPEND QBT_QT_COMPONENTS DBus)
|
|
||||||
endif (DBUS)
|
|
||||||
find_package(Qt5 5.5.1 COMPONENTS ${QBT_QT_COMPONENTS} REQUIRED)
|
|
||||||
|
|
||||||
if (GUI AND APPLE)
|
find_package(Qt5 ${requiredQtVersion} REQUIRED COMPONENTS Core Network Xml LinguistTools)
|
||||||
# Fix MOC inability to detect macOS. This seems to only affect cmake.
|
find_package(Qt5Widgets ${requiredQtVersion})
|
||||||
# Relevant issue: https://bugreports.qt.io/browse/QTBUG-58325
|
if (Qt5Widgets_FOUND)
|
||||||
set(CMAKE_AUTOMOC_MOC_OPTIONS ${CMAKE_AUTOMOC_MOC_OPTIONS} -DQ_OS_MAC)
|
find_package(Qt5DBus ${requiredQtVersion})
|
||||||
endif ()
|
else()
|
||||||
|
add_definitions(-DDISABLE_GUI)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_package_properties(Qt5Widgets PROPERTIES
|
||||||
|
DESCRIPTION "Set of components for creating classic desktop-style UIs for the Qt5 framework"
|
||||||
|
PURPOSE "Enables qBittorrent GUI. Unneeded for headless configuration."
|
||||||
|
TYPE OPTIONAL
|
||||||
|
)
|
||||||
|
|
||||||
|
set_package_properties(Qt5DBus PROPERTIES
|
||||||
|
DESCRIPTION "Qt5 module for inter-process communication over the D-Bus protocol"
|
||||||
|
PURPOSE "Enables communication with other system components (e.g. notification service) via D-Bus. "
|
||||||
|
TYPE RECOMMENDED
|
||||||
|
)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC True)
|
set(CMAKE_AUTOMOC True)
|
||||||
list(APPEND CMAKE_AUTORCC_OPTIONS -compress 9 -threshold 5)
|
list(APPEND CMAKE_AUTORCC_OPTIONS -compress 9 -threshold 5)
|
||||||
|
if (APPLE)
|
||||||
|
# Workaround CMake bug (autogen does not pass required parameters to moc)
|
||||||
|
# Relevant issue: https://gitlab.kitware.com/cmake/cmake/issues/18041
|
||||||
|
list(APPEND CMAKE_AUTOMOC_MOC_OPTIONS -DQ_OS_MAC -DQ_OS_DARWIN)
|
||||||
|
endif ()
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
@@ -43,56 +56,34 @@ add_definitions(-DQT_NO_CAST_TO_ASCII)
|
|||||||
# Efficient construction for QString & QByteArray (Qt >= 4.8)
|
# Efficient construction for QString & QByteArray (Qt >= 4.8)
|
||||||
add_definitions(-DQT_USE_QSTRINGBUILDER)
|
add_definitions(-DQT_USE_QSTRINGBUILDER)
|
||||||
|
|
||||||
if (NOT GUI)
|
if (CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
add_definitions(-DDISABLE_GUI -DDISABLE_COUNTRIES_RESOLUTION)
|
|
||||||
endif (NOT GUI)
|
|
||||||
|
|
||||||
if (NOT WEBUI)
|
|
||||||
add_definitions(-DDISABLE_WEBUI)
|
|
||||||
endif (NOT WEBUI)
|
|
||||||
|
|
||||||
if (STACKTRACE)
|
|
||||||
add_definitions(-DSTACKTRACE)
|
|
||||||
endif(STACKTRACE)
|
|
||||||
# nogui {
|
|
||||||
# TARGET = qbittorrent-nox
|
|
||||||
# } else {
|
|
||||||
# CONFIG(static) {
|
|
||||||
# DEFINES += QBT_STATIC_QT
|
|
||||||
# QTPLUGIN += qico
|
|
||||||
# }
|
|
||||||
# TARGET = qbittorrent
|
|
||||||
# }
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
add_compile_options(-Wformat -Wformat-security)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
message(STATUS "Project is built in DEBUG mode.")
|
message(STATUS "Project is built in DEBUG mode.")
|
||||||
else (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
else()
|
||||||
message(STATUS "Project is built in RELEASE mode.")
|
message(STATUS "Project is built in RELEASE mode.")
|
||||||
message(STATUS "Disabling debug output.")
|
message(STATUS "Disabling debug output.")
|
||||||
add_definitions(-DQT_NO_DEBUG_OUTPUT)
|
add_definitions(-DQT_NO_DEBUG_OUTPUT)
|
||||||
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
endif()
|
||||||
|
|
||||||
set(QBT_USE_GUI ${GUI})
|
|
||||||
set(QBT_USE_WEBUI ${WEBUI})
|
|
||||||
|
|
||||||
configure_file(config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
if (SYSTEM_QTSINGLEAPPLICATION)
|
find_package(QtSingleApplication)
|
||||||
find_package(QtSingleApplication REQUIRED)
|
set_package_properties(QtSingleApplication PROPERTIES
|
||||||
else (SYSTEM_QTSINGLEAPPLICATION)
|
URL "https://code.qt.io/cgit/qt-solutions/qt-solutions.git/"
|
||||||
|
DESCRIPTION "Qt library to start applications only once per user"
|
||||||
|
TYPE RECOMMENDED
|
||||||
|
PURPOSE "Use the system qtsingleapplication library or shipped one otherwise"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (NOT QtSingleApplication_FOUND)
|
||||||
add_subdirectory(app/qtsingleapplication)
|
add_subdirectory(app/qtsingleapplication)
|
||||||
endif (SYSTEM_QTSINGLEAPPLICATION)
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(app)
|
add_subdirectory(app)
|
||||||
add_subdirectory(base)
|
add_subdirectory(base)
|
||||||
|
|
||||||
if (GUI)
|
if (Qt5Widgets_FOUND)
|
||||||
add_subdirectory(gui)
|
add_subdirectory(gui)
|
||||||
endif (GUI)
|
endif ()
|
||||||
|
|
||||||
if (WEBUI)
|
if (WEBUI)
|
||||||
add_subdirectory(webui)
|
add_subdirectory(webui)
|
||||||
|
|||||||
@@ -1,43 +1,41 @@
|
|||||||
project(qbt_executable)
|
add_executable(qBittorrent
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
set(QBT_APP_HEADERS
|
|
||||||
application.h
|
application.h
|
||||||
cmdoptions.h
|
cmdoptions.h
|
||||||
filelogger.h
|
filelogger.h
|
||||||
)
|
upgrade.h
|
||||||
|
|
||||||
set(QBT_APP_SOURCES
|
|
||||||
application.cpp
|
application.cpp
|
||||||
cmdoptions.cpp
|
cmdoptions.cpp
|
||||||
filelogger.cpp
|
filelogger.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_include_directories(qBittorrent PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
target_link_libraries(qBittorrent
|
||||||
|
PRIVATE
|
||||||
|
qbt_base
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(qBittorrent
|
||||||
|
PROPERTIES
|
||||||
|
AUTOUIC True
|
||||||
|
AUTORCC True
|
||||||
|
MACOSX_BUNDLE True
|
||||||
|
)
|
||||||
|
|
||||||
# translations
|
# translations
|
||||||
|
include(QbtTranslations)
|
||||||
|
|
||||||
file(GLOB QBT_TS_FILES ../lang/*.ts)
|
file(GLOB QBT_TS_FILES ../lang/*.ts)
|
||||||
get_filename_component(QBT_QM_FILES_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/../lang" ABSOLUTE)
|
qbt_add_translations(qBittorrent QRC_FILE "../lang/lang.qrc" TS_FILES ${QBT_TS_FILES})
|
||||||
set_source_files_properties(${QBT_TS_FILES} PROPERTIES OUTPUT_LOCATION "${QBT_QM_FILES_BINARY_DIR}")
|
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS LinguistTools REQUIRED)
|
if (WEBUI)
|
||||||
qt5_add_translation(QBT_QM_FILES ${QBT_TS_FILES})
|
file(GLOB QBT_WEBUI_TS_FILES ../webui/www/translations/*.ts)
|
||||||
|
qbt_add_translations(qBittorrent QRC_FILE "../webui/www/translations/webui_translations.qrc" TS_FILES ${QBT_WEBUI_TS_FILES})
|
||||||
get_filename_component(_lang_qrc_src "${CMAKE_CURRENT_SOURCE_DIR}/../lang.qrc" ABSOLUTE)
|
endif()
|
||||||
get_filename_component(_lang_qrc_dst "${CMAKE_CURRENT_BINARY_DIR}/../lang.qrc" ABSOLUTE)
|
|
||||||
get_filename_component(_lang_qrc_dst_dir "${CMAKE_CURRENT_BINARY_DIR}/../" ABSOLUTE)
|
|
||||||
|
|
||||||
message(STATUS "copying ${_lang_qrc_src} -> ${_lang_qrc_dst}")
|
|
||||||
file(COPY ${_lang_qrc_src} DESTINATION ${_lang_qrc_dst_dir})
|
|
||||||
|
|
||||||
set_source_files_properties("${_lang_qrc_dst}" PROPERTIES GENERATED True)
|
|
||||||
foreach(qm_file ${QBT_QM_FILES})
|
|
||||||
set_source_files_properties("${_lang_qrc_dst}" PROPERTIES OBJECT_DEPENDS ${qm_file})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(QBT_APP_RESOURCES
|
set(QBT_APP_RESOURCES
|
||||||
../icons.qrc
|
../icons/icons.qrc
|
||||||
../searchengine.qrc
|
../searchengine/searchengine.qrc
|
||||||
"${_lang_qrc_dst}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# With AUTORCC rcc is ran by cmake before language files are generated,
|
# With AUTORCC rcc is ran by cmake before language files are generated,
|
||||||
@@ -46,51 +44,41 @@ qt5_add_resources(QBT_APP_RESOURCE_SOURCE ${QBT_APP_RESOURCES})
|
|||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
list (APPEND QBT_APP_SOURCES ../qbittorrent_mingw.rc)
|
target_sources(qBittorrent PRIVATE ../qbittorrent_mingw.rc)
|
||||||
else (MINGW)
|
else (MINGW)
|
||||||
list (APPEND QBT_APP_SOURCES ../qbittorrent.rc)
|
target_sources(qBittorrent PRIVATE ../qbittorrent.rc)
|
||||||
endif (MINGW)
|
endif (MINGW)
|
||||||
list(APPEND QBT_APP_SOURCES ../qbittorrent.exe.manifest)
|
target_sources(qBittorrent PRIVATE ../qbittorrent.exe.manifest)
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
|
||||||
if (STACKTRACE)
|
if (STACKTRACE)
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
list(APPEND QBT_APP_HEADERS stacktrace.h)
|
target_sources(qBittorrent PRIVATE stacktrace.h)
|
||||||
else (UNIX)
|
else (UNIX)
|
||||||
list(APPEND QBT_APP_HEADERS stacktrace_win.h)
|
target_sources(qBittorrent PRIVATE stacktrace_win.h)
|
||||||
if (GUI)
|
if (Qt5Widgets_FOUND)
|
||||||
list(APPEND QBT_APP_HEADERS stacktrace_win_dlg.h)
|
target_sources(qBittorrent PRIVATE stacktracedialog.h)
|
||||||
endif (GUI)
|
endif (Qt5Widgets_FOUND)
|
||||||
endif (UNIX)
|
endif (UNIX)
|
||||||
endif (STACKTRACE)
|
endif (STACKTRACE)
|
||||||
|
|
||||||
# usesystemqtsingleapplication {
|
|
||||||
# nogui {
|
|
||||||
# CONFIG += qtsinglecoreapplication
|
|
||||||
# } else {
|
|
||||||
# CONFIG += qtsingleapplication
|
|
||||||
# }
|
|
||||||
# } else {
|
|
||||||
# nogui {
|
|
||||||
# include(qtsingleapplication/qtsinglecoreapplication.pri)
|
|
||||||
# } else {
|
|
||||||
# include(qtsingleapplication/qtsingleapplication.pri)
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|
||||||
# upgrade code
|
if (Qt5Widgets_FOUND)
|
||||||
list(APPEND QBT_APP_HEADERS upgrade.h)
|
target_link_libraries(qBittorrent PRIVATE qbt_searchengine qbt_gui)
|
||||||
list(APPEND QBT_TARGET_LIBRARIES qbt_base)
|
set_target_properties(qBittorrent
|
||||||
|
PROPERTIES
|
||||||
if (GUI)
|
OUTPUT_NAME qbittorrent
|
||||||
list(APPEND QBT_TARGET_LIBRARIES qbt_searchengine qbt_gui)
|
WIN32_EXECUTABLE True
|
||||||
include_directories(../gui
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/../gui
|
|
||||||
)
|
)
|
||||||
endif (GUI)
|
else(Qt5Widgets_FOUND)
|
||||||
|
set_target_properties(qBittorrent
|
||||||
|
PROPERTIES
|
||||||
|
OUTPUT_NAME qbittorrent-nox
|
||||||
|
)
|
||||||
|
endif (Qt5Widgets_FOUND)
|
||||||
|
|
||||||
if (WEBUI)
|
if (WEBUI)
|
||||||
list(APPEND QBT_TARGET_LIBRARIES qbt_webui)
|
target_link_libraries(qBittorrent PRIVATE qbt_webui)
|
||||||
endif (WEBUI)
|
endif (WEBUI)
|
||||||
|
|
||||||
# we have to include resources into the bundle
|
# we have to include resources into the bundle
|
||||||
@@ -142,30 +130,11 @@ if (APPLE)
|
|||||||
PROPERTIES MACOSX_PACKAGE_LOCATION translations)
|
PROPERTIES MACOSX_PACKAGE_LOCATION translations)
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|
||||||
add_executable(qBittorrent ${QBT_APP_HEADERS} ${QBT_APP_SOURCES} ${QBT_QM_FILES} ${QBT_APP_RESOURCE_SOURCE})
|
target_sources(qBittorrent PRIVATE ${QBT_QM_FILES} ${QBT_APP_RESOURCE_SOURCE})
|
||||||
if (GUI)
|
|
||||||
set_target_properties(qBittorrent
|
|
||||||
PROPERTIES
|
|
||||||
OUTPUT_NAME qbittorrent
|
|
||||||
WIN32_EXECUTABLE True
|
|
||||||
)
|
|
||||||
else (GUI)
|
|
||||||
set_target_properties(qBittorrent
|
|
||||||
PROPERTIES
|
|
||||||
OUTPUT_NAME qbittorrent-nox
|
|
||||||
)
|
|
||||||
endif (GUI)
|
|
||||||
|
|
||||||
set_target_properties(qBittorrent
|
|
||||||
PROPERTIES
|
|
||||||
AUTOUIC True
|
|
||||||
AUTORCC True
|
|
||||||
MACOSX_BUNDLE True
|
|
||||||
)
|
|
||||||
|
|
||||||
get_target_property(QBT_EXECUTABLE_NAME qBittorrent OUTPUT_NAME)
|
get_target_property(QBT_EXECUTABLE_NAME qBittorrent OUTPUT_NAME)
|
||||||
|
|
||||||
target_link_libraries(qBittorrent ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)
|
target_link_libraries(qBittorrent PRIVATE ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(qbt_BUNDLE_NAME ${QBT_EXECUTABLE_NAME})
|
set(qbt_BUNDLE_NAME ${QBT_EXECUTABLE_NAME})
|
||||||
@@ -186,6 +155,7 @@ install(TARGETS qBittorrent
|
|||||||
BUNDLE DESTINATION .
|
BUNDLE DESTINATION .
|
||||||
COMPONENT runtime)
|
COMPONENT runtime)
|
||||||
|
|
||||||
if (GUI AND APPLE)
|
if (Qt5Widgets_FOUND AND APPLE)
|
||||||
|
find_package(Qt5Svg REQUIRED)
|
||||||
include(bundle)
|
include(bundle)
|
||||||
endif (GUI AND APPLE)
|
endif (Qt5Widgets_FOUND AND APPLE)
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ stacktrace {
|
|||||||
else {
|
else {
|
||||||
HEADERS += $$PWD/stacktrace_win.h
|
HEADERS += $$PWD/stacktrace_win.h
|
||||||
!nogui {
|
!nogui {
|
||||||
HEADERS += $$PWD/stacktrace_win_dlg.h
|
HEADERS += $$PWD/stacktracedialog.h
|
||||||
FORMS += $$PWD/stacktrace_win_dlg.ui
|
FORMS += $$PWD/stacktracedialog.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,20 +31,38 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#include <memory>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QAtomicInt>
|
#include <QAtomicInt>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <memory>
|
||||||
|
#include <Shellapi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
#include <QMessageBox>
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QSessionManager>
|
||||||
|
#include <QSharedMemory>
|
||||||
|
#endif // Q_OS_WIN
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <QFileOpenEvent>
|
||||||
|
#endif // Q_OS_MAC
|
||||||
|
#include "addnewtorrentdialog.h"
|
||||||
|
#include "gui/guiiconprovider.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "shutdownconfirmdialog.h"
|
||||||
|
#else // DISABLE_GUI
|
||||||
|
#include <cstdio>
|
||||||
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
|
#include "base/exceptions.h"
|
||||||
#include "base/iconprovider.h"
|
#include "base/iconprovider.h"
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
@@ -56,34 +74,13 @@
|
|||||||
#include "base/rss/rss_autodownloader.h"
|
#include "base/rss/rss_autodownloader.h"
|
||||||
#include "base/rss/rss_session.h"
|
#include "base/rss/rss_session.h"
|
||||||
#include "base/scanfoldersmodel.h"
|
#include "base/scanfoldersmodel.h"
|
||||||
|
#include "base/search/searchpluginmanager.h"
|
||||||
#include "base/settingsstorage.h"
|
#include "base/settingsstorage.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 "filelogger.h"
|
#include "filelogger.h"
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#include <QSessionManager>
|
|
||||||
#include <QSharedMemory>
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
#include <QFileOpenEvent>
|
|
||||||
#include <QFont>
|
|
||||||
#include <QUrl>
|
|
||||||
#endif // Q_OS_MAC
|
|
||||||
#include "addnewtorrentdialog.h"
|
|
||||||
#include "gui/guiiconprovider.h"
|
|
||||||
#include "mainwindow.h"
|
|
||||||
#include "shutdownconfirmdlg.h"
|
|
||||||
#else // DISABLE_GUI
|
|
||||||
#include <cstdio>
|
|
||||||
#endif // DISABLE_GUI
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#include <Shellapi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DISABLE_WEBUI
|
#ifndef DISABLE_WEBUI
|
||||||
#include "webui/webui.h"
|
#include "webui/webui.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -93,7 +90,7 @@ namespace
|
|||||||
#define SETTINGS_KEY(name) "Application/" name
|
#define SETTINGS_KEY(name) "Application/" name
|
||||||
|
|
||||||
// FileLogger properties keys
|
// FileLogger properties keys
|
||||||
#define FILELOGGER_SETTINGS_KEY(name) SETTINGS_KEY("FileLogger/") name
|
#define FILELOGGER_SETTINGS_KEY(name) QStringLiteral(SETTINGS_KEY("FileLogger/") name)
|
||||||
const QString KEY_FILELOGGER_ENABLED = FILELOGGER_SETTINGS_KEY("Enabled");
|
const QString KEY_FILELOGGER_ENABLED = FILELOGGER_SETTINGS_KEY("Enabled");
|
||||||
const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path");
|
const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path");
|
||||||
const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup");
|
const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup");
|
||||||
@@ -102,13 +99,13 @@ namespace
|
|||||||
const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age");
|
const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age");
|
||||||
const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType");
|
const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType");
|
||||||
|
|
||||||
//just a shortcut
|
// just a shortcut
|
||||||
inline SettingsStorage *settings() { return SettingsStorage::instance(); }
|
inline SettingsStorage *settings() { return SettingsStorage::instance(); }
|
||||||
|
|
||||||
const QString LOG_FOLDER("logs");
|
const QString LOG_FOLDER = QStringLiteral("logs");
|
||||||
const char PARAMS_SEPARATOR[] = "|";
|
const QChar PARAMS_SEPARATOR = '|';
|
||||||
|
|
||||||
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QLatin1String("profile");
|
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QStringLiteral("profile");
|
||||||
|
|
||||||
const int MIN_FILELOG_SIZE = 1024; // 1KiB
|
const int MIN_FILELOG_SIZE = 1024; // 1KiB
|
||||||
const int MAX_FILELOG_SIZE = 1000 * 1024 * 1024; // 1000MiB
|
const int MAX_FILELOG_SIZE = 1000 * 1024 * 1024; // 1000MiB
|
||||||
@@ -127,6 +124,7 @@ Application::Application(const QString &id, int &argc, char **argv)
|
|||||||
qRegisterMetaType<Log::Msg>("Log::Msg");
|
qRegisterMetaType<Log::Msg>("Log::Msg");
|
||||||
|
|
||||||
setApplicationName("qBittorrent");
|
setApplicationName("qBittorrent");
|
||||||
|
setOrganizationDomain("qbittorrent.org");
|
||||||
validateCommandLineParameters();
|
validateCommandLineParameters();
|
||||||
|
|
||||||
QString profileDir = m_commandLineArgs.portableMode
|
QString profileDir = m_commandLineArgs.portableMode
|
||||||
@@ -148,14 +146,17 @@ Application::Application(const QString &id, int &argc, char **argv)
|
|||||||
#if !defined(DISABLE_GUI)
|
#if !defined(DISABLE_GUI)
|
||||||
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
||||||
setQuitOnLastWindowClosed(false);
|
setQuitOnLastWindowClosed(false);
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
||||||
|
setDesktopFileName("org.qbittorrent.qBittorrent");
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
|
#if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
|
||||||
connect(this, SIGNAL(commitDataRequest(QSessionManager &)), this, SLOT(shutdownCleanup(QSessionManager &)), Qt::DirectConnection);
|
connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(this, SIGNAL(messageReceived(const QString &)), SLOT(processMessage(const QString &)));
|
connect(this, &Application::messageReceived, this, &Application::processMessage);
|
||||||
connect(this, SIGNAL(aboutToQuit()), SLOT(cleanup()));
|
connect(this, &QCoreApplication::aboutToQuit, this, &Application::cleanup);
|
||||||
|
|
||||||
if (isFileLoggerEnabled())
|
if (isFileLoggerEnabled())
|
||||||
m_fileLogger = new FileLogger(fileLoggerPath(), isFileLoggerBackup(), fileLoggerMaxSize(), isFileLoggerDeleteOld(), fileLoggerAge(), static_cast<FileLogger::FileLogAgeType>(fileLoggerAgeType()));
|
m_fileLogger = new FileLogger(fileLoggerPath(), isFileLoggerBackup(), fileLoggerMaxSize(), isFileLoggerDeleteOld(), fileLoggerAge(), static_cast<FileLogger::FileLogAgeType>(fileLoggerAgeType()));
|
||||||
@@ -261,17 +262,17 @@ void Application::setFileLoggerAge(const int value)
|
|||||||
int Application::fileLoggerAgeType() const
|
int Application::fileLoggerAgeType() const
|
||||||
{
|
{
|
||||||
int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1).toInt();
|
int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1).toInt();
|
||||||
return (val < 0 || val > 2) ? 1 : val;
|
return ((val < 0) || (val > 2)) ? 1 : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerAgeType(const int value)
|
void Application::setFileLoggerAgeType(const int value)
|
||||||
{
|
{
|
||||||
settings()->storeValue(KEY_FILELOGGER_AGETYPE, (value < 0 || value > 2) ? 1 : value);
|
settings()->storeValue(KEY_FILELOGGER_AGETYPE, ((value < 0) || (value > 2)) ? 1 : value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::processMessage(const QString &message)
|
void Application::processMessage(const QString &message)
|
||||||
{
|
{
|
||||||
QStringList params = message.split(QLatin1String(PARAMS_SEPARATOR), QString::SkipEmptyParts);
|
QStringList params = message.split(PARAMS_SEPARATOR, QString::SkipEmptyParts);
|
||||||
// If Application is not running (i.e., other
|
// If Application is not running (i.e., other
|
||||||
// components are not ready) store params
|
// components are not ready) store params
|
||||||
if (m_running)
|
if (m_running)
|
||||||
@@ -290,9 +291,21 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
|||||||
std::sort(tags.begin(), tags.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
std::sort(tags.begin(), tags.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
||||||
program.replace("%G", tags.join(','));
|
program.replace("%G", tags.join(','));
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
const auto chopPathSep = [](const QString &str) -> QString
|
||||||
|
{
|
||||||
|
if (str.endsWith('\\'))
|
||||||
|
return str.mid(0, (str.length() -1));
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
program.replace("%F", chopPathSep(Utils::Fs::toNativePath(torrent->contentPath())));
|
||||||
|
program.replace("%R", chopPathSep(Utils::Fs::toNativePath(torrent->rootPath())));
|
||||||
|
program.replace("%D", chopPathSep(Utils::Fs::toNativePath(torrent->savePath())));
|
||||||
|
#else
|
||||||
program.replace("%F", Utils::Fs::toNativePath(torrent->contentPath()));
|
program.replace("%F", Utils::Fs::toNativePath(torrent->contentPath()));
|
||||||
program.replace("%R", Utils::Fs::toNativePath(torrent->rootPath()));
|
program.replace("%R", Utils::Fs::toNativePath(torrent->rootPath()));
|
||||||
program.replace("%D", Utils::Fs::toNativePath(torrent->savePath()));
|
program.replace("%D", Utils::Fs::toNativePath(torrent->savePath()));
|
||||||
|
#endif
|
||||||
program.replace("%C", QString::number(torrent->filesCount()));
|
program.replace("%C", QString::number(torrent->filesCount()));
|
||||||
program.replace("%Z", QString::number(torrent->totalSize()));
|
program.replace("%Z", QString::number(torrent->totalSize()));
|
||||||
program.replace("%T", torrent->currentTracker());
|
program.replace("%T", torrent->currentTracker());
|
||||||
@@ -301,9 +314,7 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
|||||||
Logger *logger = Logger::instance();
|
Logger *logger = Logger::instance();
|
||||||
logger->addMessage(tr("Torrent: %1, running external program, command: %2").arg(torrent->name(), program));
|
logger->addMessage(tr("Torrent: %1, running external program, command: %2").arg(torrent->name(), program));
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX)
|
#if defined(Q_OS_WIN)
|
||||||
QProcess::startDetached(QLatin1String("/bin/sh"), {QLatin1String("-c"), program});
|
|
||||||
#else
|
|
||||||
std::unique_ptr<wchar_t[]> programWchar(new wchar_t[program.length() + 1] {});
|
std::unique_ptr<wchar_t[]> programWchar(new wchar_t[program.length() + 1] {});
|
||||||
program.toWCharArray(programWchar.get());
|
program.toWCharArray(programWchar.get());
|
||||||
|
|
||||||
@@ -320,18 +331,24 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
|||||||
QProcess::startDetached(QString::fromWCharArray(args[0]), argList);
|
QProcess::startDetached(QString::fromWCharArray(args[0]), argList);
|
||||||
|
|
||||||
::LocalFree(args);
|
::LocalFree(args);
|
||||||
|
#else
|
||||||
|
// Cannot give users shell environment by default, as doing so could
|
||||||
|
// enable command injection via torrent name and other arguments
|
||||||
|
// (especially when some automated download mechanism has been setup).
|
||||||
|
// See: https://github.com/qbittorrent/qBittorrent/issues/10925
|
||||||
|
QProcess::startDetached(program);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::sendNotificationEmail(const BitTorrent::TorrentHandle *torrent)
|
void Application::sendNotificationEmail(const BitTorrent::TorrentHandle *torrent)
|
||||||
{
|
{
|
||||||
// Prepare mail content
|
// Prepare mail content
|
||||||
const QString content = tr("Torrent name: %1").arg(torrent->name()) + "\n"
|
const QString content = tr("Torrent name: %1").arg(torrent->name()) + '\n'
|
||||||
+ tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + "\n"
|
+ tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + '\n'
|
||||||
+ tr("Save path: %1").arg(torrent->savePath()) + "\n\n"
|
+ tr("Save path: %1").arg(torrent->savePath()) + "\n\n"
|
||||||
+ tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds")
|
+ tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds")
|
||||||
.arg(Utils::Misc::userFriendlyDuration(torrent->activeTime())) + "\n\n\n"
|
.arg(Utils::Misc::userFriendlyDuration(torrent->activeTime())) + "\n\n\n"
|
||||||
+ tr("Thank you for using qBittorrent.") + "\n";
|
+ tr("Thank you for using qBittorrent.") + '\n';
|
||||||
|
|
||||||
// Send the notification email
|
// Send the notification email
|
||||||
const Preferences *pref = Preferences::instance();
|
const Preferences *pref = Preferences::instance();
|
||||||
@@ -382,7 +399,7 @@ void Application::allTorrentsFinished()
|
|||||||
// do nothing & skip confirm
|
// do nothing & skip confirm
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!ShutdownConfirmDlg::askForConfirmation(m_window, action)) return;
|
if (!ShutdownConfirmDialog::askForConfirmation(m_window, action)) return;
|
||||||
}
|
}
|
||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
@@ -403,7 +420,7 @@ void Application::allTorrentsFinished()
|
|||||||
|
|
||||||
bool Application::sendParams(const QStringList ¶ms)
|
bool Application::sendParams(const QStringList ¶ms)
|
||||||
{
|
{
|
||||||
return sendMessage(params.join(QLatin1String(PARAMS_SEPARATOR)));
|
return sendMessage(params.join(PARAMS_SEPARATOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
// As program parameters, we can get paths or urls.
|
// As program parameters, we can get paths or urls.
|
||||||
@@ -421,7 +438,7 @@ void Application::processParams(const QStringList ¶ms)
|
|||||||
BitTorrent::AddTorrentParams torrentParams;
|
BitTorrent::AddTorrentParams torrentParams;
|
||||||
TriStateBool skipTorrentDialog;
|
TriStateBool skipTorrentDialog;
|
||||||
|
|
||||||
foreach (QString param, params) {
|
for (QString param : params) {
|
||||||
param = param.trimmed();
|
param = param.trimmed();
|
||||||
|
|
||||||
// Process strings indicating options specified by the user.
|
// Process strings indicating options specified by the user.
|
||||||
@@ -488,30 +505,46 @@ int Application::exec(const QStringList ¶ms)
|
|||||||
GuiIconProvider::initInstance();
|
GuiIconProvider::initInstance();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BitTorrent::Session::initInstance();
|
try {
|
||||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(torrentFinished(BitTorrent::TorrentHandle *const)));
|
BitTorrent::Session::initInstance();
|
||||||
connect(BitTorrent::Session::instance(), SIGNAL(allTorrentsFinished()), SLOT(allTorrentsFinished()), Qt::QueuedConnection);
|
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentFinished, this, &Application::torrentFinished);
|
||||||
|
connect(BitTorrent::Session::instance(), &BitTorrent::Session::allTorrentsFinished, this, &Application::allTorrentsFinished, Qt::QueuedConnection);
|
||||||
|
|
||||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||||
Net::GeoIPManager::initInstance();
|
Net::GeoIPManager::initInstance();
|
||||||
#endif
|
#endif
|
||||||
ScanFoldersModel::initInstance(this);
|
ScanFoldersModel::initInstance(this);
|
||||||
|
|
||||||
#ifndef DISABLE_WEBUI
|
#ifndef DISABLE_WEBUI
|
||||||
m_webui = new WebUI;
|
m_webui = new WebUI;
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
if (m_webui->isErrored())
|
if (m_webui->isErrored())
|
||||||
return 1;
|
return 1;
|
||||||
connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); });
|
connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); });
|
||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
#endif // DISABLE_WEBUI
|
#endif // DISABLE_WEBUI
|
||||||
|
|
||||||
new RSS::Session; // create RSS::Session singleton
|
new RSS::Session; // create RSS::Session singleton
|
||||||
new RSS::AutoDownloader; // create RSS::AutoDownloader singleton
|
new RSS::AutoDownloader; // create RSS::AutoDownloader singleton
|
||||||
|
}
|
||||||
|
catch (const RuntimeError &err) {
|
||||||
|
#ifdef DISABLE_GUI
|
||||||
|
fprintf(stderr, "%s", err.what());
|
||||||
|
#else
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setText(tr("Application failed to start."));
|
||||||
|
msgBox.setInformativeText(err.message());
|
||||||
|
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
||||||
|
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||||
|
msgBox.exec();
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
#ifndef DISABLE_WEBUI
|
#ifndef DISABLE_WEBUI
|
||||||
Preferences* const pref = Preferences::instance();
|
Preferences *const pref = Preferences::instance();
|
||||||
// Display some information to the user
|
// Display some information to the user
|
||||||
const QString mesg = QString("\n******** %1 ********\n").arg(tr("Information"))
|
const QString mesg = QString("\n******** %1 ********\n").arg(tr("Information"))
|
||||||
+ tr("To control qBittorrent, access the Web UI at %1")
|
+ tr("To control qBittorrent, access the Web UI at %1")
|
||||||
@@ -607,7 +640,7 @@ bool Application::notify(QObject *receiver, QEvent *event)
|
|||||||
|
|
||||||
void Application::initializeTranslation()
|
void Application::initializeTranslation()
|
||||||
{
|
{
|
||||||
Preferences* const pref = Preferences::instance();
|
Preferences *const pref = Preferences::instance();
|
||||||
// Load translation
|
// Load translation
|
||||||
QString localeStr = pref->getLocale();
|
QString localeStr = pref->getLocale();
|
||||||
|
|
||||||
@@ -660,7 +693,7 @@ void Application::shutdownCleanup(QSessionManager &manager)
|
|||||||
// According to the qt docs we shouldn't call quit() inside a slot.
|
// According to the qt docs we shouldn't call quit() inside a slot.
|
||||||
// aboutToQuit() is never emitted if the user hits "Cancel" in
|
// aboutToQuit() is never emitted if the user hits "Cancel" in
|
||||||
// the above dialog.
|
// the above dialog.
|
||||||
QTimer::singleShot(0, qApp, SLOT(quit()));
|
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -673,7 +706,7 @@ void Application::cleanup()
|
|||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
if (m_window) {
|
if (m_window) {
|
||||||
// Hide the window and not leave it on screen as
|
// Hide the window and don't leave it on screen as
|
||||||
// unresponsive. Also for Windows take the WinId
|
// unresponsive. Also for Windows take the WinId
|
||||||
// after it's hidden, because hide() may cause a
|
// after it's hidden, because hide() may cause a
|
||||||
// WinId change.
|
// WinId change.
|
||||||
@@ -717,6 +750,7 @@ void Application::cleanup()
|
|||||||
delete m_fileLogger;
|
delete m_fileLogger;
|
||||||
Logger::freeInstance();
|
Logger::freeInstance();
|
||||||
IconProvider::freeInstance();
|
IconProvider::freeInstance();
|
||||||
|
SearchPluginManager::freeInstance();
|
||||||
Utils::Fs::removeDirRecursive(Utils::Fs::tempPath());
|
Utils::Fs::removeDirRecursive(Utils::Fs::tempPath());
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
|
|||||||
@@ -40,15 +40,13 @@ typedef QtSingleApplication BaseApplication;
|
|||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QSessionManager;
|
class QSessionManager;
|
||||||
QT_END_NAMESPACE
|
|
||||||
#endif // Q_OS_WIN
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include "qtsinglecoreapplication.h"
|
#include "qtsinglecoreapplication.h"
|
||||||
typedef QtSingleCoreApplication BaseApplication;
|
typedef QtSingleCoreApplication BaseApplication;
|
||||||
#endif
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "cmdoptions.h"
|
#include "cmdoptions.h"
|
||||||
@@ -110,9 +108,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
bool event(QEvent *);
|
bool event(QEvent *) override;
|
||||||
#endif
|
#endif
|
||||||
bool notify(QObject* receiver, QEvent* event) override;
|
bool notify(QObject *receiver, QEvent *event) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -26,8 +26,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cmdoptions.h"
|
#include "cmdoptions.h"
|
||||||
@@ -43,6 +41,7 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "base/global.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
|
|
||||||
@@ -100,7 +99,7 @@ namespace
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Boolean option.
|
// Boolean option.
|
||||||
class BoolOption: protected Option
|
class BoolOption : protected Option
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr BoolOption(const char *name, char shortcut = 0)
|
constexpr BoolOption(const char *name, char shortcut = 0)
|
||||||
@@ -118,7 +117,7 @@ namespace
|
|||||||
{
|
{
|
||||||
QString val = env.value(envVarName());
|
QString val = env.value(envVarName());
|
||||||
// we accept "1" and "true" (upper or lower cased) as boolean 'true' values
|
// we accept "1" and "true" (upper or lower cased) as boolean 'true' values
|
||||||
return (val == QLatin1String("1") || val.toUpper() == QLatin1String("TRUE"));
|
return ((val == QLatin1String("1")) || (val.toUpper() == QLatin1String("TRUE")));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString usage() const
|
QString usage() const
|
||||||
@@ -137,7 +136,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Option with string value. May not have a shortcut
|
// Option with string value. May not have a shortcut
|
||||||
struct StringOption: protected Option
|
struct StringOption : protected Option
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr StringOption(const char *name)
|
constexpr StringOption(const char *name)
|
||||||
@@ -184,7 +183,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Option with integer value. May not have a shortcut
|
// Option with integer value. May not have a shortcut
|
||||||
class IntOption: protected StringOption
|
class IntOption : protected StringOption
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr IntOption(const char *name)
|
constexpr IntOption(const char *name)
|
||||||
@@ -230,7 +229,7 @@ namespace
|
|||||||
|
|
||||||
// Option that is explicitly set to true or false, and whose value is undefined when unspecified.
|
// Option that is explicitly set to true or false, and whose value is undefined when unspecified.
|
||||||
// May not have a shortcut.
|
// May not have a shortcut.
|
||||||
class TriStateBoolOption: protected Option
|
class TriStateBoolOption : protected Option
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr TriStateBoolOption(const char *name, bool defaultValue)
|
constexpr TriStateBoolOption(const char *name, bool defaultValue)
|
||||||
@@ -260,10 +259,10 @@ namespace
|
|||||||
else if (parts.size() == 2) {
|
else if (parts.size() == 2) {
|
||||||
QString val = parts[1];
|
QString val = parts[1];
|
||||||
|
|
||||||
if (val.toUpper() == QLatin1String("TRUE") || val == QLatin1String("1")) {
|
if ((val.toUpper() == QLatin1String("TRUE")) || (val == QLatin1String("1"))) {
|
||||||
return TriStateBool::True;
|
return TriStateBool::True;
|
||||||
}
|
}
|
||||||
else if (val.toUpper() == QLatin1String("FALSE") || val == QLatin1String("0")) {
|
else if ((val.toUpper() == QLatin1String("FALSE")) || (val == QLatin1String("0"))) {
|
||||||
return TriStateBool::False;
|
return TriStateBool::False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,10 +284,10 @@ namespace
|
|||||||
else if (val == QLatin1String("-1")) {
|
else if (val == QLatin1String("-1")) {
|
||||||
return TriStateBool::Undefined;
|
return TriStateBool::Undefined;
|
||||||
}
|
}
|
||||||
else if (val.toUpper() == QLatin1String("TRUE") || val == QLatin1String("1")) {
|
else if ((val.toUpper() == QLatin1String("TRUE")) || (val == QLatin1String("1"))) {
|
||||||
return TriStateBool::True;
|
return TriStateBool::True;
|
||||||
}
|
}
|
||||||
else if (val.toUpper() == QLatin1String("FALSE") || val == QLatin1String("0")) {
|
else if ((val.toUpper() == QLatin1String("FALSE")) || (val == QLatin1String("0"))) {
|
||||||
return TriStateBool::False;
|
return TriStateBool::False;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -360,7 +359,7 @@ QStringList QBtCommandLineParameters::paramList() const
|
|||||||
// the user has specified. Here we place special strings that are
|
// the user has specified. Here we place special strings that are
|
||||||
// almost certainly not going to collide with a file path or URL
|
// almost certainly not going to collide with a file path or URL
|
||||||
// specified by the user, and placing them at the beginning of the
|
// specified by the user, and placing them at the beginning of the
|
||||||
// string listr so that they will be processed before the list of
|
// string list so that they will be processed before the list of
|
||||||
// torrent paths or URLs.
|
// torrent paths or URLs.
|
||||||
|
|
||||||
if (!savePath.isEmpty())
|
if (!savePath.isEmpty())
|
||||||
@@ -404,9 +403,9 @@ QBtCommandLineParameters parseCommandLine(const QStringList &args)
|
|||||||
const QString &arg = args[i];
|
const QString &arg = args[i];
|
||||||
|
|
||||||
if ((arg.startsWith("--") && !arg.endsWith(".torrent"))
|
if ((arg.startsWith("--") && !arg.endsWith(".torrent"))
|
||||||
|| (arg.startsWith("-") && (arg.size() == 2))) {
|
|| (arg.startsWith('-') && (arg.size() == 2))) {
|
||||||
// Parse known parameters
|
// Parse known parameters
|
||||||
if ((arg == SHOW_HELP_OPTION)) {
|
if (arg == SHOW_HELP_OPTION) {
|
||||||
result.showHelp = true;
|
result.showHelp = true;
|
||||||
}
|
}
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
@@ -488,7 +487,7 @@ CommandLineParameterError::CommandLineParameterError(const QString &messageForUs
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& CommandLineParameterError::messageForUser() const
|
const QString &CommandLineParameterError::messageForUser() const
|
||||||
{
|
{
|
||||||
return m_messageForUser;
|
return m_messageForUser;
|
||||||
}
|
}
|
||||||
@@ -499,9 +498,9 @@ QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN
|
|||||||
QStringList lines = {words.first()};
|
QStringList lines = {words.first()};
|
||||||
int currentLineMaxLength = wrapAtColumn - initialIndentation;
|
int currentLineMaxLength = wrapAtColumn - initialIndentation;
|
||||||
|
|
||||||
foreach (const QString &word, words.mid(1)) {
|
for (const QString &word : asConst(words.mid(1))) {
|
||||||
if (lines.last().length() + word.length() + 1 < currentLineMaxLength) {
|
if (lines.last().length() + word.length() + 1 < currentLineMaxLength) {
|
||||||
lines.last().append(" " + word);
|
lines.last().append(' ' + word);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lines.append(QString(initialIndentation, ' ') + word);
|
lines.append(QString(initialIndentation, ' ') + word);
|
||||||
@@ -509,7 +508,7 @@ QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines.join("\n");
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
QString makeUsage(const QString &prgName)
|
QString makeUsage(const QString &prgName)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -26,8 +26,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef APP_OPTIONS_H
|
#ifndef APP_OPTIONS_H
|
||||||
@@ -62,11 +60,11 @@ struct QBtCommandLineParameters
|
|||||||
QStringList paramList() const;
|
QStringList paramList() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandLineParameterError: public std::runtime_error
|
class CommandLineParameterError : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CommandLineParameterError(const QString &messageForUser);
|
CommandLineParameterError(const QString &messageForUser);
|
||||||
const QString& messageForUser() const;
|
const QString &messageForUser() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_messageForUser;
|
const QString m_messageForUser;
|
||||||
|
|||||||
@@ -26,11 +26,14 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "filelogger.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include "filelogger.h"
|
|
||||||
|
#include "base/global.h"
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
|
|
||||||
@@ -41,17 +44,17 @@ FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize
|
|||||||
{
|
{
|
||||||
m_flusher.setInterval(0);
|
m_flusher.setInterval(0);
|
||||||
m_flusher.setSingleShot(true);
|
m_flusher.setSingleShot(true);
|
||||||
connect(&m_flusher, SIGNAL(timeout()), SLOT(flushLog()));
|
connect(&m_flusher, &QTimer::timeout, this, &FileLogger::flushLog);
|
||||||
|
|
||||||
changePath(path);
|
changePath(path);
|
||||||
if (deleteOld)
|
if (deleteOld)
|
||||||
this->deleteOld(age, ageType);
|
this->deleteOld(age, ageType);
|
||||||
|
|
||||||
const Logger* const logger = Logger::instance();
|
const Logger *const logger = Logger::instance();
|
||||||
foreach (const Log::Msg& msg, logger->getMessages())
|
for (const Log::Msg &msg : asConst(logger->getMessages()))
|
||||||
addLogMessage(msg);
|
addLogMessage(msg);
|
||||||
|
|
||||||
connect(logger, SIGNAL(newLogMessage(const Log::Msg &)), SLOT(addLogMessage(const Log::Msg &)));
|
connect(logger, &Logger::newLogMessage, this, &FileLogger::addLogMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLogger::~FileLogger()
|
FileLogger::~FileLogger()
|
||||||
@@ -61,7 +64,7 @@ FileLogger::~FileLogger()
|
|||||||
delete m_logFile;
|
delete m_logFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLogger::changePath(const QString& newPath)
|
void FileLogger::changePath(const QString &newPath)
|
||||||
{
|
{
|
||||||
QString tmpPath = Utils::Fs::fromNativePath(newPath);
|
QString tmpPath = Utils::Fs::fromNativePath(newPath);
|
||||||
QDir dir(tmpPath);
|
QDir dir(tmpPath);
|
||||||
@@ -83,21 +86,21 @@ void FileLogger::changePath(const QString& newPath)
|
|||||||
void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
|
void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
|
||||||
{
|
{
|
||||||
QDateTime date = QDateTime::currentDateTime();
|
QDateTime date = QDateTime::currentDateTime();
|
||||||
QDir dir(m_path);
|
QDir dir(Utils::Fs::branchPath(m_path));
|
||||||
|
|
||||||
switch (ageType) {
|
for (const QFileInfo &file : asConst(dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed))) {
|
||||||
case DAYS:
|
QDateTime modificationDate = file.lastModified();
|
||||||
date = date.addDays(age);
|
switch (ageType) {
|
||||||
break;
|
case DAYS:
|
||||||
case MONTHS:
|
modificationDate = modificationDate.addDays(age);
|
||||||
date = date.addMonths(age);
|
break;
|
||||||
break;
|
case MONTHS:
|
||||||
default:
|
modificationDate = modificationDate.addMonths(age);
|
||||||
date = date.addYears(age);
|
break;
|
||||||
}
|
default:
|
||||||
|
modificationDate = modificationDate.addYears(age);
|
||||||
foreach (const QFileInfo file, dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed)) {
|
}
|
||||||
if (file.lastModified() < date)
|
if (modificationDate > date)
|
||||||
break;
|
break;
|
||||||
Utils::Fs::forceRemove(file.absoluteFilePath());
|
Utils::Fs::forceRemove(file.absoluteFilePath());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,4 +76,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // FILELOGGER_H
|
#endif // FILELOGGER_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -25,8 +25,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -63,14 +61,14 @@ Q_IMPORT_PLUGIN(QICOPlugin)
|
|||||||
#include "stacktrace.h"
|
#include "stacktrace.h"
|
||||||
#else
|
#else
|
||||||
#include "stacktrace_win.h"
|
#include "stacktrace_win.h"
|
||||||
#include "stacktrace_win_dlg.h"
|
#include "stacktracedialog.h"
|
||||||
#endif // Q_OS_UNIX
|
#endif // Q_OS_UNIX
|
||||||
#endif //STACKTRACE
|
#endif //STACKTRACE
|
||||||
|
|
||||||
#include "application.h"
|
#include "base/preferences.h"
|
||||||
#include "base/profile.h"
|
#include "base/profile.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/preferences.h"
|
#include "application.h"
|
||||||
#include "cmdoptions.h"
|
#include "cmdoptions.h"
|
||||||
#include "upgrade.h"
|
#include "upgrade.h"
|
||||||
|
|
||||||
@@ -95,7 +93,7 @@ const char *sysSigName[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||||
void reportToUser(const char* str);
|
void reportToUser(const char *str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void displayVersion();
|
void displayVersion();
|
||||||
@@ -104,10 +102,6 @@ void displayBadArgMessage(const QString &message);
|
|||||||
|
|
||||||
#if !defined(DISABLE_GUI)
|
#if !defined(DISABLE_GUI)
|
||||||
void showSplashScreen();
|
void showSplashScreen();
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX)
|
|
||||||
void setupDpi();
|
|
||||||
#endif // Q_OS_UNIX
|
|
||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
@@ -122,10 +116,6 @@ int main(int argc, char *argv[])
|
|||||||
macMigratePlists();
|
macMigratePlists();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(DISABLE_GUI) && defined(Q_OS_UNIX)
|
|
||||||
setupDpi();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create Application
|
// Create Application
|
||||||
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
||||||
@@ -212,7 +202,7 @@ int main(int argc, char *argv[])
|
|||||||
// this is the default in Qt6
|
// this is the default in Qt6
|
||||||
app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
// Since Apple made difficult for users to set PATH, we set here for convenience.
|
// Since Apple made difficult for users to set PATH, we set here for convenience.
|
||||||
@@ -236,7 +226,7 @@ int main(int argc, char *argv[])
|
|||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
if (params.shouldDaemonize) {
|
if (params.shouldDaemonize) {
|
||||||
app.reset(); // Destroy current application
|
app.reset(); // Destroy current application
|
||||||
if ((daemon(1, 0) == 0)) {
|
if (daemon(1, 0) == 0) {
|
||||||
app.reset(new Application(appId, argc, argv));
|
app.reset(new Application(appId, argc, argv));
|
||||||
if (app->isRunning()) {
|
if (app->isRunning()) {
|
||||||
// Another instance had time to start.
|
// Another instance had time to start.
|
||||||
@@ -269,7 +259,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||||
void reportToUser(const char* str)
|
void reportToUser(const char *str)
|
||||||
{
|
{
|
||||||
const size_t strLen = strlen(str);
|
const size_t strLen = strlen(str);
|
||||||
if (write(STDERR_FILENO, str, strLen) < static_cast<ssize_t>(strLen)) {
|
if (write(STDERR_FILENO, str, strLen) < static_cast<ssize_t>(strLen)) {
|
||||||
@@ -308,7 +298,7 @@ void sigAbnormalHandler(int signum)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined Q_OS_WIN
|
#if defined Q_OS_WIN
|
||||||
StraceDlg dlg; // unsafe
|
StacktraceDialog dlg; // unsafe
|
||||||
dlg.setStacktraceString(QLatin1String(sigName), straceWin::getBacktrace());
|
dlg.setStacktraceString(QLatin1String(sigName), straceWin::getBacktrace());
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
#endif
|
#endif
|
||||||
@@ -321,25 +311,17 @@ void sigAbnormalHandler(int signum)
|
|||||||
#if !defined(DISABLE_GUI)
|
#if !defined(DISABLE_GUI)
|
||||||
void showSplashScreen()
|
void showSplashScreen()
|
||||||
{
|
{
|
||||||
QPixmap splash_img(":/icons/skin/splash.png");
|
QPixmap splashImg(":/icons/skin/splash.png");
|
||||||
QPainter painter(&splash_img);
|
QPainter painter(&splashImg);
|
||||||
QString version = QBT_VERSION;
|
QString version = QBT_VERSION;
|
||||||
painter.setPen(QPen(Qt::white));
|
painter.setPen(QPen(Qt::white));
|
||||||
painter.setFont(QFont("Arial", 22, QFont::Black));
|
painter.setFont(QFont("Arial", 22, QFont::Black));
|
||||||
painter.drawText(224 - painter.fontMetrics().width(version), 270, version);
|
painter.drawText(224 - painter.fontMetrics().width(version), 270, version);
|
||||||
QSplashScreen *splash = new QSplashScreen(splash_img);
|
QSplashScreen *splash = new QSplashScreen(splashImg);
|
||||||
splash->show();
|
splash->show();
|
||||||
QTimer::singleShot(1500, splash, SLOT(deleteLater()));
|
QTimer::singleShot(1500, splash, &QObject::deleteLater);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX)
|
|
||||||
void setupDpi()
|
|
||||||
{
|
|
||||||
if (qEnvironmentVariableIsEmpty("QT_AUTO_SCREEN_SCALE_FACTOR"))
|
|
||||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
|
||||||
}
|
|
||||||
#endif // Q_OS_UNIX
|
|
||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
void displayVersion()
|
void displayVersion()
|
||||||
@@ -347,7 +329,7 @@ void displayVersion()
|
|||||||
printf("%s %s\n", qUtf8Printable(qApp->applicationName()), QBT_VERSION);
|
printf("%s %s\n", qUtf8Printable(qApp->applicationName()), QBT_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayBadArgMessage(const QString& message)
|
void displayBadArgMessage(const QString &message)
|
||||||
{
|
{
|
||||||
QString help = QObject::tr("Run application with -h option to read about command line parameters.");
|
QString help = QObject::tr("Run application with -h option to read about command line parameters.");
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -366,7 +348,7 @@ void displayBadArgMessage(const QString& message)
|
|||||||
|
|
||||||
bool userAgreesWithLegalNotice()
|
bool userAgreesWithLegalNotice()
|
||||||
{
|
{
|
||||||
Preferences* const pref = Preferences::instance();
|
Preferences *const pref = Preferences::instance();
|
||||||
if (pref->getAcceptedLegal()) // Already accepted once
|
if (pref->getAcceptedLegal()) // Already accepted once
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -378,7 +360,7 @@ bool userAgreesWithLegalNotice()
|
|||||||
printf("%s", qUtf8Printable(eula));
|
printf("%s", qUtf8Printable(eula));
|
||||||
|
|
||||||
char ret = getchar(); // Read pressed key
|
char ret = getchar(); // Read pressed key
|
||||||
if (ret == 'y' || ret == 'Y') {
|
if ((ret == 'y') || (ret == 'Y')) {
|
||||||
// Save the answer
|
// Save the answer
|
||||||
pref->setAcceptedLegal(true);
|
pref->setAcceptedLegal(true);
|
||||||
return true;
|
return true;
|
||||||
@@ -388,16 +370,16 @@ bool userAgreesWithLegalNotice()
|
|||||||
msgBox.setText(QObject::tr("qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.\n\nNo further notices will be issued."));
|
msgBox.setText(QObject::tr("qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.\n\nNo further notices will be issued."));
|
||||||
msgBox.setWindowTitle(QObject::tr("Legal notice"));
|
msgBox.setWindowTitle(QObject::tr("Legal notice"));
|
||||||
msgBox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole);
|
msgBox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole);
|
||||||
QAbstractButton *agree_button = msgBox.addButton(QObject::tr("I Agree"), QMessageBox::AcceptRole);
|
QAbstractButton *agreeButton = msgBox.addButton(QObject::tr("I Agree"), QMessageBox::AcceptRole);
|
||||||
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
||||||
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
if (msgBox.clickedButton() == agree_button) {
|
if (msgBox.clickedButton() == agreeButton) {
|
||||||
// Save the answer
|
// Save the answer
|
||||||
pref->setAcceptedLegal(true);
|
pref->setAcceptedLegal(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,24 @@ set(QBT_QTSINGLEAPPLICATION_SOURCES
|
|||||||
qtlocalpeer.cpp
|
qtlocalpeer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (GUI)
|
if (Qt5Widgets_FOUND)
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsingleapplication.h)
|
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsingleapplication.h)
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsingleapplication.cpp)
|
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsingleapplication.cpp)
|
||||||
else (GUI)
|
else (Qt5Widgets_FOUND)
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsinglecoreapplication.h)
|
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsinglecoreapplication.h)
|
||||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp)
|
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp)
|
||||||
endif (GUI)
|
endif (Qt5Widgets_FOUND)
|
||||||
|
|
||||||
add_library(qtsingleapplication STATIC ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES})
|
add_library(qtsingleapplication STATIC ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES})
|
||||||
target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}")
|
target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}")
|
||||||
target_link_qt_components(qtsingleapplication Network)
|
target_link_libraries(qtsingleapplication PRIVATE Qt5::Network)
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
target_compile_options(qtsingleapplication PRIVATE "-w") # disable warning for 3rdparty code
|
target_compile_options(qtsingleapplication PRIVATE "-w") # disable warning for 3rdparty code
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (GUI)
|
if (Qt5Widgets_FOUND)
|
||||||
target_link_qt_components(qtsingleapplication Widgets)
|
target_link_libraries(qtsingleapplication PRIVATE Qt5::Widgets)
|
||||||
endif (GUI)
|
endif (Qt5Widgets_FOUND)
|
||||||
|
|
||||||
add_library(QtSingleApplication::QtSingleApplication ALIAS qtsingleapplication)
|
add_library(QtSingleApplication::QtSingleApplication ALIAS qtsingleapplication)
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
server = new QLocalServer(this);
|
server = new QLocalServer(this);
|
||||||
|
server->setSocketOptions(QLocalServer::UserAccessOption);
|
||||||
QString lockName = QDir(QDir::tempPath()).absolutePath()
|
QString lockName = QDir(QDir::tempPath()).absolutePath()
|
||||||
+ QLatin1Char('/') + socketName
|
+ QLatin1Char('/') + socketName
|
||||||
+ QLatin1String("-lockfile");
|
+ QLatin1String("-lockfile");
|
||||||
@@ -191,6 +192,12 @@ void QtLocalPeer::receiveConnection()
|
|||||||
QByteArray uMsg;
|
QByteArray uMsg;
|
||||||
quint32 remaining;
|
quint32 remaining;
|
||||||
ds >> remaining;
|
ds >> remaining;
|
||||||
|
if (remaining > 65535) {
|
||||||
|
// drop suspiciously large data
|
||||||
|
delete socket;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uMsg.resize(remaining);
|
uMsg.resize(remaining);
|
||||||
int got = 0;
|
int got = 0;
|
||||||
char* uMsgBuf = uMsg.data();
|
char* uMsgBuf = uMsg.data();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ bool straceWin::makeRelativePath(const QString& dir, QString& file)
|
|||||||
|
|
||||||
QString straceWin::getSourcePathAndLineNumber(HANDLE hProcess, DWORD64 addr)
|
QString straceWin::getSourcePathAndLineNumber(HANDLE hProcess, DWORD64 addr)
|
||||||
{
|
{
|
||||||
IMAGEHLP_LINE64 line = {0};
|
IMAGEHLP_LINE64 line {};
|
||||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
DWORD dwDisplacement = 0;
|
DWORD dwDisplacement = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -27,20 +27,21 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STACKTRACE_WIN_DLG_H
|
#ifndef STACKTRACEDIALOG_H
|
||||||
#define STACKTRACE_WIN_DLG_H
|
#define STACKTRACEDIALOG_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include "base/utils/misc.h"
|
|
||||||
#include "ui_stacktrace_win_dlg.h"
|
|
||||||
|
|
||||||
class StraceDlg : public QDialog, private Ui::errorDialog
|
#include "base/utils/misc.h"
|
||||||
|
#include "ui_stacktracedialog.h"
|
||||||
|
|
||||||
|
class StacktraceDialog : public QDialog, private Ui::StacktraceDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StraceDlg(QWidget *parent = nullptr)
|
StacktraceDialog(QWidget *parent = nullptr)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
@@ -83,4 +84,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // STACKTRACEDIALOG_H
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>errorDialog</class>
|
<class>StacktraceDialog</class>
|
||||||
<widget class="QDialog" name="errorDialog">
|
<widget class="QDialog" name="StacktraceDialog">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
@@ -29,34 +29,34 @@
|
|||||||
#ifndef UPGRADE_H
|
#ifndef UPGRADE_H
|
||||||
#define UPGRADE_H
|
#define UPGRADE_H
|
||||||
|
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
|
||||||
#include <libtorrent/bdecode.hpp>
|
|
||||||
#endif
|
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
#include <libtorrent/entry.hpp>
|
#include <libtorrent/entry.hpp>
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
|
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||||
|
#include <libtorrent/bdecode.hpp>
|
||||||
|
#else
|
||||||
#include <libtorrent/lazy_entry.hpp>
|
#include <libtorrent/lazy_entry.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#endif
|
#endif
|
||||||
#include <QRegExp>
|
|
||||||
#include <QString>
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
|
#include "base/preferences.h"
|
||||||
#include "base/profile.h"
|
#include "base/profile.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/preferences.h"
|
|
||||||
|
|
||||||
bool userAcceptsUpgrade()
|
bool userAcceptsUpgrade()
|
||||||
{
|
{
|
||||||
@@ -83,7 +83,7 @@ bool userAcceptsUpgrade()
|
|||||||
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||||
if (msgBox.exec() == QMessageBox::Ok)
|
if (msgBox.exec() == QMessageBox::Ok)
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -114,12 +114,28 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent =
|
|||||||
bool v3_3 = false;
|
bool v3_3 = false;
|
||||||
int queuePosition = 0;
|
int queuePosition = 0;
|
||||||
QString outFilePath = filepath;
|
QString outFilePath = filepath;
|
||||||
QRegExp rx(QLatin1String("([A-Fa-f0-9]{40})\\.fastresume\\.(\\d+)$"));
|
static const QRegularExpression rx(QLatin1String("([A-Fa-f0-9]{40})\\.fastresume\\.(.+)$"));
|
||||||
if (rx.indexIn(filepath) != -1) {
|
const QRegularExpressionMatch rxMatch = rx.match(filepath);
|
||||||
// old v3.3.x format
|
if (rxMatch.hasMatch()) {
|
||||||
queuePosition = rx.cap(2).toInt();
|
// Old v3.3.x format had a number at the end indicating the queue position.
|
||||||
|
// The naming scheme was '<infohash>.fastresume.<queueposition>'.
|
||||||
|
// However, QSaveFile, which uses QTemporaryFile internally, might leave
|
||||||
|
// non-commited files behind eg after a crash. These files have the
|
||||||
|
// naming scheme '<infohash>.fastresume.XXXXXX' where each X is a random
|
||||||
|
// character. So we detect if the last part is present. Then check if it
|
||||||
|
// is 6 chars long. If all the 6 chars are digits we assume it is an old
|
||||||
|
// v3.3.x format. Otherwise it is considered a non-commited fastresume
|
||||||
|
// and is deleted, because it may be a corrupted/incomplete fastresume.
|
||||||
|
// NOTE: When the upgrade code is removed, we must continue to perform
|
||||||
|
// cleanup of non-commited QSaveFile/QTemporaryFile fastresumes
|
||||||
|
queuePosition = rxMatch.captured(2).toInt();
|
||||||
|
if ((rxMatch.captured(2).size() == 6) && (queuePosition <= 99999)) {
|
||||||
|
Utils::Fs::forceRemove(filepath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
v3_3 = true;
|
v3_3 = true;
|
||||||
outFilePath.replace(QRegExp("\\.\\d+$"), "");
|
outFilePath.replace(QRegularExpression("\\.fastresume\\..+$"), ".fastresume");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
queuePosition = fastOld.dict_find_int_value("qBt-queuePosition", 0);
|
queuePosition = fastOld.dict_find_int_value("qBt-queuePosition", 0);
|
||||||
@@ -130,6 +146,15 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent =
|
|||||||
// in versions < 3.3 we have -1 for seeding torrents, so we convert it to 0
|
// in versions < 3.3 we have -1 for seeding torrents, so we convert it to 0
|
||||||
fastNew["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0);
|
fastNew["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0);
|
||||||
|
|
||||||
|
if (v3_3) {
|
||||||
|
QFileInfo oldFile(filepath);
|
||||||
|
QFileInfo newFile(outFilePath);
|
||||||
|
if (newFile.exists()
|
||||||
|
&& (oldFile.lastModified() < newFile.lastModified())) {
|
||||||
|
Utils::Fs::forceRemove(filepath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
QFile file2(outFilePath);
|
QFile file2(outFilePath);
|
||||||
QVector<char> out;
|
QVector<char> out;
|
||||||
libtorrent::bencode(std::back_inserter(out), fastNew);
|
libtorrent::bencode(std::back_inserter(out), fastNew);
|
||||||
@@ -154,9 +179,9 @@ bool upgrade(bool ask = true)
|
|||||||
|
|
||||||
// ****************************************************************************************
|
// ****************************************************************************************
|
||||||
// Silently converts old v3.3.x .fastresume files
|
// Silently converts old v3.3.x .fastresume files
|
||||||
QStringList backupFiles_3_3 = backupFolderDir.entryList(
|
const QStringList backupFiles_3_3 = backupFolderDir.entryList(
|
||||||
QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted);
|
QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted);
|
||||||
foreach (const QString &backupFile, backupFiles_3_3)
|
for (const QString &backupFile : backupFiles_3_3)
|
||||||
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
||||||
// ****************************************************************************************
|
// ****************************************************************************************
|
||||||
|
|
||||||
@@ -172,15 +197,17 @@ bool upgrade(bool ask = true)
|
|||||||
|
|
||||||
if (ask && !userAcceptsUpgrade()) return false;
|
if (ask && !userAcceptsUpgrade()) return false;
|
||||||
|
|
||||||
QStringList backupFiles = backupFolderDir.entryList(
|
const QStringList backupFiles = backupFolderDir.entryList(
|
||||||
QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted);
|
QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted);
|
||||||
QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
|
const QRegularExpression rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
|
||||||
foreach (QString backupFile, backupFiles) {
|
for (const QString &backupFile : backupFiles) {
|
||||||
if (rx.indexIn(backupFile) != -1) {
|
const QRegularExpressionMatch rxMatch = rx.match(backupFile);
|
||||||
if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[rx.cap(1)].toHash()))
|
if (rxMatch.hasMatch()) {
|
||||||
oldResumeData.remove(rx.cap(1));
|
const QString hashStr = rxMatch.captured(1);
|
||||||
|
if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[hashStr].toHash()))
|
||||||
|
oldResumeData.remove(hashStr);
|
||||||
else
|
else
|
||||||
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING);
|
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(hashStr), Log::WARNING);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent. Invalid fastresume file name: %1").arg(backupFile), Log::WARNING);
|
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent. Invalid fastresume file name: %1").arg(backupFile), Log::WARNING);
|
||||||
@@ -238,7 +265,7 @@ void migratePlistToIni(const QString &application)
|
|||||||
plistFile->setFallbacksEnabled(false);
|
plistFile->setFallbacksEnabled(false);
|
||||||
const QStringList plist = plistFile->allKeys();
|
const QStringList plist = plistFile->allKeys();
|
||||||
if (!plist.isEmpty()) {
|
if (!plist.isEmpty()) {
|
||||||
foreach (const QString &key, plist)
|
for (const QString &key : plist)
|
||||||
iniFile.setValue(key, plistFile->value(key));
|
iniFile.setValue(key, plistFile->value(key));
|
||||||
plistFile->clear();
|
plistFile->clear();
|
||||||
}
|
}
|
||||||
@@ -272,6 +299,6 @@ void migrateRSS()
|
|||||||
qBTRSSLegacy->remove("old_items");
|
qBTRSSLegacy->remove("old_items");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
#endif // UPGRADE_H
|
#endif // UPGRADE_H
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
find_package(ZLIB 1.2.5.2 REQUIRED)
|
find_package(ZLIB 1.2.5.2 REQUIRED)
|
||||||
|
|
||||||
set(QBT_BASE_HEADERS
|
add_library(qbt_base STATIC
|
||||||
|
# headers
|
||||||
bittorrent/addtorrentparams.h
|
bittorrent/addtorrentparams.h
|
||||||
bittorrent/cachestatus.h
|
bittorrent/cachestatus.h
|
||||||
|
bittorrent/filepriority.h
|
||||||
bittorrent/infohash.h
|
bittorrent/infohash.h
|
||||||
bittorrent/magneturi.h
|
bittorrent/magneturi.h
|
||||||
bittorrent/peerinfo.h
|
bittorrent/peerinfo.h
|
||||||
@@ -48,6 +50,7 @@ search/searchdownloadhandler.h
|
|||||||
search/searchhandler.h
|
search/searchhandler.h
|
||||||
search/searchpluginmanager.h
|
search/searchpluginmanager.h
|
||||||
utils/bytearray.h
|
utils/bytearray.h
|
||||||
|
utils/foreignapps.h
|
||||||
utils/fs.h
|
utils/fs.h
|
||||||
utils/gzip.h
|
utils/gzip.h
|
||||||
utils/misc.h
|
utils/misc.h
|
||||||
@@ -72,9 +75,9 @@ torrentfilter.h
|
|||||||
tristatebool.h
|
tristatebool.h
|
||||||
types.h
|
types.h
|
||||||
unicodestrings.h
|
unicodestrings.h
|
||||||
)
|
|
||||||
|
|
||||||
set(QBT_BASE_SOURCES
|
# sources
|
||||||
|
bittorrent/filepriority.cpp
|
||||||
bittorrent/infohash.cpp
|
bittorrent/infohash.cpp
|
||||||
bittorrent/magneturi.cpp
|
bittorrent/magneturi.cpp
|
||||||
bittorrent/peerinfo.cpp
|
bittorrent/peerinfo.cpp
|
||||||
@@ -117,6 +120,7 @@ search/searchdownloadhandler.cpp
|
|||||||
search/searchhandler.cpp
|
search/searchhandler.cpp
|
||||||
search/searchpluginmanager.cpp
|
search/searchpluginmanager.cpp
|
||||||
utils/bytearray.cpp
|
utils/bytearray.cpp
|
||||||
|
utils/foreignapps.cpp
|
||||||
utils/fs.cpp
|
utils/fs.cpp
|
||||||
utils/gzip.cpp
|
utils/gzip.cpp
|
||||||
utils/misc.cpp
|
utils/misc.cpp
|
||||||
@@ -137,16 +141,20 @@ torrentfilter.cpp
|
|||||||
tristatebool.cpp
|
tristatebool.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(qbt_base STATIC ${QBT_BASE_HEADERS} ${QBT_BASE_SOURCES})
|
target_link_libraries(qbt_base
|
||||||
target_link_libraries(qbt_base PRIVATE ZLIB::ZLIB PUBLIC LibtorrentRasterbar::LibTorrent)
|
PRIVATE
|
||||||
target_link_qt_components(qbt_base PUBLIC Core Network Xml)
|
ZLIB::ZLIB
|
||||||
|
PUBLIC
|
||||||
|
LibtorrentRasterbar::torrent-rasterbar
|
||||||
|
Qt5::Core Qt5::Network Qt5::Xml
|
||||||
|
)
|
||||||
|
|
||||||
if (GUI)
|
if (Qt5Widgets_FOUND)
|
||||||
target_link_libraries(qbt_base PUBLIC Qt5::Gui Qt5::Widgets)
|
target_link_libraries(qbt_base PUBLIC Qt5::Gui Qt5::Widgets)
|
||||||
endif (GUI)
|
endif (Qt5Widgets_FOUND)
|
||||||
|
|
||||||
if (DBUS)
|
if (Qt5DBus_FOUND)
|
||||||
target_link_qt_components(qbt_base PRIVATE DBus)
|
target_link_libraries(qbt_base PRIVATE Qt5::DBus)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ AsyncFileStorage::AsyncFileStorage(const QString &storageFolderPath, QObject *pa
|
|||||||
, m_lockFile(m_storageDir.absoluteFilePath(QStringLiteral("storage.lock")))
|
, m_lockFile(m_storageDir.absoluteFilePath(QStringLiteral("storage.lock")))
|
||||||
{
|
{
|
||||||
if (!m_storageDir.mkpath(m_storageDir.absolutePath()))
|
if (!m_storageDir.mkpath(m_storageDir.absolutePath()))
|
||||||
throw AsyncFileStorageError(
|
throw AsyncFileStorageError {tr("Could not create directory '%1'.")
|
||||||
QString("Could not create directory '%1'.").arg(m_storageDir.absolutePath()));
|
.arg(m_storageDir.absolutePath())};
|
||||||
|
|
||||||
// TODO: This folder locking approach does not work for UNIX systems. Implement it.
|
// TODO: This folder locking approach does not work for UNIX systems. Implement it.
|
||||||
if (!m_lockFile.open(QFile::WriteOnly))
|
if (!m_lockFile.open(QFile::WriteOnly))
|
||||||
throw AsyncFileStorageError(m_lockFile.errorString());
|
throw AsyncFileStorageError {m_lockFile.errorString()};
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncFileStorage::~AsyncFileStorage()
|
AsyncFileStorage::~AsyncFileStorage()
|
||||||
@@ -76,13 +76,3 @@ void AsyncFileStorage::store_impl(const QString &fileName, const QByteArray &dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncFileStorageError::AsyncFileStorageError(const QString &message)
|
|
||||||
: std::runtime_error(message.toUtf8().data())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AsyncFileStorageError::message() const
|
|
||||||
{
|
|
||||||
return what();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -28,22 +28,22 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class AsyncFileStorageError: public std::runtime_error
|
#include "base/exceptions.h"
|
||||||
|
|
||||||
|
class AsyncFileStorageError : public RuntimeError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AsyncFileStorageError(const QString &message);
|
using RuntimeError::RuntimeError;
|
||||||
QString message() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncFileStorage: public QObject
|
class AsyncFileStorage : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(AsyncFileStorage)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);
|
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ HEADERS += \
|
|||||||
$$PWD/asyncfilestorage.h \
|
$$PWD/asyncfilestorage.h \
|
||||||
$$PWD/bittorrent/addtorrentparams.h \
|
$$PWD/bittorrent/addtorrentparams.h \
|
||||||
$$PWD/bittorrent/cachestatus.h \
|
$$PWD/bittorrent/cachestatus.h \
|
||||||
|
$$PWD/bittorrent/filepriority.h \
|
||||||
$$PWD/bittorrent/infohash.h \
|
$$PWD/bittorrent/infohash.h \
|
||||||
$$PWD/bittorrent/magneturi.h \
|
$$PWD/bittorrent/magneturi.h \
|
||||||
$$PWD/bittorrent/peerinfo.h \
|
$$PWD/bittorrent/peerinfo.h \
|
||||||
@@ -64,6 +65,7 @@ HEADERS += \
|
|||||||
$$PWD/types.h \
|
$$PWD/types.h \
|
||||||
$$PWD/unicodestrings.h \
|
$$PWD/unicodestrings.h \
|
||||||
$$PWD/utils/bytearray.h \
|
$$PWD/utils/bytearray.h \
|
||||||
|
$$PWD/utils/foreignapps.h \
|
||||||
$$PWD/utils/fs.h \
|
$$PWD/utils/fs.h \
|
||||||
$$PWD/utils/gzip.h \
|
$$PWD/utils/gzip.h \
|
||||||
$$PWD/utils/misc.h \
|
$$PWD/utils/misc.h \
|
||||||
@@ -74,6 +76,7 @@ HEADERS += \
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/asyncfilestorage.cpp \
|
$$PWD/asyncfilestorage.cpp \
|
||||||
|
$$PWD/bittorrent/filepriority.cpp \
|
||||||
$$PWD/bittorrent/infohash.cpp \
|
$$PWD/bittorrent/infohash.cpp \
|
||||||
$$PWD/bittorrent/magneturi.cpp \
|
$$PWD/bittorrent/magneturi.cpp \
|
||||||
$$PWD/bittorrent/peerinfo.cpp \
|
$$PWD/bittorrent/peerinfo.cpp \
|
||||||
@@ -127,6 +130,7 @@ SOURCES += \
|
|||||||
$$PWD/torrentfilter.cpp \
|
$$PWD/torrentfilter.cpp \
|
||||||
$$PWD/tristatebool.cpp \
|
$$PWD/tristatebool.cpp \
|
||||||
$$PWD/utils/bytearray.cpp \
|
$$PWD/utils/bytearray.cpp \
|
||||||
|
$$PWD/utils/foreignapps.cpp \
|
||||||
$$PWD/utils/fs.cpp \
|
$$PWD/utils/fs.cpp \
|
||||||
$$PWD/utils/gzip.cpp \
|
$$PWD/utils/gzip.cpp \
|
||||||
$$PWD/utils/misc.cpp \
|
$$PWD/utils/misc.cpp \
|
||||||
|
|||||||
46
src/base/bittorrent/filepriority.cpp
Normal file
46
src/base/bittorrent/filepriority.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 "filepriority.h"
|
||||||
|
|
||||||
|
namespace BitTorrent
|
||||||
|
{
|
||||||
|
bool isValidFilePriority(const BitTorrent::FilePriority priority)
|
||||||
|
{
|
||||||
|
switch (priority) {
|
||||||
|
case BitTorrent::FilePriority::Ignored:
|
||||||
|
case BitTorrent::FilePriority::Normal:
|
||||||
|
case BitTorrent::FilePriority::High:
|
||||||
|
case BitTorrent::FilePriority::Maximum:
|
||||||
|
case BitTorrent::FilePriority::Mixed:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/base/bittorrent/filepriority.h
Normal file
43
src/base/bittorrent/filepriority.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace BitTorrent
|
||||||
|
{
|
||||||
|
enum class FilePriority : int
|
||||||
|
{
|
||||||
|
Ignored = 0,
|
||||||
|
Normal = 1,
|
||||||
|
High = 6,
|
||||||
|
Maximum = 7,
|
||||||
|
Mixed = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isValidFilePriority(BitTorrent::FilePriority priority);
|
||||||
|
}
|
||||||
@@ -26,9 +26,10 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include "infohash.h"
|
#include "infohash.h"
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
|
|
||||||
InfoHash::InfoHash()
|
InfoHash::InfoHash()
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
#ifndef BITTORRENT_INFOHASH_H
|
#ifndef BITTORRENT_INFOHASH_H
|
||||||
#define BITTORRENT_INFOHASH_H
|
#define BITTORRENT_INFOHASH_H
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <libtorrent/sha1_hash.hpp>
|
#include <libtorrent/sha1_hash.hpp>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,16 +26,17 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QByteArray>
|
#include "magneturi.h"
|
||||||
#include <QRegExp>
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
#include <libtorrent/error_code.hpp>
|
#include <libtorrent/error_code.hpp>
|
||||||
#include <libtorrent/magnet_uri.hpp>
|
#include <libtorrent/magnet_uri.hpp>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "magneturi.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -45,7 +46,7 @@ namespace
|
|||||||
rawBc = rawBc.mid(8); // skip bc://bt/
|
rawBc = rawBc.mid(8); // skip bc://bt/
|
||||||
rawBc = QByteArray::fromBase64(rawBc); // Decode base64
|
rawBc = QByteArray::fromBase64(rawBc); // Decode base64
|
||||||
// Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ
|
// Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ
|
||||||
QStringList parts = QString(rawBc).split("/");
|
QStringList parts = QString(rawBc).split('/');
|
||||||
if (parts.size() != 5) return QString();
|
if (parts.size() != 5) return QString();
|
||||||
|
|
||||||
QString filename = parts.at(1);
|
QString filename = parts.at(1);
|
||||||
@@ -69,8 +70,8 @@ MagnetUri::MagnetUri(const QString &source)
|
|||||||
qDebug("Creating magnet link from bc link");
|
qDebug("Creating magnet link from bc link");
|
||||||
m_url = bcLinkToMagnet(source);
|
m_url = bcLinkToMagnet(source);
|
||||||
}
|
}
|
||||||
else if (((source.size() == 40) && !source.contains(QRegExp("[^0-9A-Fa-f]")))
|
else if (((source.size() == 40) && !source.contains(QRegularExpression("[^0-9A-Fa-f]")))
|
||||||
|| ((source.size() == 32) && !source.contains(QRegExp("[^2-7A-Za-z]")))) {
|
|| ((source.size() == 32) && !source.contains(QRegularExpression("[^2-7A-Za-z]")))) {
|
||||||
m_url = "magnet:?xt=urn:btih:" + source;
|
m_url = "magnet:?xt=urn:btih:" + source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,10 +83,10 @@ MagnetUri::MagnetUri(const QString &source)
|
|||||||
m_hash = m_addTorrentParams.info_hash;
|
m_hash = m_addTorrentParams.info_hash;
|
||||||
m_name = QString::fromStdString(m_addTorrentParams.name);
|
m_name = QString::fromStdString(m_addTorrentParams.name);
|
||||||
|
|
||||||
foreach (const std::string &tracker, m_addTorrentParams.trackers)
|
for (const std::string &tracker : m_addTorrentParams.trackers)
|
||||||
m_trackers.append(QString::fromStdString(tracker));
|
m_trackers.append(QString::fromStdString(tracker));
|
||||||
|
|
||||||
foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds)
|
for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
|
||||||
m_urlSeeds.append(QUrl(urlSeed.c_str()));
|
m_urlSeeds.append(QUrl(urlSeed.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,8 +246,8 @@ QString PeerInfo::connectionType() const
|
|||||||
|
|
||||||
void PeerInfo::calcRelevance(const TorrentHandle *torrent)
|
void PeerInfo::calcRelevance(const TorrentHandle *torrent)
|
||||||
{
|
{
|
||||||
const QBitArray &allPieces = torrent->pieces();
|
const QBitArray allPieces = torrent->pieces();
|
||||||
const QBitArray &peerPieces = pieces();
|
const QBitArray peerPieces = pieces();
|
||||||
|
|
||||||
int localMissing = 0;
|
int localMissing = 0;
|
||||||
int remoteHaves = 0;
|
int remoteHaves = 0;
|
||||||
@@ -377,7 +377,7 @@ void PeerInfo::determineFlags()
|
|||||||
|
|
||||||
// L = Peer is local
|
// L = Peer is local
|
||||||
if (fromLSD()) {
|
if (fromLSD()) {
|
||||||
m_flags += "L";
|
m_flags += 'L';
|
||||||
flagsDescriptionList += "L = "
|
flagsDescriptionList += "L = "
|
||||||
+ tr("peer from LSD");
|
+ tr("peer from LSD");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ void BandwidthScheduler::start()
|
|||||||
|
|
||||||
bool BandwidthScheduler::isTimeForAlternative() const
|
bool BandwidthScheduler::isTimeForAlternative() const
|
||||||
{
|
{
|
||||||
const Preferences* const pref = Preferences::instance();
|
const Preferences *const pref = Preferences::instance();
|
||||||
|
|
||||||
QTime start = pref->getSchedulerStartTime();
|
QTime start = pref->getSchedulerStartTime();
|
||||||
QTime end = pref->getSchedulerEndTime();
|
QTime end = pref->getSchedulerEndTime();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
class BandwidthScheduler: public QObject
|
class BandwidthScheduler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(BandwidthScheduler)
|
Q_DISABLE_COPY(BandwidthScheduler)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libt.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@@ -147,13 +147,13 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
if (bytesRead < 0)
|
if (bytesRead < 0)
|
||||||
break;
|
break;
|
||||||
int dataSize = bytesRead + offset;
|
int dataSize = bytesRead + offset;
|
||||||
if (bytesRead == 0 && dataSize == 0)
|
if ((bytesRead == 0) && (dataSize == 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (start = 0; start < dataSize; ++start) {
|
for (start = 0; start < dataSize; ++start) {
|
||||||
endOfLine = -1;
|
endOfLine = -1;
|
||||||
// The file might have ended without the last line having a newline
|
// The file might have ended without the last line having a newline
|
||||||
if (!(bytesRead == 0 && dataSize > 0)) {
|
if (!((bytesRead == 0) && (dataSize > 0))) {
|
||||||
for (int i = start; i < dataSize; ++i) {
|
for (int i = start; i < dataSize; ++i) {
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
endOfLine = i;
|
endOfLine = i;
|
||||||
@@ -295,13 +295,13 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
if (bytesRead < 0)
|
if (bytesRead < 0)
|
||||||
break;
|
break;
|
||||||
int dataSize = bytesRead + offset;
|
int dataSize = bytesRead + offset;
|
||||||
if (bytesRead == 0 && dataSize == 0)
|
if ((bytesRead == 0) && (dataSize == 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (start = 0; start < dataSize; ++start) {
|
for (start = 0; start < dataSize; ++start) {
|
||||||
endOfLine = -1;
|
endOfLine = -1;
|
||||||
// The file might have ended without the last line having a newline
|
// The file might have ended without the last line having a newline
|
||||||
if (!(bytesRead == 0 && dataSize > 0)) {
|
if (!((bytesRead == 0) && (dataSize > 0))) {
|
||||||
for (int i = start; i < dataSize; ++i) {
|
for (int i = start; i < dataSize; ++i) {
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
endOfLine = i;
|
endOfLine = i;
|
||||||
@@ -407,24 +407,24 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name, char delim)
|
int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name, char delim)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int total_read = 0;
|
int totalRead = 0;
|
||||||
int read;
|
int read;
|
||||||
do {
|
do {
|
||||||
read = stream.readRawData(&c, 1);
|
read = stream.readRawData(&c, 1);
|
||||||
total_read += read;
|
totalRead += read;
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
if (c != delim) {
|
if (c != delim) {
|
||||||
name += c;
|
name += c;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Delim found
|
// Delim found
|
||||||
return total_read;
|
return totalRead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(read > 0);
|
while (read > 0);
|
||||||
|
|
||||||
return total_read;
|
return totalRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parser for PeerGuardian ip filter in p2p format
|
// Parser for PeerGuardian ip filter in p2p format
|
||||||
@@ -455,7 +455,7 @@ int FilterParserThread::parseP2BFilterFile()
|
|||||||
unsigned int start, end;
|
unsigned int start, end;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
while(getlineInStream(stream, name, '\0') && !m_abort) {
|
while (getlineInStream(stream, name, '\0') && !m_abort) {
|
||||||
if (!stream.readRawData(reinterpret_cast<char*>(&start), sizeof(start))
|
if (!stream.readRawData(reinterpret_cast<char*>(&start), sizeof(start))
|
||||||
|| !stream.readRawData(reinterpret_cast<char*>(&end), sizeof(end))) {
|
|| !stream.readRawData(reinterpret_cast<char*>(&end), sizeof(end))) {
|
||||||
LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||||
@@ -610,7 +610,7 @@ int FilterParserThread::findAndNullDelimiter(char *const data, char delimiter, i
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FilterParserThread::trim(char* const data, int start, int end)
|
int FilterParserThread::trim(char *const data, int start, int end)
|
||||||
{
|
{
|
||||||
if (start >= end) return start;
|
if (start >= end) return start;
|
||||||
int newStart = start;
|
int newStart = start;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -26,30 +26,36 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "resumedatasavingmanager.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSaveFile>
|
#include <QSaveFile>
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "resumedatasavingmanager.h"
|
|
||||||
|
|
||||||
ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath)
|
ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath)
|
||||||
: m_resumeDataDir(resumeFolderPath)
|
: m_resumeDataDir(resumeFolderPath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data) const
|
void ResumeDataSavingManager::save(const QString &filename, const QByteArray &data) const
|
||||||
{
|
{
|
||||||
QString filename = QString("%1.fastresume").arg(infoHash);
|
const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
|
||||||
QString filepath = m_resumeDataDir.absoluteFilePath(filename);
|
|
||||||
|
|
||||||
qDebug() << "Saving resume data in" << filepath;
|
QSaveFile file {filepath};
|
||||||
QSaveFile resumeFile(filepath);
|
if (file.open(QIODevice::WriteOnly)) {
|
||||||
if (resumeFile.open(QIODevice::WriteOnly)) {
|
file.write(data);
|
||||||
resumeFile.write(data);
|
if (!file.commit()) {
|
||||||
if (!resumeFile.commit()) {
|
Logger::instance()->addMessage(QString("Couldn't save data in '%1'. Error: %2")
|
||||||
Logger::instance()->addMessage(QString("Couldn't save resume data in %1. Error: %2")
|
.arg(filepath, file.errorString()), Log::WARNING);
|
||||||
.arg(filepath, resumeFile.errorString()), Log::WARNING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResumeDataSavingManager::remove(const QString &filename) const
|
||||||
|
{
|
||||||
|
const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
|
||||||
|
|
||||||
|
Utils::Fs::forceRemove(filepath);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -26,8 +26,7 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RESUMEDATASAVINGMANAGER_H
|
#pragma once
|
||||||
#define RESUMEDATASAVINGMANAGER_H
|
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -36,15 +35,15 @@
|
|||||||
class ResumeDataSavingManager : public QObject
|
class ResumeDataSavingManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(ResumeDataSavingManager)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ResumeDataSavingManager(const QString &resumeFolderPath);
|
explicit ResumeDataSavingManager(const QString &resumeFolderPath);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void saveResumeData(QString infoHash, QByteArray data) const;
|
void save(const QString &filename, const QByteArray &data) const;
|
||||||
|
void remove(const QString &filename) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QDir m_resumeDataDir;
|
QDir m_resumeDataDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RESUMEDATASAVINGMANAGER_H
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Statistics::Statistics(Session *session)
|
|||||||
, m_dirty(false)
|
, m_dirty(false)
|
||||||
{
|
{
|
||||||
load();
|
load();
|
||||||
connect(&m_timer, SIGNAL(timeout()), this, SLOT(gather()));
|
connect(&m_timer, &QTimer::timeout, this, &Statistics::gather);
|
||||||
m_timer.start(60 * 1000);
|
m_timer.start(60 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace BitTorrent
|
|||||||
class Session;
|
class Session;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Statistics : QObject
|
class Statistics : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Statistics)
|
Q_DISABLE_COPY(Statistics)
|
||||||
@@ -28,7 +28,6 @@ private:
|
|||||||
void save() const;
|
void save() const;
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
private:
|
|
||||||
BitTorrent::Session *m_session;
|
BitTorrent::Session *m_session;
|
||||||
// Will overflow at 15.9 EiB
|
// Will overflow at 15.9 EiB
|
||||||
quint64 m_alltimeUL;
|
quint64 m_alltimeUL;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -30,18 +30,14 @@
|
|||||||
#ifndef BITTORRENT_SESSION_H
|
#ifndef BITTORRENT_SESSION_H
|
||||||
#define BITTORRENT_SESSION_H
|
#define BITTORRENT_SESSION_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <libtorrent/version.hpp>
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
#include <vector>
|
||||||
#include <QElapsedTimer>
|
|
||||||
#endif
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
|
||||||
#include <QMutex>
|
|
||||||
#endif
|
|
||||||
#include <QNetworkConfigurationManager>
|
#include <QNetworkConfigurationManager>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
@@ -49,6 +45,12 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
|
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
|
#include <QMutex>
|
||||||
|
#else
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "base/settingvalue.h"
|
#include "base/settingvalue.h"
|
||||||
#include "base/tristatebool.h"
|
#include "base/tristatebool.h"
|
||||||
#include "base/types.h"
|
#include "base/types.h"
|
||||||
@@ -111,7 +113,6 @@ class QTimer;
|
|||||||
class QStringList;
|
class QStringList;
|
||||||
class QString;
|
class QString;
|
||||||
class QUrl;
|
class QUrl;
|
||||||
template<typename T> class QList;
|
|
||||||
|
|
||||||
class FilterParserThread;
|
class FilterParserThread;
|
||||||
class BandwidthScheduler;
|
class BandwidthScheduler;
|
||||||
@@ -137,7 +138,7 @@ namespace BitTorrent
|
|||||||
class Tracker;
|
class Tracker;
|
||||||
class MagnetUri;
|
class MagnetUri;
|
||||||
class TrackerEntry;
|
class TrackerEntry;
|
||||||
struct AddTorrentData;
|
struct CreateTorrentParams;
|
||||||
|
|
||||||
struct TorrentStatusReport
|
struct TorrentStatusReport
|
||||||
{
|
{
|
||||||
@@ -236,7 +237,7 @@ namespace BitTorrent
|
|||||||
int diskJobTime = 0;
|
int diskJobTime = 0;
|
||||||
} disk;
|
} disk;
|
||||||
};
|
};
|
||||||
#endif
|
#endif // LIBTORRENT_VERSION_NUM >= 10100
|
||||||
|
|
||||||
class Session : public QObject
|
class Session : public QObject
|
||||||
{
|
{
|
||||||
@@ -374,6 +375,10 @@ namespace BitTorrent
|
|||||||
void setAnnounceToAllTrackers(bool val);
|
void setAnnounceToAllTrackers(bool val);
|
||||||
bool announceToAllTiers() const;
|
bool announceToAllTiers() const;
|
||||||
void setAnnounceToAllTiers(bool val);
|
void setAnnounceToAllTiers(bool val);
|
||||||
|
int asyncIOThreads() const;
|
||||||
|
void setAsyncIOThreads(int num);
|
||||||
|
int checkingMemUsage() const;
|
||||||
|
void setCheckingMemUsage(int size);
|
||||||
int diskCacheSize() const;
|
int diskCacheSize() const;
|
||||||
void setDiskCacheSize(int size);
|
void setDiskCacheSize(int size);
|
||||||
int diskCacheTTL() const;
|
int diskCacheTTL() const;
|
||||||
@@ -451,6 +456,7 @@ namespace BitTorrent
|
|||||||
TorrentStatusReport torrentStatusReport() const;
|
TorrentStatusReport torrentStatusReport() const;
|
||||||
bool hasActiveTorrents() const;
|
bool hasActiveTorrents() const;
|
||||||
bool hasUnfinishedTorrents() const;
|
bool hasUnfinishedTorrents() const;
|
||||||
|
bool hasRunningSeed() const;
|
||||||
const SessionStatus &status() const;
|
const SessionStatus &status() const;
|
||||||
const CacheStatus &cacheStatus() const;
|
const CacheStatus &cacheStatus() const;
|
||||||
quint64 getAlltimeDL() const;
|
quint64 getAlltimeDL() const;
|
||||||
@@ -476,7 +482,9 @@ namespace BitTorrent
|
|||||||
void bottomTorrentsPriority(const QStringList &hashes);
|
void bottomTorrentsPriority(const QStringList &hashes);
|
||||||
|
|
||||||
// TorrentHandle interface
|
// TorrentHandle interface
|
||||||
|
void handleTorrentSaveResumeDataRequested(TorrentHandle *const torrent);
|
||||||
void handleTorrentShareLimitChanged(TorrentHandle *const torrent);
|
void handleTorrentShareLimitChanged(TorrentHandle *const torrent);
|
||||||
|
void handleTorrentNameChanged(TorrentHandle *const torrent);
|
||||||
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
|
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
|
||||||
void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory);
|
void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory);
|
||||||
void handleTorrentTagAdded(TorrentHandle *const torrent, const QString &tag);
|
void handleTorrentTagAdded(TorrentHandle *const torrent, const QString &tag);
|
||||||
@@ -546,7 +554,7 @@ namespace BitTorrent
|
|||||||
void generateResumeData(bool final = false);
|
void generateResumeData(bool final = false);
|
||||||
void handleIPFilterParsed(int ruleCount);
|
void handleIPFilterParsed(int ruleCount);
|
||||||
void handleIPFilterError();
|
void handleIPFilterError();
|
||||||
void handleDownloadFinished(const QString &url, const QString &filePath);
|
void handleDownloadFinished(const QString &url, const QByteArray &data);
|
||||||
void handleDownloadFailed(const QString &url, const QString &reason);
|
void handleDownloadFailed(const QString &url, const QString &reason);
|
||||||
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
|
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
|
||||||
|
|
||||||
@@ -562,7 +570,7 @@ namespace BitTorrent
|
|||||||
bool requestedFileDeletion;
|
bool requestedFileDeletion;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Session(QObject *parent = 0);
|
explicit Session(QObject *parent = nullptr);
|
||||||
~Session();
|
~Session();
|
||||||
|
|
||||||
bool hasPerTorrentRatioLimit() const;
|
bool hasPerTorrentRatioLimit() const;
|
||||||
@@ -594,20 +602,20 @@ namespace BitTorrent
|
|||||||
void enableIPFilter();
|
void enableIPFilter();
|
||||||
void disableIPFilter();
|
void disableIPFilter();
|
||||||
|
|
||||||
bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri,
|
bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
|
||||||
TorrentInfo torrentInfo = TorrentInfo(),
|
TorrentInfo torrentInfo = TorrentInfo(),
|
||||||
const QByteArray &fastresumeData = QByteArray());
|
const QByteArray &fastresumeData = QByteArray());
|
||||||
bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const;
|
bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const;
|
||||||
|
|
||||||
void updateSeedingLimitTimer();
|
void updateSeedingLimitTimer();
|
||||||
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
||||||
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);
|
||||||
void handleAddTorrentAlert(libtorrent::add_torrent_alert *p);
|
void handleAddTorrentAlert(libtorrent::add_torrent_alert *p);
|
||||||
void handleStateUpdateAlert(libtorrent::state_update_alert *p);
|
void handleStateUpdateAlert(libtorrent::state_update_alert *p);
|
||||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p);
|
void handleMetadataReceivedAlert(const libtorrent::metadata_received_alert *p);
|
||||||
|
void handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p);
|
||||||
void handleFileErrorAlert(libtorrent::file_error_alert *p);
|
void handleFileErrorAlert(libtorrent::file_error_alert *p);
|
||||||
void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p);
|
void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p);
|
||||||
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p);
|
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p);
|
||||||
@@ -627,6 +635,8 @@ namespace BitTorrent
|
|||||||
void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle);
|
void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle);
|
||||||
|
|
||||||
void saveResumeData();
|
void saveResumeData();
|
||||||
|
void saveTorrentsQueue();
|
||||||
|
void removeTorrentsQueue();
|
||||||
|
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
void dispatchAlerts(libtorrent::alert *alertPtr);
|
void dispatchAlerts(libtorrent::alert *alertPtr);
|
||||||
@@ -650,6 +660,8 @@ namespace BitTorrent
|
|||||||
CachedSettingValue<QString> m_IPFilterFile;
|
CachedSettingValue<QString> m_IPFilterFile;
|
||||||
CachedSettingValue<bool> m_announceToAllTrackers;
|
CachedSettingValue<bool> m_announceToAllTrackers;
|
||||||
CachedSettingValue<bool> m_announceToAllTiers;
|
CachedSettingValue<bool> m_announceToAllTiers;
|
||||||
|
CachedSettingValue<int> m_asyncIOThreads;
|
||||||
|
CachedSettingValue<int> m_checkingMemUsage;
|
||||||
CachedSettingValue<int> m_diskCacheSize;
|
CachedSettingValue<int> m_diskCacheSize;
|
||||||
CachedSettingValue<int> m_diskCacheTTL;
|
CachedSettingValue<int> m_diskCacheTTL;
|
||||||
CachedSettingValue<bool> m_useOSCache;
|
CachedSettingValue<bool> m_useOSCache;
|
||||||
@@ -753,13 +765,17 @@ namespace BitTorrent
|
|||||||
|
|
||||||
QHash<InfoHash, TorrentInfo> m_loadedMetadata;
|
QHash<InfoHash, TorrentInfo> m_loadedMetadata;
|
||||||
QHash<InfoHash, TorrentHandle *> m_torrents;
|
QHash<InfoHash, TorrentHandle *> m_torrents;
|
||||||
QHash<InfoHash, AddTorrentData> m_addingTorrents;
|
QHash<InfoHash, CreateTorrentParams> m_addingTorrents;
|
||||||
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
||||||
QHash<InfoHash, RemovingTorrentData> m_removingTorrents;
|
QHash<InfoHash, RemovingTorrentData> m_removingTorrents;
|
||||||
TorrentStatusReport m_torrentStatusReport;
|
TorrentStatusReport m_torrentStatusReport;
|
||||||
QStringMap m_categories;
|
QStringMap m_categories;
|
||||||
QSet<QString> m_tags;
|
QSet<QString> m_tags;
|
||||||
|
|
||||||
|
// I/O errored torrents
|
||||||
|
QSet<InfoHash> m_recentErroredTorrents;
|
||||||
|
QTimer *m_recentErroredTorrentsTimer;
|
||||||
|
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
QMutex m_alertsMutex;
|
QMutex m_alertsMutex;
|
||||||
QWaitCondition m_alertsWaitCondition;
|
QWaitCondition m_alertsWaitCondition;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2010 Christophe Dumez
|
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "torrentcreatorthread.h"
|
#include "torrentcreatorthread.h"
|
||||||
@@ -91,7 +89,7 @@ void TorrentCreatorThread::run()
|
|||||||
emit updateProgress(0);
|
emit updateProgress(0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + "/";
|
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + '/';
|
||||||
|
|
||||||
// Adding files to the torrent
|
// Adding files to the torrent
|
||||||
libt::file_storage fs;
|
libt::file_storage fs;
|
||||||
@@ -112,7 +110,7 @@ void TorrentCreatorThread::run()
|
|||||||
QStringList fileNames;
|
QStringList fileNames;
|
||||||
QHash<QString, boost::int64_t> fileSizeMap;
|
QHash<QString, boost::int64_t> fileSizeMap;
|
||||||
|
|
||||||
for (const auto &dir : qAsConst(dirs)) {
|
for (const auto &dir : asConst(dirs)) {
|
||||||
QStringList tmpNames; // natural sort files within each dir
|
QStringList tmpNames; // natural sort files within each dir
|
||||||
|
|
||||||
QDirIterator fileIter(dir, QDir::Files);
|
QDirIterator fileIter(dir, QDir::Files);
|
||||||
@@ -128,7 +126,7 @@ void TorrentCreatorThread::run()
|
|||||||
fileNames += tmpNames;
|
fileNames += tmpNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &fileName : qAsConst(fileNames))
|
for (const auto &fileName : asConst(fileNames))
|
||||||
fs.add_file(fileName.toStdString(), fileSizeMap[fileName]);
|
fs.add_file(fileName.toStdString(), fileSizeMap[fileName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,14 +141,14 @@ void TorrentCreatorThread::run()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add url seeds
|
// Add url seeds
|
||||||
foreach (QString seed, m_params.urlSeeds) {
|
for (QString seed : asConst(m_params.urlSeeds)) {
|
||||||
seed = seed.trimmed();
|
seed = seed.trimmed();
|
||||||
if (!seed.isEmpty())
|
if (!seed.isEmpty())
|
||||||
newTorrent.add_url_seed(seed.toStdString());
|
newTorrent.add_url_seed(seed.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
int tier = 0;
|
int tier = 0;
|
||||||
foreach (const QString &tracker, m_params.trackers) {
|
for (const QString &tracker : asConst(m_params.trackers)) {
|
||||||
if (tracker.isEmpty())
|
if (tracker.isEmpty())
|
||||||
++tier;
|
++tier;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2010 Christophe Dumez
|
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BITTORRENT_TORRENTCREATORTHREAD_H
|
#ifndef BITTORRENT_TORRENTCREATORTHREAD_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -88,10 +88,10 @@ namespace BitTorrent
|
|||||||
class TrackerEntry;
|
class TrackerEntry;
|
||||||
struct AddTorrentParams;
|
struct AddTorrentParams;
|
||||||
|
|
||||||
struct AddTorrentData
|
struct CreateTorrentParams
|
||||||
{
|
{
|
||||||
bool resumed;
|
bool restored; // is existing torrent job?
|
||||||
// for both new and resumed torrents
|
// for both new and restored torrents
|
||||||
QString name;
|
QString name;
|
||||||
QString category;
|
QString category;
|
||||||
QSet<QString> tags;
|
QSet<QString> tags;
|
||||||
@@ -102,18 +102,18 @@ namespace BitTorrent
|
|||||||
bool hasSeedStatus;
|
bool hasSeedStatus;
|
||||||
bool skipChecking;
|
bool skipChecking;
|
||||||
bool hasRootFolder;
|
bool hasRootFolder;
|
||||||
bool addForced;
|
bool forced;
|
||||||
bool addPaused;
|
bool paused;
|
||||||
int uploadLimit;
|
int uploadLimit;
|
||||||
int downloadLimit;
|
int downloadLimit;
|
||||||
// for new torrents
|
// for new torrents
|
||||||
QVector<int> filePriorities;
|
QVector<int> filePriorities;
|
||||||
// for resumed torrents
|
// for restored torrents
|
||||||
qreal ratioLimit;
|
qreal ratioLimit;
|
||||||
int seedingTimeLimit;
|
int seedingTimeLimit;
|
||||||
|
|
||||||
AddTorrentData();
|
CreateTorrentParams();
|
||||||
AddTorrentData(const AddTorrentParams ¶ms);
|
CreateTorrentParams(const AddTorrentParams ¶ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TrackerInfo
|
struct TrackerInfo
|
||||||
@@ -149,6 +149,8 @@ namespace BitTorrent
|
|||||||
PausedDownloading,
|
PausedDownloading,
|
||||||
PausedUploading,
|
PausedUploading,
|
||||||
|
|
||||||
|
Moving,
|
||||||
|
|
||||||
MissingFiles,
|
MissingFiles,
|
||||||
Error
|
Error
|
||||||
};
|
};
|
||||||
@@ -156,6 +158,7 @@ namespace BitTorrent
|
|||||||
class TorrentHandle : public QObject
|
class TorrentHandle : public QObject
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY(TorrentHandle)
|
Q_DISABLE_COPY(TorrentHandle)
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentHandle)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const qreal USE_GLOBAL_RATIO;
|
static const qreal USE_GLOBAL_RATIO;
|
||||||
@@ -168,7 +171,7 @@ namespace BitTorrent
|
|||||||
static const int MAX_SEEDING_TIME;
|
static const int MAX_SEEDING_TIME;
|
||||||
|
|
||||||
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
|
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
|
||||||
const AddTorrentData &data);
|
const CreateTorrentParams ¶ms);
|
||||||
~TorrentHandle();
|
~TorrentHandle();
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
@@ -331,7 +334,7 @@ namespace BitTorrent
|
|||||||
void setName(const QString &name);
|
void setName(const QString &name);
|
||||||
void setSequentialDownload(bool b);
|
void setSequentialDownload(bool b);
|
||||||
void toggleSequentialDownload();
|
void toggleSequentialDownload();
|
||||||
void setFirstLastPiecePriority(bool b);
|
void setFirstLastPiecePriority(bool enabled);
|
||||||
void toggleFirstLastPiecePriority();
|
void toggleFirstLastPiecePriority();
|
||||||
void pause();
|
void pause();
|
||||||
void resume(bool forced = false);
|
void resume(bool forced = false);
|
||||||
@@ -345,7 +348,6 @@ namespace BitTorrent
|
|||||||
void renameFile(int index, const QString &name);
|
void renameFile(int index, const QString &name);
|
||||||
bool saveTorrentFile(const QString &path);
|
bool saveTorrentFile(const QString &path);
|
||||||
void prioritizeFiles(const QVector<int> &priorities);
|
void prioritizeFiles(const QVector<int> &priorities);
|
||||||
void setFilePriority(int index, int priority);
|
|
||||||
void setRatioLimit(qreal limit);
|
void setRatioLimit(qreal limit);
|
||||||
void setSeedingTimeLimit(int limit);
|
void setSeedingTimeLimit(int limit);
|
||||||
void setUploadLimit(int limit);
|
void setUploadLimit(int limit);
|
||||||
@@ -353,7 +355,7 @@ namespace BitTorrent
|
|||||||
void setSuperSeeding(bool enable);
|
void setSuperSeeding(bool enable);
|
||||||
void flushCache();
|
void flushCache();
|
||||||
void addTrackers(const QList<TrackerEntry> &trackers);
|
void addTrackers(const QList<TrackerEntry> &trackers);
|
||||||
void replaceTrackers(QList<TrackerEntry> trackers);
|
void replaceTrackers(const QList<TrackerEntry> &trackers);
|
||||||
void addUrlSeeds(const QList<QUrl> &urlSeeds);
|
void addUrlSeeds(const QList<QUrl> &urlSeeds);
|
||||||
void removeUrlSeeds(const QList<QUrl> &urlSeeds);
|
void removeUrlSeeds(const QList<QUrl> &urlSeeds);
|
||||||
bool connectPeer(const PeerAddress &peerAddress);
|
bool connectPeer(const PeerAddress &peerAddress);
|
||||||
@@ -370,7 +372,7 @@ namespace BitTorrent
|
|||||||
void handleTempPathChanged();
|
void handleTempPathChanged();
|
||||||
void handleCategorySavePathChanged();
|
void handleCategorySavePathChanged();
|
||||||
void handleAppendExtensionToggled();
|
void handleAppendExtensionToggled();
|
||||||
void saveResumeData(bool updateStatus = false);
|
void saveResumeData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief fraction of file pieces that are available at least from one peer
|
* @brief fraction of file pieces that are available at least from one peer
|
||||||
@@ -383,30 +385,36 @@ namespace BitTorrent
|
|||||||
private:
|
private:
|
||||||
typedef boost::function<void ()> EventTrigger;
|
typedef boost::function<void ()> EventTrigger;
|
||||||
|
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
using LTFileIndex = int;
|
||||||
|
#else
|
||||||
|
using LTFileIndex = lt::file_index_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
void updateStatus();
|
void updateStatus();
|
||||||
void updateStatus(const libtorrent::torrent_status &nativeStatus);
|
void updateStatus(const libtorrent::torrent_status &nativeStatus);
|
||||||
void updateState();
|
void updateState();
|
||||||
void updateTorrentInfo();
|
void updateTorrentInfo();
|
||||||
|
|
||||||
void handleStorageMovedAlert(libtorrent::storage_moved_alert *p);
|
void handleStorageMovedAlert(const libtorrent::storage_moved_alert *p);
|
||||||
void handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert *p);
|
void handleStorageMovedFailedAlert(const libtorrent::storage_moved_failed_alert *p);
|
||||||
void handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p);
|
void handleTrackerReplyAlert(const libtorrent::tracker_reply_alert *p);
|
||||||
void handleTrackerWarningAlert(libtorrent::tracker_warning_alert *p);
|
void handleTrackerWarningAlert(const libtorrent::tracker_warning_alert *p);
|
||||||
void handleTrackerErrorAlert(libtorrent::tracker_error_alert *p);
|
void handleTrackerErrorAlert(const libtorrent::tracker_error_alert *p);
|
||||||
void handleTorrentCheckedAlert(libtorrent::torrent_checked_alert *p);
|
void handleTorrentCheckedAlert(const libtorrent::torrent_checked_alert *p);
|
||||||
void handleTorrentFinishedAlert(libtorrent::torrent_finished_alert *p);
|
void handleTorrentFinishedAlert(const libtorrent::torrent_finished_alert *p);
|
||||||
void handleTorrentPausedAlert(libtorrent::torrent_paused_alert *p);
|
void handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p);
|
||||||
void handleTorrentResumedAlert(libtorrent::torrent_resumed_alert *p);
|
void handleTorrentResumedAlert(const libtorrent::torrent_resumed_alert *p);
|
||||||
void handleSaveResumeDataAlert(libtorrent::save_resume_data_alert *p);
|
void handleSaveResumeDataAlert(const libtorrent::save_resume_data_alert *p);
|
||||||
void handleSaveResumeDataFailedAlert(libtorrent::save_resume_data_failed_alert *p);
|
void handleSaveResumeDataFailedAlert(const libtorrent::save_resume_data_failed_alert *p);
|
||||||
void handleFastResumeRejectedAlert(libtorrent::fastresume_rejected_alert *p);
|
void handleFastResumeRejectedAlert(const libtorrent::fastresume_rejected_alert *p);
|
||||||
void handleFileRenamedAlert(libtorrent::file_renamed_alert *p);
|
void handleFileRenamedAlert(const libtorrent::file_renamed_alert *p);
|
||||||
void handleFileRenameFailedAlert(libtorrent::file_rename_failed_alert *p);
|
void handleFileRenameFailedAlert(const libtorrent::file_rename_failed_alert *p);
|
||||||
void handleFileCompletedAlert(libtorrent::file_completed_alert *p);
|
void handleFileCompletedAlert(const libtorrent::file_completed_alert *p);
|
||||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p);
|
void handleMetadataReceivedAlert(const libtorrent::metadata_received_alert *p);
|
||||||
void handleStatsAlert(libtorrent::stats_alert *p);
|
void handleStatsAlert(const libtorrent::stats_alert *p);
|
||||||
|
|
||||||
void resume_impl(bool forced, bool uploadMode);
|
void resume_impl(bool forced);
|
||||||
bool isMoveInProgress() const;
|
bool isMoveInProgress() const;
|
||||||
QString nativeActualSavePath() const;
|
QString nativeActualSavePath() const;
|
||||||
|
|
||||||
@@ -418,6 +426,7 @@ namespace BitTorrent
|
|||||||
bool addTracker(const TrackerEntry &tracker);
|
bool addTracker(const TrackerEntry &tracker);
|
||||||
bool addUrlSeed(const QUrl &urlSeed);
|
bool addUrlSeed(const QUrl &urlSeed);
|
||||||
bool removeUrlSeed(const QUrl &urlSeed);
|
bool removeUrlSeed(const QUrl &urlSeed);
|
||||||
|
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<int> &updatedFilePrio = {});
|
||||||
|
|
||||||
Session *const m_session;
|
Session *const m_session;
|
||||||
libtorrent::torrent_handle m_nativeHandle;
|
libtorrent::torrent_handle m_nativeHandle;
|
||||||
@@ -443,6 +452,10 @@ namespace BitTorrent
|
|||||||
QQueue<EventTrigger> m_moveFinishedTriggers;
|
QQueue<EventTrigger> m_moveFinishedTriggers;
|
||||||
int m_renameCount;
|
int m_renameCount;
|
||||||
|
|
||||||
|
// Until libtorrent provide an "old_name" field in `file_renamed_alert`
|
||||||
|
// we will rely on this workaround to remove empty leftover folders
|
||||||
|
QHash<LTFileIndex, QVector<QString>> m_oldPath;
|
||||||
|
|
||||||
bool m_useAutoTMM;
|
bool m_useAutoTMM;
|
||||||
|
|
||||||
// Persistent data
|
// Persistent data
|
||||||
@@ -454,13 +467,26 @@ namespace BitTorrent
|
|||||||
qreal m_ratioLimit;
|
qreal m_ratioLimit;
|
||||||
int m_seedingTimeLimit;
|
int m_seedingTimeLimit;
|
||||||
bool m_tempPathDisabled;
|
bool m_tempPathDisabled;
|
||||||
|
bool m_fastresumeDataRejected;
|
||||||
bool m_hasMissingFiles;
|
bool m_hasMissingFiles;
|
||||||
bool m_hasRootFolder;
|
bool m_hasRootFolder;
|
||||||
bool m_needsToSetFirstLastPiecePriority;
|
bool m_needsToSetFirstLastPiecePriority;
|
||||||
|
bool m_needsToStartForced;
|
||||||
|
|
||||||
bool m_pauseAfterRecheck;
|
|
||||||
bool m_needSaveResumeData;
|
|
||||||
QHash<QString, TrackerInfo> m_trackerInfos;
|
QHash<QString, TrackerInfo> m_trackerInfos;
|
||||||
|
|
||||||
|
enum StartupState
|
||||||
|
{
|
||||||
|
Preparing, // torrent is preparing to start regular processing
|
||||||
|
Starting, // torrent is prepared and starting to perform regular processing
|
||||||
|
Started // torrent is performing regular processing
|
||||||
|
};
|
||||||
|
StartupState m_startupState = Preparing;
|
||||||
|
// Handle torrent state when it starts performing some service job
|
||||||
|
// being in Paused state so it might be unpaused internally and then paused again
|
||||||
|
bool m_pauseWhenReady;
|
||||||
|
|
||||||
|
bool m_unchecked = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,21 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QDebug>
|
#include "torrentinfo.h"
|
||||||
#include <QString>
|
|
||||||
#include <QList>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QDateTime>
|
|
||||||
|
|
||||||
#include <libtorrent/error_code.hpp>
|
#include <libtorrent/error_code.hpp>
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "base/global.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "infohash.h"
|
#include "infohash.h"
|
||||||
#include "trackerentry.h"
|
#include "trackerentry.h"
|
||||||
#include "torrentinfo.h"
|
|
||||||
|
|
||||||
namespace libt = libtorrent;
|
namespace libt = libtorrent;
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
@@ -62,46 +63,6 @@ TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
|||||||
|
|
||||||
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
||||||
{
|
{
|
||||||
libt::error_code ec;
|
|
||||||
TorrentInfo info(NativePtr(new libt::torrent_info(data.constData(), data.size(), ec)));
|
|
||||||
if (error) {
|
|
||||||
if (ec)
|
|
||||||
*error = QString::fromStdString(ec.message());
|
|
||||||
else
|
|
||||||
error->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
|
|
||||||
{
|
|
||||||
if (error)
|
|
||||||
error->clear();
|
|
||||||
|
|
||||||
QFile file {path};
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
|
||||||
if (error)
|
|
||||||
*error = file.errorString();
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
const qint64 fileSizeLimit = 100 * 1024 * 1024; // 100 MB
|
|
||||||
if (file.size() > fileSizeLimit) {
|
|
||||||
if (error)
|
|
||||||
*error = tr("File size exceeds max limit %1").arg(fileSizeLimit);
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArray data = file.read(fileSizeLimit);
|
|
||||||
if (data.size() != file.size()) {
|
|
||||||
if (error)
|
|
||||||
*error = tr("Torrent file read error");
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||||
// used in `torrent_info()` constructor
|
// used in `torrent_info()` constructor
|
||||||
const int depthLimit = 100;
|
const int depthLimit = 100;
|
||||||
@@ -133,6 +94,44 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexc
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
error->clear();
|
||||||
|
|
||||||
|
QFile file {path};
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
if (error)
|
||||||
|
*error = file.errorString();
|
||||||
|
return TorrentInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.size() > MAX_TORRENT_SIZE) {
|
||||||
|
if (error)
|
||||||
|
*error = tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE));
|
||||||
|
return TorrentInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
try {
|
||||||
|
data = file.readAll();
|
||||||
|
}
|
||||||
|
catch (const std::bad_alloc &e) {
|
||||||
|
if (error)
|
||||||
|
*error = tr("Torrent file read error: %1").arg(e.what());
|
||||||
|
return TorrentInfo();
|
||||||
|
}
|
||||||
|
if (data.size() != file.size()) {
|
||||||
|
if (error)
|
||||||
|
*error = tr("Torrent file read error: size mismatch");
|
||||||
|
return TorrentInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return load(data, error);
|
||||||
|
}
|
||||||
|
|
||||||
bool TorrentInfo::isValid() const
|
bool TorrentInfo::isValid() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo && m_nativeInfo->is_valid() && (m_nativeInfo->num_files() > 0));
|
return (m_nativeInfo && m_nativeInfo->is_valid() && (m_nativeInfo->num_files() > 0));
|
||||||
@@ -248,7 +247,7 @@ QList<TrackerEntry> TorrentInfo::trackers() const
|
|||||||
if (!isValid()) return QList<TrackerEntry>();
|
if (!isValid()) return QList<TrackerEntry>();
|
||||||
|
|
||||||
QList<TrackerEntry> trackers;
|
QList<TrackerEntry> trackers;
|
||||||
foreach (const libt::announce_entry &tracker, m_nativeInfo->trackers())
|
for (const libt::announce_entry &tracker : m_nativeInfo->trackers())
|
||||||
trackers.append(tracker);
|
trackers.append(tracker);
|
||||||
|
|
||||||
return trackers;
|
return trackers;
|
||||||
@@ -259,7 +258,7 @@ QList<QUrl> TorrentInfo::urlSeeds() const
|
|||||||
if (!isValid()) return QList<QUrl>();
|
if (!isValid()) return QList<QUrl>();
|
||||||
|
|
||||||
QList<QUrl> urlSeeds;
|
QList<QUrl> urlSeeds;
|
||||||
foreach (const libt::web_seed_entry &webSeed, m_nativeInfo->web_seeds())
|
for (const libt::web_seed_entry &webSeed : m_nativeInfo->web_seeds())
|
||||||
if (webSeed.type == libt::web_seed_entry::url_seed)
|
if (webSeed.type == libt::web_seed_entry::url_seed)
|
||||||
urlSeeds.append(QUrl(webSeed.url.c_str()));
|
urlSeeds.append(QUrl(webSeed.url.c_str()));
|
||||||
|
|
||||||
@@ -315,7 +314,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
|
|||||||
return hashes;
|
return hashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo::PieceRange TorrentInfo::filePieces(const QString& file) const
|
TorrentInfo::PieceRange TorrentInfo::filePieces(const QString &file) const
|
||||||
{
|
{
|
||||||
if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct
|
if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct
|
||||||
return {};
|
return {};
|
||||||
@@ -340,21 +339,26 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(int fileIndex) const
|
|||||||
|
|
||||||
const libt::file_storage &files = nativeInfo()->files();
|
const libt::file_storage &files = nativeInfo()->files();
|
||||||
const auto fileSize = files.file_size(fileIndex);
|
const auto fileSize = files.file_size(fileIndex);
|
||||||
const auto firstOffset = files.file_offset(fileIndex);
|
const auto fileOffset = files.file_offset(fileIndex);
|
||||||
return makeInterval(static_cast<int>(firstOffset / pieceLength()),
|
|
||||||
static_cast<int>((firstOffset + fileSize - 1) / pieceLength()));
|
const int beginIdx = (fileOffset / pieceLength());
|
||||||
|
const int endIdx = ((fileOffset + fileSize - 1) / pieceLength());
|
||||||
|
|
||||||
|
if (fileSize <= 0)
|
||||||
|
return {beginIdx, 0};
|
||||||
|
return makeInterval(beginIdx, endIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentInfo::renameFile(uint index, const QString &newPath)
|
void TorrentInfo::renameFile(const int index, const QString &newPath)
|
||||||
{
|
{
|
||||||
if (!isValid()) return;
|
if (!isValid()) return;
|
||||||
nativeInfo()->rename_file(index, Utils::Fs::toNativePath(newPath).toStdString());
|
nativeInfo()->rename_file(index, Utils::Fs::toNativePath(newPath).toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const
|
int BitTorrent::TorrentInfo::fileIndex(const QString &fileName) const
|
||||||
{
|
{
|
||||||
// the check whether the object valid is not needed here
|
// the check whether the object is valid is not needed here
|
||||||
// because filesCount() returns -1 in that case and the loop exits immediately
|
// because if filesCount() returns -1 the loop exits immediately
|
||||||
for (int i = 0; i < filesCount(); ++i)
|
for (int i = 0; i < filesCount(); ++i)
|
||||||
if (fileName == filePath(i))
|
if (fileName == filePath(i))
|
||||||
return i;
|
return i;
|
||||||
@@ -362,24 +366,29 @@ int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentInfo::hasRootFolder() const
|
QString TorrentInfo::rootFolder() const
|
||||||
{
|
{
|
||||||
QString testRootFolder;
|
QString rootFolder;
|
||||||
for (int i = 0; i < filesCount(); ++i) {
|
for (int i = 0; i < filesCount(); ++i) {
|
||||||
const QString filePath = this->filePath(i);
|
const QString filePath = this->filePath(i);
|
||||||
if (QDir::isAbsolutePath(filePath)) continue;
|
if (QDir::isAbsolutePath(filePath)) continue;
|
||||||
|
|
||||||
const auto filePathElements = filePath.splitRef('/');
|
const auto filePathElements = filePath.splitRef('/');
|
||||||
// if at least one file has no root folder, no common root folder exists
|
// if at least one file has no root folder, no common root folder exists
|
||||||
if (filePathElements.count() <= 1) return false;
|
if (filePathElements.count() <= 1) return "";
|
||||||
|
|
||||||
if (testRootFolder.isEmpty())
|
if (rootFolder.isEmpty())
|
||||||
testRootFolder = filePathElements.at(0).toString();
|
rootFolder = filePathElements.at(0).toString();
|
||||||
else if (testRootFolder != filePathElements.at(0))
|
else if (rootFolder != filePathElements.at(0))
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return rootFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TorrentInfo::hasRootFolder() const
|
||||||
|
{
|
||||||
|
return !rootFolder().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentInfo::stripRootFolder()
|
void TorrentInfo::stripRootFolder()
|
||||||
|
|||||||
@@ -29,21 +29,21 @@
|
|||||||
#ifndef BITTORRENT_TORRENTINFO_H
|
#ifndef BITTORRENT_TORRENTINFO_H
|
||||||
#define BITTORRENT_TORRENTINFO_H
|
#define BITTORRENT_TORRENTINFO_H
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
#include <libtorrent/version.hpp>
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QList>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include "base/indexrange.h"
|
#include "base/indexrange.h"
|
||||||
|
|
||||||
class QString;
|
|
||||||
class QUrl;
|
|
||||||
class QDateTime;
|
|
||||||
class QStringList;
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
template<typename T> class QList;
|
class QDateTime;
|
||||||
template<typename T> class QVector;
|
class QString;
|
||||||
|
class QStringList;
|
||||||
|
class QUrl;
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
@@ -52,7 +52,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
class TorrentInfo
|
class TorrentInfo
|
||||||
{
|
{
|
||||||
Q_DECLARE_TR_FUNCTIONS("TorrentInfo")
|
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
@@ -102,8 +102,9 @@ namespace BitTorrent
|
|||||||
PieceRange filePieces(const QString &file) const;
|
PieceRange filePieces(const QString &file) const;
|
||||||
PieceRange filePieces(int fileIndex) const;
|
PieceRange filePieces(int fileIndex) const;
|
||||||
|
|
||||||
void renameFile(uint index, const QString &newPath);
|
void renameFile(int index, const QString &newPath);
|
||||||
|
|
||||||
|
QString rootFolder() const;
|
||||||
bool hasRootFolder() const;
|
bool hasRootFolder() const;
|
||||||
void stripRootFolder();
|
void stripRootFolder();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
@@ -27,17 +27,13 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vector>
|
#include "tracker.h"
|
||||||
|
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
#include <libtorrent/entry.hpp>
|
#include <libtorrent/entry.hpp>
|
||||||
|
|
||||||
#include "base/global.h"
|
|
||||||
#include "base/http/server.h"
|
#include "base/http/server.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/utils/bytearray.h"
|
|
||||||
#include "base/utils/string.h"
|
|
||||||
#include "tracker.h"
|
|
||||||
|
|
||||||
// static limits
|
// static limits
|
||||||
static const int MAX_TORRENTS = 100;
|
static const int MAX_TORRENTS = 100;
|
||||||
@@ -59,7 +55,7 @@ bool Peer::operator==(const Peer &other) const
|
|||||||
|
|
||||||
QString Peer::uid() const
|
QString Peer::uid() const
|
||||||
{
|
{
|
||||||
return ip + ":" + QString::number(port);
|
return ip.toString() + ':' + QString::number(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
libtorrent::entry Peer::toEntry(bool noPeerId) const
|
libtorrent::entry Peer::toEntry(bool noPeerId) const
|
||||||
@@ -67,7 +63,7 @@ libtorrent::entry Peer::toEntry(bool noPeerId) const
|
|||||||
libtorrent::entry::dictionary_type peerMap;
|
libtorrent::entry::dictionary_type peerMap;
|
||||||
if (!noPeerId)
|
if (!noPeerId)
|
||||||
peerMap["id"] = libtorrent::entry(peerId.toStdString());
|
peerMap["id"] = libtorrent::entry(peerId.toStdString());
|
||||||
peerMap["ip"] = libtorrent::entry(ip.toStdString());
|
peerMap["ip"] = libtorrent::entry(ip.toString().toStdString());
|
||||||
peerMap["port"] = libtorrent::entry(port);
|
peerMap["port"] = libtorrent::entry(port);
|
||||||
|
|
||||||
return libtorrent::entry(peerMap);
|
return libtorrent::entry(peerMap);
|
||||||
@@ -132,22 +128,13 @@ Http::Response Tracker::processRequest(const Http::Request &request, const Http:
|
|||||||
|
|
||||||
void Tracker::respondToAnnounceRequest()
|
void Tracker::respondToAnnounceRequest()
|
||||||
{
|
{
|
||||||
QMap<QString, QByteArray> queryParams;
|
const QMap<QString, QByteArray> &queryParams = m_request.query;
|
||||||
// Parse GET parameters
|
TrackerAnnounceRequest announceReq;
|
||||||
using namespace Utils::ByteArray;
|
|
||||||
for (const QByteArray ¶m : copyAsConst(splitToViews(m_request.query, "&"))) {
|
|
||||||
const int sepPos = param.indexOf('=');
|
|
||||||
if (sepPos <= 0) continue; // ignores params without name
|
|
||||||
|
|
||||||
const QString paramName {QString::fromUtf8(param.constData(), sepPos)};
|
|
||||||
const QByteArray paramValue {param.mid(sepPos + 1)};
|
|
||||||
queryParams[paramName] = paramValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackerAnnounceRequest annonceReq;
|
|
||||||
|
|
||||||
// IP
|
// IP
|
||||||
annonceReq.peer.ip = m_env.clientAddress.toString();
|
// Use the "ip" parameter provided from tracker request first, then fall back to client IP if invalid
|
||||||
|
const QHostAddress paramIP {QString::fromLatin1(queryParams.value("ip"))};
|
||||||
|
announceReq.peer.ip = paramIP.isNull() ? m_env.clientAddress : paramIP;
|
||||||
|
|
||||||
// 1. Get info_hash
|
// 1. Get info_hash
|
||||||
if (!queryParams.contains("info_hash")) {
|
if (!queryParams.contains("info_hash")) {
|
||||||
@@ -155,7 +142,7 @@ void Tracker::respondToAnnounceRequest()
|
|||||||
status(101, "Missing info_hash");
|
status(101, "Missing info_hash");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
annonceReq.infoHash = queryParams.value("info_hash");
|
announceReq.infoHash = queryParams.value("info_hash");
|
||||||
// info_hash cannot be longer than 20 bytes
|
// info_hash cannot be longer than 20 bytes
|
||||||
/*if (annonce_req.info_hash.toLatin1().length() > 20) {
|
/*if (annonce_req.info_hash.toLatin1().length() > 20) {
|
||||||
qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
|
qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
|
||||||
@@ -169,7 +156,7 @@ void Tracker::respondToAnnounceRequest()
|
|||||||
status(102, "Missing peer_id");
|
status(102, "Missing peer_id");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
annonceReq.peer.peerId = queryParams.value("peer_id");
|
announceReq.peer.peerId = queryParams.value("peer_id");
|
||||||
// peer_id cannot be longer than 20 bytes
|
// peer_id cannot be longer than 20 bytes
|
||||||
/*if (annonce_req.peer.peer_id.length() > 20) {
|
/*if (annonce_req.peer.peer_id.length() > 20) {
|
||||||
qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id));
|
qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id));
|
||||||
@@ -184,52 +171,52 @@ void Tracker::respondToAnnounceRequest()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
annonceReq.peer.port = queryParams.value("port").toInt(&ok);
|
announceReq.peer.port = queryParams.value("port").toInt(&ok);
|
||||||
if (!ok || (annonceReq.peer.port < 0) || (annonceReq.peer.port > 65535)) {
|
if (!ok || (announceReq.peer.port < 0) || (announceReq.peer.port > 65535)) {
|
||||||
qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port);
|
qDebug("Tracker: Invalid port number (%d)", announceReq.peer.port);
|
||||||
status(103, "Missing port");
|
status(103, "Missing port");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Get event
|
// 4. Get event
|
||||||
annonceReq.event = "";
|
announceReq.event = "";
|
||||||
if (queryParams.contains("event")) {
|
if (queryParams.contains("event")) {
|
||||||
annonceReq.event = queryParams.value("event");
|
announceReq.event = queryParams.value("event");
|
||||||
qDebug("Tracker: event is %s", qUtf8Printable(annonceReq.event));
|
qDebug("Tracker: event is %s", qUtf8Printable(announceReq.event));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Get numwant
|
// 5. Get numwant
|
||||||
annonceReq.numwant = 50;
|
announceReq.numwant = 50;
|
||||||
if (queryParams.contains("numwant")) {
|
if (queryParams.contains("numwant")) {
|
||||||
int tmp = queryParams.value("numwant").toInt();
|
int tmp = queryParams.value("numwant").toInt();
|
||||||
if (tmp > 0) {
|
if (tmp > 0) {
|
||||||
qDebug("Tracker: numwant = %d", tmp);
|
qDebug("Tracker: numwant = %d", tmp);
|
||||||
annonceReq.numwant = tmp;
|
announceReq.numwant = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. no_peer_id (extension)
|
// 6. no_peer_id (extension)
|
||||||
annonceReq.noPeerId = false;
|
announceReq.noPeerId = false;
|
||||||
if (queryParams.contains("no_peer_id"))
|
if (queryParams.contains("no_peer_id"))
|
||||||
annonceReq.noPeerId = true;
|
announceReq.noPeerId = true;
|
||||||
|
|
||||||
// 7. TODO: support "compact" extension
|
// 7. TODO: support "compact" extension
|
||||||
|
|
||||||
// Done parsing, now let's reply
|
// Done parsing, now let's reply
|
||||||
if (annonceReq.event == "stopped") {
|
if (announceReq.event == "stopped") {
|
||||||
unregisterPeer(annonceReq);
|
unregisterPeer(announceReq);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
registerPeer(annonceReq);
|
registerPeer(announceReq);
|
||||||
replyWithPeerList(annonceReq);
|
replyWithPeerList(announceReq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
|
void Tracker::registerPeer(const TrackerAnnounceRequest &announceReq)
|
||||||
{
|
{
|
||||||
if (annonceReq.peer.port == 0) return;
|
if (announceReq.peer.port == 0) return;
|
||||||
|
|
||||||
if (!m_torrents.contains(annonceReq.infoHash)) {
|
if (!m_torrents.contains(announceReq.infoHash)) {
|
||||||
// Unknown torrent
|
// Unknown torrent
|
||||||
if (m_torrents.size() == MAX_TORRENTS) {
|
if (m_torrents.size() == MAX_TORRENTS) {
|
||||||
// Reached max size, remove a random torrent
|
// Reached max size, remove a random torrent
|
||||||
@@ -238,34 +225,34 @@ void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register the user
|
// Register the user
|
||||||
PeerList &peers = m_torrents[annonceReq.infoHash];
|
PeerList &peers = m_torrents[announceReq.infoHash];
|
||||||
if (!peers.contains(annonceReq.peer.uid())) {
|
if (!peers.contains(announceReq.peer.uid())) {
|
||||||
// Unknown peer
|
// Unknown peer
|
||||||
if (peers.size() == MAX_PEERS_PER_TORRENT) {
|
if (peers.size() == MAX_PEERS_PER_TORRENT) {
|
||||||
// Too many peers, remove a random one
|
// Too many peers, remove a random one
|
||||||
peers.erase(peers.begin());
|
peers.erase(peers.begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
peers[annonceReq.peer.uid()] = annonceReq.peer;
|
peers[announceReq.peer.uid()] = announceReq.peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tracker::unregisterPeer(const TrackerAnnounceRequest &annonceReq)
|
void Tracker::unregisterPeer(const TrackerAnnounceRequest &announceReq)
|
||||||
{
|
{
|
||||||
if (annonceReq.peer.port == 0) return;
|
if (announceReq.peer.port == 0) return;
|
||||||
|
|
||||||
if (m_torrents[annonceReq.infoHash].remove(annonceReq.peer.uid()) > 0)
|
if (m_torrents[announceReq.infoHash].remove(announceReq.peer.uid()) > 0)
|
||||||
qDebug("Tracker: Peer stopped downloading, deleting it from the list");
|
qDebug("Tracker: Peer stopped downloading, deleting it from the list");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
|
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &announceReq)
|
||||||
{
|
{
|
||||||
// Prepare the entry for bencoding
|
// Prepare the entry for bencoding
|
||||||
libtorrent::entry::dictionary_type replyDict;
|
libtorrent::entry::dictionary_type replyDict;
|
||||||
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
|
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
|
||||||
|
|
||||||
libtorrent::entry::list_type peerList;
|
libtorrent::entry::list_type peerList;
|
||||||
for (const Peer &p : m_torrents.value(annonceReq.infoHash))
|
for (const Peer &p : m_torrents.value(announceReq.infoHash))
|
||||||
peerList.push_back(p.toEntry(annonceReq.noPeerId));
|
peerList.push_back(p.toEntry(announceReq.noPeerId));
|
||||||
replyDict["peers"] = libtorrent::entry(peerList);
|
replyDict["peers"] = libtorrent::entry(peerList);
|
||||||
|
|
||||||
const libtorrent::entry replyEntry(replyDict);
|
const libtorrent::entry replyEntry(replyDict);
|
||||||
@@ -277,5 +264,3 @@ void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
|
|||||||
// HTTP reply
|
// HTTP reply
|
||||||
print(reply, Http::CONTENT_TYPE_TXT);
|
print(reply, Http::CONTENT_TYPE_TXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,10 +32,10 @@
|
|||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
#include "base/http/irequesthandler.h"
|
#include "base/http/irequesthandler.h"
|
||||||
#include "base/http/responsebuilder.h"
|
#include "base/http/responsebuilder.h"
|
||||||
#include "base/http/types.h"
|
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ namespace BitTorrent
|
|||||||
{
|
{
|
||||||
struct Peer
|
struct Peer
|
||||||
{
|
{
|
||||||
QString ip;
|
QHostAddress ip;
|
||||||
QByteArray peerId;
|
QByteArray peerId;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
@@ -90,9 +90,9 @@ namespace BitTorrent
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void respondToAnnounceRequest();
|
void respondToAnnounceRequest();
|
||||||
void registerPeer(const TrackerAnnounceRequest &annonceReq);
|
void registerPeer(const TrackerAnnounceRequest &announceReq);
|
||||||
void unregisterPeer(const TrackerAnnounceRequest &annonceReq);
|
void unregisterPeer(const TrackerAnnounceRequest &announceReq);
|
||||||
void replyWithPeerList(const TrackerAnnounceRequest &annonceReq);
|
void replyWithPeerList(const TrackerAnnounceRequest &announceReq);
|
||||||
|
|
||||||
Http::Server *m_server;
|
Http::Server *m_server;
|
||||||
TorrentList m_torrents;
|
TorrentList m_torrents;
|
||||||
|
|||||||
@@ -26,11 +26,12 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "trackerentry.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "trackerentry.h"
|
|
||||||
|
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ namespace BitTorrent
|
|||||||
public:
|
public:
|
||||||
enum Status
|
enum Status
|
||||||
{
|
{
|
||||||
NotContacted,
|
NotContacted = 1,
|
||||||
Working,
|
Working = 2,
|
||||||
Updating,
|
Updating = 3,
|
||||||
NotWorking
|
NotWorking = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
TrackerEntry(const QString &url);
|
TrackerEntry(const QString &url);
|
||||||
|
|||||||
@@ -30,11 +30,10 @@
|
|||||||
|
|
||||||
RuntimeError::RuntimeError(const QString &message)
|
RuntimeError::RuntimeError(const QString &message)
|
||||||
: std::runtime_error {message.toUtf8().data()}
|
: std::runtime_error {message.toUtf8().data()}
|
||||||
, m_message {message}
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QString RuntimeError::message() const
|
QString RuntimeError::message() const
|
||||||
{
|
{
|
||||||
return m_message;
|
return what();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,4 @@ class RuntimeError : public std::runtime_error
|
|||||||
public:
|
public:
|
||||||
explicit RuntimeError(const QString &message = "");
|
explicit RuntimeError(const QString &message = "");
|
||||||
QString message() const;
|
QString message() const;
|
||||||
|
|
||||||
private:
|
|
||||||
const QString m_message;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,18 +28,19 @@
|
|||||||
|
|
||||||
#include "filesystemwatcher.h"
|
#include "filesystemwatcher.h"
|
||||||
|
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#include "base/algorithm.h"
|
#include "base/algorithm.h"
|
||||||
#include "base/bittorrent/magneturi.h"
|
#include "base/bittorrent/magneturi.h"
|
||||||
#include "base/bittorrent/torrentinfo.h"
|
#include "base/bittorrent/torrentinfo.h"
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
|
#include "base/logger.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
|
|
||||||
@@ -57,18 +58,14 @@ FileSystemWatcher::FileSystemWatcher(QObject *parent)
|
|||||||
m_partialTorrentTimer.setSingleShot(true);
|
m_partialTorrentTimer.setSingleShot(true);
|
||||||
connect(&m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents);
|
connect(&m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents);
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
connect(&m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders);
|
connect(&m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FileSystemWatcher::directories() const
|
QStringList FileSystemWatcher::directories() const
|
||||||
{
|
{
|
||||||
QStringList dirs = QFileSystemWatcher::directories();
|
QStringList dirs = QFileSystemWatcher::directories();
|
||||||
#ifndef Q_OS_WIN
|
for (const QDir &dir : asConst(m_watchedFolders))
|
||||||
for (const QDir &dir : qAsConst(m_watchedFolders))
|
|
||||||
dirs << dir.canonicalPath();
|
dirs << dir.canonicalPath();
|
||||||
#endif
|
|
||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,15 +73,14 @@ void FileSystemWatcher::addPath(const QString &path)
|
|||||||
{
|
{
|
||||||
if (path.isEmpty()) return;
|
if (path.isEmpty()) return;
|
||||||
|
|
||||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
#if !defined Q_OS_HAIKU
|
||||||
const QDir dir(path);
|
const QDir dir(path);
|
||||||
if (!dir.exists()) return;
|
if (!dir.exists()) return;
|
||||||
|
|
||||||
// Check if the path points to a network file system or not
|
// Check if the path points to a network file system or not
|
||||||
if (Utils::Fs::isNetworkFileSystem(path)) {
|
if (Utils::Fs::isNetworkFileSystem(path)) {
|
||||||
// Network mode
|
// Network mode
|
||||||
qDebug("Network folder detected: %s", qUtf8Printable(path));
|
LogMsg(tr("Watching remote folder: \"%1\"").arg(Utils::Fs::toNativePath(path)));
|
||||||
qDebug("Using file polling mode instead of inotify...");
|
|
||||||
m_watchedFolders << dir;
|
m_watchedFolders << dir;
|
||||||
|
|
||||||
m_watchTimer.start(WATCH_INTERVAL);
|
m_watchTimer.start(WATCH_INTERVAL);
|
||||||
@@ -93,20 +89,19 @@ void FileSystemWatcher::addPath(const QString &path)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Normal mode
|
// Normal mode
|
||||||
qDebug("FS Watcher is watching %s in normal mode", qUtf8Printable(path));
|
LogMsg(tr("Watching local folder: \"%1\"").arg(Utils::Fs::toNativePath(path)));
|
||||||
QFileSystemWatcher::addPath(path);
|
QFileSystemWatcher::addPath(path);
|
||||||
scanLocalFolder(path);
|
scanLocalFolder(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemWatcher::removePath(const QString &path)
|
void FileSystemWatcher::removePath(const QString &path)
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
if (m_watchedFolders.removeOne(path)) {
|
if (m_watchedFolders.removeOne(path)) {
|
||||||
if (m_watchedFolders.isEmpty())
|
if (m_watchedFolders.isEmpty())
|
||||||
m_watchTimer.stop();
|
m_watchTimer.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// Normal mode
|
// Normal mode
|
||||||
QFileSystemWatcher::removePath(path);
|
QFileSystemWatcher::removePath(path);
|
||||||
}
|
}
|
||||||
@@ -116,13 +111,11 @@ void FileSystemWatcher::scanLocalFolder(const QString &path)
|
|||||||
QTimer::singleShot(2000, this, [this, path]() { processTorrentsInDir(path); });
|
QTimer::singleShot(2000, this, [this, path]() { processTorrentsInDir(path); });
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
void FileSystemWatcher::scanNetworkFolders()
|
void FileSystemWatcher::scanNetworkFolders()
|
||||||
{
|
{
|
||||||
for (const QDir &dir : qAsConst(m_watchedFolders))
|
for (const QDir &dir : asConst(m_watchedFolders))
|
||||||
processTorrentsInDir(dir);
|
processTorrentsInDir(dir);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void FileSystemWatcher::processPartialTorrents()
|
void FileSystemWatcher::processPartialTorrents()
|
||||||
{
|
{
|
||||||
@@ -169,7 +162,7 @@ void FileSystemWatcher::processTorrentsInDir(const QDir &dir)
|
|||||||
const QStringList files = dir.entryList({"*.torrent", "*.magnet"}, QDir::Files);
|
const QStringList files = dir.entryList({"*.torrent", "*.magnet"}, QDir::Files);
|
||||||
for (const QString &file : files) {
|
for (const QString &file : files) {
|
||||||
const QString fileAbsPath = dir.absoluteFilePath(file);
|
const QString fileAbsPath = dir.absoluteFilePath(file);
|
||||||
if (file.endsWith(".magnet"))
|
if (file.endsWith(".magnet", Qt::CaseInsensitive))
|
||||||
torrents << fileAbsPath;
|
torrents << fileAbsPath;
|
||||||
else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid())
|
else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid())
|
||||||
torrents << fileAbsPath;
|
torrents << fileAbsPath;
|
||||||
|
|||||||
@@ -56,9 +56,7 @@ signals:
|
|||||||
protected slots:
|
protected slots:
|
||||||
void scanLocalFolder(const QString &path);
|
void scanLocalFolder(const QString &path);
|
||||||
void processPartialTorrents();
|
void processPartialTorrents();
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
void scanNetworkFolders();
|
void scanNetworkFolders();
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processTorrentsInDir(const QDir &dir);
|
void processTorrentsInDir(const QDir &dir);
|
||||||
@@ -67,10 +65,8 @@ private:
|
|||||||
QHash<QString, int> m_partialTorrents;
|
QHash<QString, int> m_partialTorrents;
|
||||||
QTimer m_partialTorrentTimer;
|
QTimer m_partialTorrentTimer;
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
QList<QDir> m_watchedFolders;
|
QList<QDir> m_watchedFolders;
|
||||||
QTimer m_watchTimer;
|
QTimer m_watchTimer;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FILESYSTEMWATCHER_H
|
#endif // FILESYSTEMWATCHER_H
|
||||||
|
|||||||
@@ -32,17 +32,15 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
const char C_TORRENT_FILE_EXTENSION[] = ".torrent";
|
const char C_TORRENT_FILE_EXTENSION[] = ".torrent";
|
||||||
|
const int MAX_TORRENT_SIZE = 100 * 1024 * 1024; // 100 MiB
|
||||||
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; }
|
constexpr typename std::add_const<T>::type &asConst(T &t) noexcept { return t; }
|
||||||
|
|
||||||
// prevent rvalue arguments:
|
// Forward rvalue as const
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void qAsConst(const T &&) = delete;
|
constexpr typename std::add_const<T>::type asConst(T &&t) noexcept { return std::move(t); }
|
||||||
#endif
|
|
||||||
|
|
||||||
// returns a const object copy
|
// Prevent const rvalue arguments
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr typename std::add_const<T>::type copyAsConst(T &&t) noexcept { return std::move(t); }
|
void asConst(const T &&) = delete;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2018 Mike Tzou (Chocobo1)
|
* Copyright (C) 2018 Mike Tzou (Chocobo1)
|
||||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
* Copyright (C) 2006 Ishan Arora and Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -26,13 +26,10 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
#include <QRegExp>
|
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
@@ -69,7 +66,7 @@ void Connection::read()
|
|||||||
case RequestParser::ParseStatus::Incomplete: {
|
case RequestParser::ParseStatus::Incomplete: {
|
||||||
const long bufferLimit = RequestParser::MAX_CONTENT_SIZE * 1.1; // some margin for headers
|
const long bufferLimit = RequestParser::MAX_CONTENT_SIZE * 1.1; // some margin for headers
|
||||||
if (m_receivedData.size() > bufferLimit) {
|
if (m_receivedData.size() > bufferLimit) {
|
||||||
Logger::instance()->addMessage(tr("Http request size exceeds limiation, closing socket. Limit: %ld, IP: %s")
|
Logger::instance()->addMessage(tr("Http request size exceeds limiation, closing socket. Limit: %1, IP: %2")
|
||||||
.arg(bufferLimit).arg(m_socket->peerAddress().toString()), Log::WARNING);
|
.arg(bufferLimit).arg(m_socket->peerAddress().toString()), Log::WARNING);
|
||||||
|
|
||||||
Response resp(413, "Payload Too Large");
|
Response resp(413, "Payload Too Large");
|
||||||
@@ -82,7 +79,7 @@ void Connection::read()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case RequestParser::ParseStatus::BadRequest: {
|
case RequestParser::ParseStatus::BadRequest: {
|
||||||
Logger::instance()->addMessage(tr("Bad Http request, closing socket. IP: %s")
|
Logger::instance()->addMessage(tr("Bad Http request, closing socket. IP: %1")
|
||||||
.arg(m_socket->peerAddress().toString()), Log::WARNING);
|
.arg(m_socket->peerAddress().toString()), Log::WARNING);
|
||||||
|
|
||||||
Response resp(400, "Bad Request");
|
Response resp(400, "Bad Request");
|
||||||
@@ -136,7 +133,7 @@ bool Connection::acceptsGzipEncoding(QString codings)
|
|||||||
|
|
||||||
const auto isCodingAvailable = [](const QStringList &list, const QString &encoding) -> bool
|
const auto isCodingAvailable = [](const QStringList &list, const QString &encoding) -> bool
|
||||||
{
|
{
|
||||||
foreach (const QString &str, list) {
|
for (const QString &str : list) {
|
||||||
if (!str.startsWith(encoding))
|
if (!str.startsWith(encoding))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
* Copyright (C) 2006 Ishan Arora and Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -25,8 +25,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +48,7 @@ namespace Http
|
|||||||
Q_DISABLE_COPY(Connection)
|
Q_DISABLE_COPY(Connection)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = 0);
|
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = nullptr);
|
||||||
~Connection();
|
~Connection();
|
||||||
|
|
||||||
bool hasExpired(qint64 timeout) const;
|
bool hasExpired(qint64 timeout) const;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include "base/global.h"
|
||||||
#include "base/utils/bytearray.h"
|
#include "base/utils/bytearray.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
|
|
||||||
@@ -180,11 +181,29 @@ bool RequestParser::parseRequestLine(const QString &line)
|
|||||||
m_request.method = match.captured(1);
|
m_request.method = match.captured(1);
|
||||||
|
|
||||||
// Request Target
|
// Request Target
|
||||||
const QByteArray decodedUrl {QByteArray::fromPercentEncoding(match.captured(2).toLatin1())};
|
const QByteArray url {match.captured(2).toLatin1()};
|
||||||
const int sepPos = decodedUrl.indexOf('?');
|
const int sepPos = url.indexOf('?');
|
||||||
m_request.path = QString::fromUtf8(decodedUrl.constData(), (sepPos == -1 ? decodedUrl.size() : sepPos));
|
const QByteArray pathComponent = ((sepPos == -1) ? url : midView(url, 0, sepPos));
|
||||||
if (sepPos >= 0)
|
|
||||||
m_request.query = decodedUrl.mid(sepPos + 1);
|
m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent));
|
||||||
|
|
||||||
|
if (sepPos >= 0) {
|
||||||
|
const QByteArray query = midView(url, (sepPos + 1));
|
||||||
|
|
||||||
|
// [rfc3986] 2.4 When to Encode or Decode
|
||||||
|
// URL components should be separated before percent-decoding
|
||||||
|
for (const QByteArray ¶m : asConst(splitToViews(query, "&"))) {
|
||||||
|
const int eqCharPos = param.indexOf('=');
|
||||||
|
if (eqCharPos <= 0) continue; // ignores params without name
|
||||||
|
|
||||||
|
const QByteArray nameComponent = midView(param, 0, eqCharPos);
|
||||||
|
const QByteArray valueComponent = midView(param, (eqCharPos + 1));
|
||||||
|
const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' '));
|
||||||
|
const QByteArray paramValue = QByteArray::fromPercentEncoding(valueComponent).replace('+', ' ');
|
||||||
|
|
||||||
|
m_request.query[paramName] = paramValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP-version
|
// HTTP-version
|
||||||
m_request.version = match.captured(3);
|
m_request.version = match.captured(3);
|
||||||
@@ -200,7 +219,10 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
|||||||
|
|
||||||
// application/x-www-form-urlencoded
|
// application/x-www-form-urlencoded
|
||||||
if (contentTypeLower.startsWith(CONTENT_TYPE_FORM_ENCODED)) {
|
if (contentTypeLower.startsWith(CONTENT_TYPE_FORM_ENCODED)) {
|
||||||
QListIterator<QStringPair> i(QUrlQuery(data).queryItems(QUrl::FullyDecoded));
|
// [URL Standard] 5.1 application/x-www-form-urlencoded parsing
|
||||||
|
const QByteArray processedData = QByteArray(data).replace('+', ' ');
|
||||||
|
|
||||||
|
QListIterator<QStringPair> i(QUrlQuery(processedData).queryItems(QUrl::FullyDecoded));
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
const QStringPair pair = i.next();
|
const QStringPair pair = i.next();
|
||||||
m_request.posts[pair.first] = pair.second;
|
m_request.posts[pair.first] = pair.second;
|
||||||
@@ -291,7 +313,7 @@ bool RequestParser::parseFormData(const QByteArray &data)
|
|||||||
const QLatin1String name("name");
|
const QLatin1String name("name");
|
||||||
|
|
||||||
if (headersMap.contains(filename)) {
|
if (headersMap.contains(filename)) {
|
||||||
m_request.files.append({filename, headersMap[HEADER_CONTENT_TYPE], payload});
|
m_request.files.append({headersMap[filename], headersMap[HEADER_CONTENT_TYPE], payload});
|
||||||
}
|
}
|
||||||
else if (headersMap.contains(name)) {
|
else if (headersMap.contains(name)) {
|
||||||
m_request.posts[headersMap[name]] = payload;
|
m_request.posts[headersMap[name]] = payload;
|
||||||
|
|||||||
@@ -97,16 +97,23 @@ void Server::incomingConnection(qintptr socketDescriptor)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Connection *c = new Connection(serverSocket, m_requestHandler, this);
|
Connection *c = new Connection(serverSocket, m_requestHandler, this);
|
||||||
m_connections.append(c);
|
m_connections.insert(c);
|
||||||
|
connect(serverSocket, &QAbstractSocket::disconnected, this, [c, this]() { removeConnection(c); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::removeConnection(Connection *connection)
|
||||||
|
{
|
||||||
|
m_connections.remove(connection);
|
||||||
|
connection->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::dropTimedOutConnection()
|
void Server::dropTimedOutConnection()
|
||||||
{
|
{
|
||||||
QMutableListIterator<Connection *> i(m_connections);
|
QMutableSetIterator<Connection *> i(m_connections);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
auto connection = i.next();
|
Connection *connection = i.next();
|
||||||
if (connection->isClosed() || connection->hasExpired(KEEP_ALIVE_DURATION)) {
|
if (connection->hasExpired(KEEP_ALIVE_DURATION)) {
|
||||||
delete connection;
|
connection->deleteLater();
|
||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,9 +153,9 @@ QList<QSslCipher> Server::safeCipherList() const
|
|||||||
const QStringList badCiphers = {"idea", "rc4"};
|
const QStringList badCiphers = {"idea", "rc4"};
|
||||||
const QList<QSslCipher> allCiphers = QSslSocket::supportedCiphers();
|
const QList<QSslCipher> allCiphers = QSslSocket::supportedCiphers();
|
||||||
QList<QSslCipher> safeCiphers;
|
QList<QSslCipher> safeCiphers;
|
||||||
foreach (const QSslCipher &cipher, allCiphers) {
|
for (const QSslCipher &cipher : allCiphers) {
|
||||||
bool isSafe = true;
|
bool isSafe = true;
|
||||||
foreach (const QString &badCipher, badCiphers) {
|
for (const QString &badCipher : badCiphers) {
|
||||||
if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) {
|
if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) {
|
||||||
isSafe = false;
|
isSafe = false;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#ifndef HTTP_SERVER_H
|
#ifndef HTTP_SERVER_H
|
||||||
#define HTTP_SERVER_H
|
#define HTTP_SERVER_H
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
@@ -63,9 +64,10 @@ namespace Http
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void incomingConnection(qintptr socketDescriptor);
|
void incomingConnection(qintptr socketDescriptor);
|
||||||
|
void removeConnection(Connection *connection);
|
||||||
|
|
||||||
IRequestHandler *m_requestHandler;
|
IRequestHandler *m_requestHandler;
|
||||||
QList<Connection *> m_connections; // for tracking persistent connections
|
QSet<Connection *> m_connections; // for tracking persistent connections
|
||||||
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
QList<QSslCipher> safeCipherList() const;
|
QList<QSslCipher> safeCipherList() const;
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ namespace Http
|
|||||||
const char HEADER_HOST[] = "host";
|
const char HEADER_HOST[] = "host";
|
||||||
const char HEADER_ORIGIN[] = "origin";
|
const char HEADER_ORIGIN[] = "origin";
|
||||||
const char HEADER_REFERER[] = "referer";
|
const char HEADER_REFERER[] = "referer";
|
||||||
|
const char HEADER_REFERRER_POLICY[] = "referrer-policy";
|
||||||
const char HEADER_SET_COOKIE[] = "set-cookie";
|
const char HEADER_SET_COOKIE[] = "set-cookie";
|
||||||
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options";
|
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options";
|
||||||
const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host";
|
const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host";
|
||||||
@@ -63,10 +64,12 @@ namespace Http
|
|||||||
const char HEADER_REQUEST_METHOD_POST[] = "POST";
|
const char HEADER_REQUEST_METHOD_POST[] = "POST";
|
||||||
|
|
||||||
const char CONTENT_TYPE_HTML[] = "text/html";
|
const char CONTENT_TYPE_HTML[] = "text/html";
|
||||||
|
const char CONTENT_TYPE_CSS[] = "text/css";
|
||||||
|
const char CONTENT_TYPE_TXT[] = "text/plain";
|
||||||
|
const char CONTENT_TYPE_JS[] = "application/javascript";
|
||||||
const char CONTENT_TYPE_JSON[] = "application/json";
|
const char CONTENT_TYPE_JSON[] = "application/json";
|
||||||
const char CONTENT_TYPE_GIF[] = "image/gif";
|
const char CONTENT_TYPE_GIF[] = "image/gif";
|
||||||
const char CONTENT_TYPE_PNG[] = "image/png";
|
const char CONTENT_TYPE_PNG[] = "image/png";
|
||||||
const char CONTENT_TYPE_TXT[] = "text/plain";
|
|
||||||
const char CONTENT_TYPE_FORM_ENCODED[] = "application/x-www-form-urlencoded";
|
const char CONTENT_TYPE_FORM_ENCODED[] = "application/x-www-form-urlencoded";
|
||||||
const char CONTENT_TYPE_FORM_DATA[] = "multipart/form-data";
|
const char CONTENT_TYPE_FORM_DATA[] = "multipart/form-data";
|
||||||
|
|
||||||
@@ -94,8 +97,8 @@ namespace Http
|
|||||||
QString version;
|
QString version;
|
||||||
QString method;
|
QString method;
|
||||||
QString path;
|
QString path;
|
||||||
QByteArray query;
|
|
||||||
QStringMap headers;
|
QStringMap headers;
|
||||||
|
QMap<QString, QByteArray> query;
|
||||||
QStringMap posts;
|
QStringMap posts;
|
||||||
QVector<UploadedFile> files;
|
QVector<UploadedFile> files;
|
||||||
};
|
};
|
||||||
@@ -105,7 +108,7 @@ namespace Http
|
|||||||
uint code;
|
uint code;
|
||||||
QString text;
|
QString text;
|
||||||
|
|
||||||
ResponseStatus(uint code = 200, const QString& text = "OK"): code(code), text(text) {}
|
ResponseStatus(uint code = 200, const QString &text = "OK"): code(code), text(text) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Response
|
struct Response
|
||||||
@@ -114,7 +117,7 @@ namespace Http
|
|||||||
QStringMap headers;
|
QStringMap headers;
|
||||||
QByteArray content;
|
QByteArray content;
|
||||||
|
|
||||||
Response(uint code = 200, const QString& text = "OK"): status(code, text) {}
|
Response(uint code = 200, const QString &text = "OK"): status(code, text) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,10 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
IconProvider::IconProvider(QObject *parent)
|
IconProvider::IconProvider(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
@@ -47,7 +48,7 @@ void IconProvider::freeInstance()
|
|||||||
{
|
{
|
||||||
if (m_instance) {
|
if (m_instance) {
|
||||||
delete m_instance;
|
delete m_instance;
|
||||||
m_instance = 0;
|
m_instance = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,9 +57,15 @@ IconProvider *IconProvider::instance()
|
|||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString IconProvider::getIconPath(const QString &iconId)
|
QString IconProvider::getIconPath(const QString &iconId) const
|
||||||
{
|
{
|
||||||
return ":/icons/qbt-theme/" + iconId + ".png";
|
// there are a few icons not available in svg
|
||||||
|
const QString pathSvg = ":/icons/qbt-theme/" + iconId + ".svg";
|
||||||
|
if (QFileInfo::exists(pathSvg))
|
||||||
|
return pathSvg;
|
||||||
|
|
||||||
|
const QString pathPng = ":/icons/qbt-theme/" + iconId + ".png";
|
||||||
|
return pathPng;
|
||||||
}
|
}
|
||||||
|
|
||||||
IconProvider *IconProvider::m_instance = 0;
|
IconProvider *IconProvider::m_instance = nullptr;
|
||||||
|
|||||||
@@ -31,8 +31,7 @@
|
|||||||
#define ICONPROVIDER_H
|
#define ICONPROVIDER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
class QString;
|
|
||||||
|
|
||||||
class IconProvider : public QObject
|
class IconProvider : public QObject
|
||||||
{
|
{
|
||||||
@@ -43,10 +42,10 @@ public:
|
|||||||
static void freeInstance();
|
static void freeInstance();
|
||||||
static IconProvider *instance();
|
static IconProvider *instance();
|
||||||
|
|
||||||
virtual QString getIconPath(const QString &iconId);
|
virtual QString getIconPath(const QString &iconId) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit IconProvider(QObject *parent = 0);
|
explicit IconProvider(QObject *parent = nullptr);
|
||||||
~IconProvider();
|
~IconProvider();
|
||||||
|
|
||||||
static IconProvider *m_instance;
|
static IconProvider *m_instance;
|
||||||
|
|||||||
@@ -38,30 +38,30 @@ class IndexInterval
|
|||||||
public:
|
public:
|
||||||
using IndexType = Index;
|
using IndexType = Index;
|
||||||
|
|
||||||
IndexInterval(IndexType first, IndexType last)
|
IndexInterval(IndexType first, IndexType last) // add constexpr when using C++14
|
||||||
: m_first {first}
|
: m_first {first}
|
||||||
, m_last {last}
|
, m_last {last}
|
||||||
{
|
{
|
||||||
Q_ASSERT(first <= last);
|
Q_ASSERT(first <= last);
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexType first() const
|
constexpr IndexType first() const
|
||||||
{
|
{
|
||||||
return m_first;
|
return m_first;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexType last() const
|
constexpr IndexType last() const
|
||||||
{
|
{
|
||||||
return m_last;
|
return m_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IndexType m_first;
|
const IndexType m_first;
|
||||||
IndexType m_last;
|
const IndexType m_last;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline IndexInterval<T> makeInterval(T first, T last)
|
constexpr IndexInterval<T> makeInterval(T first, T last)
|
||||||
{
|
{
|
||||||
return {first, last};
|
return {first, last};
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
|
|
||||||
constexpr IndexType end() const
|
constexpr IndexType end() const
|
||||||
{
|
{
|
||||||
return m_first + m_size;
|
return (m_first + m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr IndexDiffType size() const
|
constexpr IndexDiffType size() const
|
||||||
@@ -114,12 +114,12 @@ public:
|
|||||||
|
|
||||||
constexpr IndexType last() const
|
constexpr IndexType last() const
|
||||||
{
|
{
|
||||||
return m_first + m_size - 1;
|
return (m_first + m_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool isEmpty() const
|
constexpr bool isEmpty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return (m_size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
|
|
||||||
Logger* Logger::m_instance = 0;
|
Logger *Logger::m_instance = nullptr;
|
||||||
|
|
||||||
Logger::Logger()
|
Logger::Logger()
|
||||||
: lock(QReadWriteLock::Recursive)
|
: m_lock(QReadWriteLock::Recursive)
|
||||||
, msgCounter(0)
|
, m_msgCounter(0)
|
||||||
, peerCounter(0)
|
, m_peerCounter(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,15 +29,15 @@ void Logger::freeInstance()
|
|||||||
{
|
{
|
||||||
if (m_instance) {
|
if (m_instance) {
|
||||||
delete m_instance;
|
delete m_instance;
|
||||||
m_instance = 0;
|
m_instance = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&lock);
|
QWriteLocker locker(&m_lock);
|
||||||
|
|
||||||
Log::Msg temp = { msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped() };
|
Log::Msg temp = {m_msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped()};
|
||||||
m_messages.push_back(temp);
|
m_messages.push_back(temp);
|
||||||
|
|
||||||
if (m_messages.size() >= MAX_LOG_MESSAGES)
|
if (m_messages.size() >= MAX_LOG_MESSAGES)
|
||||||
@@ -48,9 +48,9 @@ void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
|||||||
|
|
||||||
void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
|
void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&lock);
|
QWriteLocker locker(&m_lock);
|
||||||
|
|
||||||
Log::Peer temp = { peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped() };
|
Log::Peer temp = {m_peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped()};
|
||||||
m_peers.push_back(temp);
|
m_peers.push_back(temp);
|
||||||
|
|
||||||
if (m_peers.size() >= MAX_LOG_MESSAGES)
|
if (m_peers.size() >= MAX_LOG_MESSAGES)
|
||||||
@@ -61,9 +61,9 @@ void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
|
|||||||
|
|
||||||
QVector<Log::Msg> Logger::getMessages(int lastKnownId) const
|
QVector<Log::Msg> Logger::getMessages(int lastKnownId) const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
int diff = msgCounter - lastKnownId - 1;
|
int diff = m_msgCounter - lastKnownId - 1;
|
||||||
int size = m_messages.size();
|
int size = m_messages.size();
|
||||||
|
|
||||||
if ((lastKnownId == -1) || (diff >= size))
|
if ((lastKnownId == -1) || (diff >= size))
|
||||||
@@ -77,9 +77,9 @@ QVector<Log::Msg> Logger::getMessages(int lastKnownId) const
|
|||||||
|
|
||||||
QVector<Log::Peer> Logger::getPeers(int lastKnownId) const
|
QVector<Log::Peer> Logger::getPeers(int lastKnownId) const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
int diff = peerCounter - lastKnownId - 1;
|
int diff = m_peerCounter - lastKnownId - 1;
|
||||||
int size = m_peers.size();
|
int size = m_peers.size();
|
||||||
|
|
||||||
if ((lastKnownId == -1) || (diff >= size))
|
if ((lastKnownId == -1) || (diff >= size))
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef LOGGER_H
|
#ifndef LOGGER_H
|
||||||
#define LOGGER_H
|
#define LOGGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QReadWriteLock>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QReadWriteLock>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
const int MAX_LOG_MESSAGES = 20000;
|
const int MAX_LOG_MESSAGES = 20000;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ namespace Log
|
|||||||
NORMAL = 0x1,
|
NORMAL = 0x1,
|
||||||
INFO = 0x2,
|
INFO = 0x2,
|
||||||
WARNING = 0x4,
|
WARNING = 0x4,
|
||||||
CRITICAL = 0x8 //ERROR is defined by libtorrent and results in compiler error
|
CRITICAL = 0x8 // ERROR is defined by libtorrent and results in compiler error
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(MsgTypes, MsgType)
|
Q_DECLARE_FLAGS(MsgTypes, MsgType)
|
||||||
|
|
||||||
@@ -63,12 +63,12 @@ private:
|
|||||||
Logger();
|
Logger();
|
||||||
~Logger();
|
~Logger();
|
||||||
|
|
||||||
static Logger* m_instance;
|
static Logger *m_instance;
|
||||||
QVector<Log::Msg> m_messages;
|
QVector<Log::Msg> m_messages;
|
||||||
QVector<Log::Peer> m_peers;
|
QVector<Log::Peer> m_peers;
|
||||||
mutable QReadWriteLock lock;
|
mutable QReadWriteLock m_lock;
|
||||||
int msgCounter;
|
int m_msgCounter;
|
||||||
int peerCounter;
|
int m_peerCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function
|
// Helper function
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user