Compare commits
256 Commits
release-4.
...
release-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede7c8acbb | ||
|
|
9195df5179 | ||
|
|
a3d5ea829b | ||
|
|
c062f86bac | ||
|
|
e5894831ec | ||
|
|
f40e92f186 | ||
|
|
0ab10ef2b3 | ||
|
|
049e376953 | ||
|
|
6dab4615aa | ||
|
|
0b9a1dfd9d | ||
|
|
11c45db2ec | ||
|
|
ba147d72b9 | ||
|
|
97ead6d7c9 | ||
|
|
51cb3ca0c8 | ||
|
|
c514c2b7a8 | ||
|
|
d26e582cc1 | ||
|
|
5d161d2477 | ||
|
|
b9ea6a5dc5 | ||
|
|
7b0b64a04e | ||
|
|
4cb386af35 | ||
|
|
14ab1b015c | ||
|
|
0a4971c994 | ||
|
|
a75ae21434 | ||
|
|
01eed5dae9 | ||
|
|
e73397c750 | ||
|
|
869d079507 | ||
|
|
71174edf72 | ||
|
|
b3d46ecb78 | ||
|
|
80035a2520 | ||
|
|
6790335239 | ||
|
|
48ff494dca | ||
|
|
c5b361ce74 | ||
|
|
397b7b9407 | ||
|
|
6e0c1e2147 | ||
|
|
e93c360db6 | ||
|
|
270e2023cd | ||
|
|
5ac858213b | ||
|
|
f0ee6aba29 | ||
|
|
fa418087c4 | ||
|
|
8493e1ad64 | ||
|
|
fe90fcef5b | ||
|
|
210fd80167 | ||
|
|
0a1e864f74 | ||
|
|
7adccab687 | ||
|
|
67e536d869 | ||
|
|
86e8d848f6 | ||
|
|
88114b4588 | ||
|
|
e468f004f4 | ||
|
|
4cfccc54ea | ||
|
|
5ffa7e4752 | ||
|
|
d7fd576293 | ||
|
|
83b34053a1 | ||
|
|
b9164adb7a | ||
|
|
8397b118b7 | ||
|
|
74dc000ac1 | ||
|
|
9b61991523 | ||
|
|
702c79a92f | ||
|
|
a27822b557 | ||
|
|
bdcb00a3b2 | ||
|
|
ac5a485651 | ||
|
|
e8c65388eb | ||
|
|
f2cbb61d49 | ||
|
|
0a1c61d9d3 | ||
|
|
01a0fff4c2 | ||
|
|
bf9516d164 | ||
|
|
fdbf8cb0ee | ||
|
|
7e8a176751 | ||
|
|
61504ae3b1 | ||
|
|
dd76525372 | ||
|
|
1c0f8b4289 | ||
|
|
63043b4927 | ||
|
|
3ea4c66d41 | ||
|
|
781d7fbf1a | ||
|
|
e7ebbffbfd | ||
|
|
39f054eef6 | ||
|
|
7a620c794d | ||
|
|
cc13f3e10d | ||
|
|
b0e41abf5a | ||
|
|
5347897b7d | ||
|
|
6f8fae9a7b | ||
|
|
62b50d1475 | ||
|
|
2fb0c86f1e | ||
|
|
aedd997604 | ||
|
|
aa3da942cb | ||
|
|
87e1a14a4b | ||
|
|
00f6bb7c82 | ||
|
|
cca93c2be2 | ||
|
|
ad9d0608d4 | ||
|
|
3c5688c6f6 | ||
|
|
ece92a886a | ||
|
|
85777ea491 | ||
|
|
b8a84dbd83 | ||
|
|
35c31906b7 | ||
|
|
1fa940876f | ||
|
|
c652123145 | ||
|
|
1c52fff1cc | ||
|
|
261f08b90e | ||
|
|
2d48581570 | ||
|
|
b8a7ecfe69 | ||
|
|
cbc2de6b85 | ||
|
|
9d2bb67834 | ||
|
|
3d7ff9765a | ||
|
|
28f2def21f | ||
|
|
0ee303789a | ||
|
|
6ccc92020c | ||
|
|
e3fe66d3ec | ||
|
|
ab5605d54b | ||
|
|
a7a90613c2 | ||
|
|
19d95ebd10 | ||
|
|
0e1849346b | ||
|
|
0f34e3bed9 | ||
|
|
c8b66b25e8 | ||
|
|
e6f07a6fe4 | ||
|
|
51469f8fa2 | ||
|
|
d78b2a569f | ||
|
|
ec6c970775 | ||
|
|
67c45efff7 | ||
|
|
a54772bf35 | ||
|
|
166be2a94d | ||
|
|
7150d05399 | ||
|
|
36a6e22f27 | ||
|
|
dc13eaed1f | ||
|
|
001bd60d36 | ||
|
|
b063042988 | ||
|
|
fa1d49add5 | ||
|
|
b45248bf99 | ||
|
|
dfe862dcd5 | ||
|
|
d4ddeaa917 | ||
|
|
13a49866a7 | ||
|
|
7e2aea92b0 | ||
|
|
7db51b2f8d | ||
|
|
ae1b963e0f | ||
|
|
b29b7e0185 | ||
|
|
71270260bf | ||
|
|
22abbc1d41 | ||
|
|
32698fe0be | ||
|
|
16f8d6a936 | ||
|
|
046d6f3bc1 | ||
|
|
e33c4086b9 | ||
|
|
51d754a53e | ||
|
|
49976bcd83 | ||
|
|
f991d2bdb4 | ||
|
|
e6ff23885e | ||
|
|
7aa859a442 | ||
|
|
180deb867a | ||
|
|
a5c531f0a4 | ||
|
|
5dd70b88d3 | ||
|
|
40f2718265 | ||
|
|
ddd106655d | ||
|
|
cc61ad01b6 | ||
|
|
8a44c1f6d5 | ||
|
|
e370cbb06b | ||
|
|
cb0c2e3b9c | ||
|
|
80360cc79a | ||
|
|
559a979536 | ||
|
|
5e88537809 | ||
|
|
8b60baea99 | ||
|
|
ac61c33d1c | ||
|
|
3088f04e6f | ||
|
|
864dca1b67 | ||
|
|
15320018f0 | ||
|
|
6226dd5b80 | ||
|
|
aafc1064d9 | ||
|
|
fb2fbc875d | ||
|
|
8085db6ba9 | ||
|
|
4f20769a6c | ||
|
|
090199f9de | ||
|
|
cd3635985e | ||
|
|
8a7179195f | ||
|
|
e45e29b431 | ||
|
|
ca28fc27dc | ||
|
|
08b2cde8e8 | ||
|
|
489d88e02a | ||
|
|
dff39ffd20 | ||
|
|
3c948ef063 | ||
|
|
7087565d92 | ||
|
|
3467358663 | ||
|
|
45a1c25a29 | ||
|
|
70a11a12b3 | ||
|
|
5d5b0d572e | ||
|
|
7c8eadfddf | ||
|
|
89ca0c537d | ||
|
|
a92a6404cb | ||
|
|
78459fcb31 | ||
|
|
41fc0fd084 | ||
|
|
5c9655abc3 | ||
|
|
3301797491 | ||
|
|
eb5e1d34df | ||
|
|
9e92e5995f | ||
|
|
e96f2d7be0 | ||
|
|
03cb51844b | ||
|
|
6b06cc9216 | ||
|
|
6b49323f05 | ||
|
|
4a11fab2b1 | ||
|
|
c382191e75 | ||
|
|
4d480b8761 | ||
|
|
cd25562fd2 | ||
|
|
9a3d560d9e | ||
|
|
4924fb95f8 | ||
|
|
6de67fe81f | ||
|
|
bc71827c01 | ||
|
|
a8ade3a04b | ||
|
|
eca04e2e92 | ||
|
|
763b9fc1da | ||
|
|
add75fbc77 | ||
|
|
86b1ac5d7c | ||
|
|
b51197936b | ||
|
|
64609ce5cf | ||
|
|
b81cbf9062 | ||
|
|
e7e881e5d7 | ||
|
|
e236a76d5a | ||
|
|
ad8a827c1f | ||
|
|
08ac33bc5c | ||
|
|
5cf39a2970 | ||
|
|
1c9321d5a1 | ||
|
|
97a8d865dc | ||
|
|
982133d9b6 | ||
|
|
d23935a269 | ||
|
|
1c343a444b | ||
|
|
1c9696b68e | ||
|
|
ecd23d0abd | ||
|
|
010d1b5ff8 | ||
|
|
46394a7c0f | ||
|
|
fc86034fab | ||
|
|
03012cc175 | ||
|
|
8518333406 | ||
|
|
b2e0e25f1c | ||
|
|
9673be17cb | ||
|
|
fa8786e230 | ||
|
|
21f72baae2 | ||
|
|
4b78af268f | ||
|
|
a734199383 | ||
|
|
046b741700 | ||
|
|
ce0b6f0d56 | ||
|
|
6de0622c1a | ||
|
|
6229b81730 | ||
|
|
c701379a2e | ||
|
|
0783968121 | ||
|
|
307f5e6e56 | ||
|
|
cb29685a24 | ||
|
|
dabba89682 | ||
|
|
2efd4f2a77 | ||
|
|
90296b3ef0 | ||
|
|
8f02fe0cc6 | ||
|
|
7a6edcdddb | ||
|
|
81139c0098 | ||
|
|
6a6268c068 | ||
|
|
68133ec8e3 | ||
|
|
314f92f2d8 | ||
|
|
8b5db328ec | ||
|
|
615b76f78c | ||
|
|
f2912c14ea | ||
|
|
08f33d7e9e | ||
|
|
c034cb5985 | ||
|
|
e3cd15dced | ||
|
|
8439d4e827 |
@@ -3,7 +3,7 @@ version: '{branch}-{build}'
|
|||||||
# Do not build on tags (GitHub only)
|
# Do not build on tags (GitHub only)
|
||||||
skip_tags: true
|
skip_tags: true
|
||||||
|
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2022
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
except: # blacklist
|
except: # blacklist
|
||||||
@@ -42,7 +42,7 @@ install:
|
|||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
# setup env
|
# setup env
|
||||||
- CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
- CALL "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||||
- SET PATH=%PATH%;C:\Qt\5.15.2\msvc2019_64\bin;%CACHE_DIR%\jom
|
- SET PATH=%PATH%;C:\Qt\5.15.2\msvc2019_64\bin;%CACHE_DIR%\jom
|
||||||
# setup project
|
# setup project
|
||||||
- COPY /Y "%CACHE_DIR%\conf.pri" "%REPO_DIR%"
|
- COPY /Y "%CACHE_DIR%\conf.pri" "%REPO_DIR%"
|
||||||
@@ -56,4 +56,38 @@ build_script:
|
|||||||
- qmake qbittorrent.pro && cd src && qmake src.pro
|
- qmake qbittorrent.pro && cd src && qmake src.pro
|
||||||
- jom -j2 -f Makefile.Release
|
- jom -j2 -f Makefile.Release
|
||||||
|
|
||||||
|
after_build:
|
||||||
|
- cd "%REPO_DIR%"
|
||||||
|
- MKDIR upload
|
||||||
|
- COPY dist\windows\qt.conf upload
|
||||||
|
- COPY src\release\qbittorrent.exe upload
|
||||||
|
- COPY src\release\qbittorrent.pdb upload
|
||||||
|
- COPY "%CACHE_DIR%\base\bin\libcrypto-1_1-x64.dll" upload
|
||||||
|
- COPY "%CACHE_DIR%\base\bin\libssl-1_1-x64.dll" upload
|
||||||
|
- COPY "%CACHE_DIR%\base\lib\torrent-rasterbar.dll" upload
|
||||||
|
- COPY "%CACHE_DIR%\base\lib\zlib1.dll" upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Gui.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Network.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Sql.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Svg.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Widgets.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5WinExtras.dll upload
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\bin\Qt5Xml.dll upload
|
||||||
|
- MKDIR upload\plugins\iconengines
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\plugins\iconengines\qsvgicon.dll upload\plugins\iconengines
|
||||||
|
- MKDIR upload\plugins\imageformats
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\plugins\imageformats\qico.dll upload\plugins\imageformats
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\plugins\imageformats\qsvg.dll upload\plugins\imageformats
|
||||||
|
- MKDIR upload\plugins\platforms
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\plugins\platforms\qwindows.dll upload\plugins\platforms
|
||||||
|
- MKDIR upload\plugins\sqldrivers
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\plugins\sqldrivers\qsqlite.dll upload\plugins\sqldrivers
|
||||||
|
- MKDIR upload\plugins\styles
|
||||||
|
- COPY C:\Qt\5.15.2\msvc2019_64\plugins\styles\qwindowsvistastyle.dll upload\plugins\styles
|
||||||
|
|
||||||
test: off
|
test: off
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: upload
|
||||||
|
name: qBittorrent-Appveyor_Windows-x64
|
||||||
|
|||||||
89
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,89 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug Report
|
|
||||||
about: Report a problem with qBittorrent to help us resolve it.
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
# Bug report
|
|
||||||
|
|
||||||
<!--
|
|
||||||
###############################################################################
|
|
||||||
WARNING!
|
|
||||||
IGNORING THE INSTRUCTIONS IN THIS TEMPLATE WILL RESULT IN THE ISSUE BEING
|
|
||||||
CLOSED AS INCOMPLETE/INVALID
|
|
||||||
###############################################################################
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
|
|
||||||
<!--
|
|
||||||
################################## IMPORTANT ##################################
|
|
||||||
|
|
||||||
As you read and fulfill each of the following requirements below,
|
|
||||||
put an "x" between the square brackets to mark each task as done, like so: [x]
|
|
||||||
-->
|
|
||||||
|
|
||||||
- [ ] I have read the **issue reporting section** in the [contributing guidelines](https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md), so I know how to submit a good bug report with the required information
|
|
||||||
- [ ] I have verified that the **issue is not fixed and is reproducible** in the **[latest version](https://www.qbittorrent.org/download.php)**
|
|
||||||
- [ ] (optional but recommended) I have verified that the **issue is not fixed and is reproducible** in the **[latest CI build](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci.yaml?query=branch%3Amaster+event%3Apush)**
|
|
||||||
- [ ] I have **checked the [frequent/common issues list](https://github.com/qbittorrent/qBittorrent/projects/2)** and **searched** the issue tracker for similar bug reports (including closed ones) **to avoid posting a duplicate**
|
|
||||||
- [ ] This report is **not a support request or question**, both of which are better suited for either the [discussions section](https://github.com/qbittorrent/qBittorrent/discussions), [forum](https://qbforums.shiki.hu/), or [subreddit](https://www.reddit.com/r/qBittorrent/). The [wiki](https://github.com/qbittorrent/qBittorrent/wiki) did not contain a suitable solution either
|
|
||||||
- [ ] I have **pasted/attached the settings file and relevant log(s)** in the **Attachments** section at the bottom of the report. Mandatory: the settings file and at least the most recent log. See [this wiki page](https://github.com/qbittorrent/qBittorrent/wiki/Frequently-Asked-Questions#Where_does_qBittorrent_save_its_settings) if you're not sure where to find them.
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
################################## IMPORTANT ##################################
|
|
||||||
|
|
||||||
Delete each "(type here)" indicator and type your text in their place in the subsections below.
|
|
||||||
You MUST fill in ALL subsections marked with "(type here)" with the appropriate information.
|
|
||||||
|
|
||||||
Please make sure the description is worded well enough to be understood.
|
|
||||||
Provide steps to reproduce the issue, any additional relevant information, suggested solution (if applicable) and as much context and examples as possible.
|
|
||||||
For more information consult the Contributing Guidelines at https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md.
|
|
||||||
|
|
||||||
Do not forget about the mandatory attachments!
|
|
||||||
|
|
||||||
Use the Preview tab before posting to make sure your report looks like it is formatted properly.
|
|
||||||
You don't need to delete these comments, they won't show up in the final post.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### qBittorrent info and operating system(s)
|
|
||||||
|
|
||||||
<!--
|
|
||||||
IMPORTANT:
|
|
||||||
if you did not get the qBittorrent installer from the links in the official website
|
|
||||||
or if you did not install it from the PPA, please mention that after the version
|
|
||||||
-->
|
|
||||||
|
|
||||||
- qBittorrent version: (type here)
|
|
||||||
- Operating system(s) where the issue occurs: (type here)
|
|
||||||
|
|
||||||
### If on Linux, `libtorrent-rasterbar` and `Qt` versions
|
|
||||||
|
|
||||||
- Qt: (type here)
|
|
||||||
- libtorrent-rasterbar: (type here)
|
|
||||||
|
|
||||||
### What is the problem
|
|
||||||
|
|
||||||
(type here)
|
|
||||||
|
|
||||||
### Detailed steps to reproduce the problem
|
|
||||||
|
|
||||||
1. (type here)
|
|
||||||
2. (type here)
|
|
||||||
3. (etc.)
|
|
||||||
|
|
||||||
### What is the expected behavior
|
|
||||||
|
|
||||||
(type here)
|
|
||||||
|
|
||||||
### Extra info (if any)
|
|
||||||
|
|
||||||
(type here)
|
|
||||||
|
|
||||||
## Attachments
|
|
||||||
|
|
||||||
<!-- paste file contents here (or attach the files if they are big), do NOT link to external sites -->
|
|
||||||
76
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File a bug report to help improve qBittorrent user experience.
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
#### ADVISORY
|
||||||
|
"We do not support any versions older than the current release series"
|
||||||
|
|
||||||
|
"We do not support any 3rd party/forked versions e.g. `portableapps`/`Enhanced Edition`etc."
|
||||||
|
|
||||||
|
"Please post all details in **English**."
|
||||||
|
|
||||||
|
#### Prerequisites before submitting an issue!
|
||||||
|
- Read the issue reporting section in the **[contributing guidelines](https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md)**, to know how to submit a good bug report with the required information.
|
||||||
|
- Verify that the issue is not fixed and is reproducible in the **[latest official qBittorrent version](https://www.qbittorrent.org/download.php).**
|
||||||
|
- (Optional, but recommended) Verify that the issue is not fixed and is reproducible in the latest CI (**[macOS](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci_macos.yaml?query=branch%3Amaster+event%3Apush)** / **[Ubuntu](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci_ubuntu.yaml?query=branch%3Amaster+event%3Apush)** / **[Windows](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci_windows.yaml?query=branch%3Amaster+event%3Apush)**) builds.
|
||||||
|
- Check the **[frequent/common issues list](https://github.com/qbittorrent/qBittorrent/projects/2)** and perform a **[search of the issue tracker (including closed ones)](https://github.com/qbittorrent/qBittorrent/issues)** to avoid posting a duplicate.
|
||||||
|
- Make sure this is not a support request or question, both of which are better suited for either the **[discussions section](https://github.com/qbittorrent/qBittorrent/discussions)**, **[forum](https://qbforums.shiki.hu/)**, or **[subreddit](https://www.reddit.com/r/qBittorrent/)**.
|
||||||
|
- Verify that the **[wiki](https://github.com/qbittorrent/qBittorrent/wiki)** did not contain a suitable solution either.
|
||||||
|
- If relevant to issue/when asked, the qBittorrent preferences file, qBittorrent.log & watched_folders.json (if using "Watched Folders" feature) must be provided.
|
||||||
|
See **[Where does qBittorrent save its settings?](https://github.com/qbittorrent/qBittorrent/wiki/Frequently-Asked-Questions#Where_does_qBittorrent_save_its_settings)**
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: qBittorrent & operating system versions
|
||||||
|
description: |
|
||||||
|
Qt and libtorrent-rasterbar versions are required when: 1. You are using linux. 2. You are not using an official build downloaded from our website.
|
||||||
|
|
||||||
|
Example of preferred formatting:
|
||||||
|
qBittorrent: 4.3.7 x64
|
||||||
|
Operating system: Windows 10 Pro 21H1/2009 x64
|
||||||
|
Qt: 5.15.2
|
||||||
|
libtorrent-rasterbar: 1.2.14
|
||||||
|
placeholder: |
|
||||||
|
qBittorrent:
|
||||||
|
Operating system:
|
||||||
|
Qt:
|
||||||
|
libtorrent-rasterbar:
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: What is the problem?
|
||||||
|
description: Please add the "crash report" (if encountered) or give a clear and concise description of problem.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: Please provide reliable steps to reproduce the problem.
|
||||||
|
placeholder: |
|
||||||
|
1. First step
|
||||||
|
2. Second step
|
||||||
|
3. and so on...
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add screenshots etc. (Anything that will provide more context about the problem)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Log(s) & preferences file(s)
|
||||||
|
description: |
|
||||||
|
Add these files: qBittorrent preferences file, qBittorrent.log & watched_folders.json (if using "Watched Folders" feature).
|
||||||
|
See **[Where does qBittorrent save its settings?](https://github.com/qbittorrent/qBittorrent/wiki/Frequently-Asked-Questions#Where_does_qBittorrent_save_its_settings)**
|
||||||
|
#### Note: It's the user's responsibility to redact any sensitive information
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
21
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,20 +1,17 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
-
|
- name: Wiki
|
||||||
about: "Consult the wiki first (especially the FAQ), it might already contain the information you are looking for"
|
|
||||||
name: Wiki
|
|
||||||
url: "https://github.com/qbittorrent/qBittorrent/wiki/"
|
url: "https://github.com/qbittorrent/qBittorrent/wiki/"
|
||||||
|
about: "Consult the wiki first (especially the FAQ), it might already contain the information you are looking for"
|
||||||
|
|
||||||
-
|
- name: Question
|
||||||
about: "Please ask questions related to usage/setup/support/non-issue development discussion in the Discussions section"
|
|
||||||
name: Question
|
|
||||||
url: "https://github.com/qbittorrent/qBittorrent/discussions"
|
url: "https://github.com/qbittorrent/qBittorrent/discussions"
|
||||||
|
about: "Please ask questions related to usage/setup/support/non-issue development discussion in the Discussions section"
|
||||||
|
|
||||||
-
|
- name: Question
|
||||||
about: "Alternatively, ask on the official forum"
|
|
||||||
name: Question
|
|
||||||
url: "http://forum.qbittorrent.org/"
|
url: "http://forum.qbittorrent.org/"
|
||||||
-
|
about: "Alternatively, ask on the official forum"
|
||||||
about: "Alternatively, use the subreddit"
|
|
||||||
name: Question
|
- name: Question
|
||||||
url: "https://www.reddit.com/r/qBittorrent/"
|
url: "https://www.reddit.com/r/qBittorrent/"
|
||||||
|
about: "Alternatively, use the subreddit"
|
||||||
|
|||||||
61
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
about: Suggest a new feature or enhancement for qBittorrent.
|
|
||||||
title: ''
|
|
||||||
labels: 'Feature request'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
# Feature request
|
|
||||||
|
|
||||||
<!--
|
|
||||||
###############################################################################
|
|
||||||
WARNING!
|
|
||||||
IGNORING THE INSTRUCTIONS IN THIS TEMPLATE WILL RESULT IN THE ISSUE BEING
|
|
||||||
CLOSED AS INCOMPLETE/INVALID
|
|
||||||
###############################################################################
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
|
|
||||||
<!--
|
|
||||||
################################## IMPORTANT ##################################
|
|
||||||
|
|
||||||
As you read and fulfill each of the following requirements below,
|
|
||||||
put an "x" between the square brackets to mark each task as done, like so: [x]
|
|
||||||
-->
|
|
||||||
|
|
||||||
- [ ] I have read the **feature request section** in the [contributing guidelines](https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md), so I know how to submit a good feature request with the required information
|
|
||||||
- [ ] I have verified that the **feature** I am requesting is **not available** in the **[latest version](https://www.qbittorrent.org/download.php)**
|
|
||||||
- [ ] (optional but recommended) I have verified that the **feature** I am requesting is **not available** in the **[latest CI build](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci.yaml?query=branch%3Amaster+event%3Apush)**
|
|
||||||
- [ ] I have **checked the [frequent/common issues list](https://github.com/qbittorrent/qBittorrent/projects/2)** and **searched** the issue tracker for similar feature requests (including closed ones) **to avoid posting a duplicate**
|
|
||||||
- [ ] This request is **not a support request or question**, both of which are better suited for either the [discussions section](https://github.com/qbittorrent/qBittorrent/discussions), [forum](https://qbforums.shiki.hu/), or [subreddit](https://www.reddit.com/r/qBittorrent/). The [wiki](https://github.com/qbittorrent/qBittorrent/wiki) did not contain a suitable solution either
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
################################## IMPORTANT ##################################
|
|
||||||
|
|
||||||
Delete each "(type here)" indicator and type your text in their place in the subsections below.
|
|
||||||
You MUST fill in ALL subsections marked with "(type here)" with the appropriate information.
|
|
||||||
|
|
||||||
Please make sure the description is worded well enough to be understood.
|
|
||||||
Provide a detailed description of the feature and as much context and examples as necessary.
|
|
||||||
If the feature request has to do with visual elements and the GUI, images/screenshots are always helpful.
|
|
||||||
For more information consult the Contributing Guidelines at https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md.
|
|
||||||
|
|
||||||
Use the Preview tab before posting to make sure your report looks like it is formatted properly.
|
|
||||||
You don't need to delete these comments, they won't show up in the final post.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Suggestion
|
|
||||||
|
|
||||||
(type here)
|
|
||||||
|
|
||||||
### Use case
|
|
||||||
|
|
||||||
(type here)
|
|
||||||
|
|
||||||
### Extra info/examples/attachments
|
|
||||||
|
|
||||||
<!-- optional -->
|
|
||||||
37
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: Suggest a new feature or enhancement for qBittorrent.
|
||||||
|
labels: ["Feature request"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
#### ADVISORY
|
||||||
|
|
||||||
|
"Please post all details in **English**."
|
||||||
|
|
||||||
|
#### Prerequisites before submitting a feature request!
|
||||||
|
- Read the feature request section in the **[contributing guidelines](https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md)**, to know how to submit a good feature request with the required information.
|
||||||
|
- Verify that the feature being requested is not available in the **[latest official qBittorrent version](https://www.qbittorrent.org/download.php).**
|
||||||
|
- (Optional but recommended) Verify that the feature being requested is not available in the latest CI (**[macOS](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci_macos.yaml?query=branch%3Amaster+event%3Apush)** / **[Ubuntu](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci_ubuntu.yaml?query=branch%3Amaster+event%3Apush)** / **[Windows](https://github.com/qbittorrent/qBittorrent/actions/workflows/ci_windows.yaml?query=branch%3Amaster+event%3Apush)**) builds.
|
||||||
|
- Search the issue tracker with the **[feature request filter](https://github.com/qbittorrent/qBittorrent/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+request%22)** for similar feature requests (including closed ones) to avoid posting a duplicate.
|
||||||
|
- Make sure this is not a support request or question, both of which are better suited for either the **[discussions section](https://github.com/qbittorrent/qBittorrent/discussions)**, **[forum](https://qbforums.shiki.hu/)**, or **[subreddit](https://www.reddit.com/r/qBittorrent/)**.
|
||||||
|
- Verify that the **[wiki](https://github.com/qbittorrent/qBittorrent/wiki)** did not contain a suitable solution either.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Suggestion
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Use case
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Extra info/examples/attachments
|
||||||
|
description: Add screenshots etc. (Anything that will give us more context about what is being requested!)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
5
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<!--
|
||||||
|
MANDATORY Before submitting your work, make sure you have:
|
||||||
|
1. Read https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md#opening-a-pull-request
|
||||||
|
2. Delete this comment block
|
||||||
|
-->
|
||||||
16
.github/PULL_REQUEST_TEMPLATE/pull_request.md
vendored
@@ -1,16 +0,0 @@
|
|||||||
# Changes proposed in this pull request
|
|
||||||
|
|
||||||
<!--
|
|
||||||
IMPORTANT: an image is worth a thousand words.
|
|
||||||
It is often a good idea to post screenshots showing the "before" and "after" your PR's changes,
|
|
||||||
especially with changes related to the GUI, along with the textual description.
|
|
||||||
Images makes it immediately clearer for others what your proposed changes are all about.
|
|
||||||
-->
|
|
||||||
|
|
||||||
(type here)
|
|
||||||
|
|
||||||
<!--
|
|
||||||
OPTIONAL: if this PR directly addresses an issue, make sure to include a "Closes #XXXXX" statement at the end.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- You don't need to delete these comments before posting, they won't show up in the post :) -->
|
|
||||||
68
.github/workflows/check_translation_tag.py
vendored
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# A pre-commit hook for detecting problematic <translation> tags
|
||||||
|
# Copyright (C) 2021 Mike Tzou (Chocobo1)
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from typing import Optional, Sequence
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
|
||||||
|
def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('filenames', nargs='*', help='Filenames to check')
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
error_msg = ""
|
||||||
|
regex = re.compile(r"\s*</translation>")
|
||||||
|
|
||||||
|
for filename in args.filenames:
|
||||||
|
line_counter = 1
|
||||||
|
error_buffer = ""
|
||||||
|
|
||||||
|
with open(filename) as file:
|
||||||
|
try:
|
||||||
|
for line in file:
|
||||||
|
if (match := regex.match(line)) is not None:
|
||||||
|
error_buffer += str(f"Defect file: \"{filename}\"\n"
|
||||||
|
f"Line: {line_counter}\n"
|
||||||
|
f"Column span: {match.span()}\n"
|
||||||
|
f"Part: \"{match.group()}\"\n\n")
|
||||||
|
line_counter += 1
|
||||||
|
|
||||||
|
except UnicodeDecodeError as error:
|
||||||
|
# not a text file, skip
|
||||||
|
continue
|
||||||
|
|
||||||
|
error_msg += error_buffer
|
||||||
|
|
||||||
|
if len(error_msg) > 0:
|
||||||
|
print(error_msg)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
exit(main())
|
||||||
7
.github/workflows/ci_file_health.yaml
vendored
@@ -11,10 +11,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: |
|
uses: actions/setup-python@v2
|
||||||
sudo apt update
|
|
||||||
sudo apt install zsh
|
|
||||||
|
|
||||||
- name: Check files
|
- name: Check files
|
||||||
run: |
|
uses: pre-commit/action@v2.0.3
|
||||||
./.github/workflows/file_health.sh
|
|
||||||
|
|||||||
95
.github/workflows/ci_macos.yaml
vendored
@@ -4,70 +4,113 @@ on: [pull_request, push]
|
|||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: macos-10.15
|
runs-on: macos-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
|
||||||
libt_version: ["v2.0.4", "v1.2.14"]
|
|
||||||
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
libt_version: ["2.0.5", "1.2.15"]
|
||||||
|
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
||||||
|
qt_version: ["5.15.2", "6.2.0"]
|
||||||
|
exclude:
|
||||||
|
- libt_version: "1.2.15"
|
||||||
|
qt_version: "6.2.0"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
boost_path: "${{ github.workspace }}/../boost"
|
||||||
openssl_root: /usr/local/opt/openssl@1.1
|
openssl_root: /usr/local/opt/openssl@1.1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
brew update > /dev/null
|
brew update > /dev/null
|
||||||
brew install \
|
brew install \
|
||||||
cmake ninja \
|
cmake ninja \
|
||||||
boost openssl@1.1 qt@5 zlib
|
openssl@1.1 zlib
|
||||||
brew link --force \
|
|
||||||
qt@5
|
- name: Setup ccache
|
||||||
# workaround for cmake + Qt
|
uses: Chocobo1/setup-ccache-action@v1
|
||||||
sudo ln -s /usr/local/opt/qt@5/mkspecs /usr/local/mkspecs
|
with:
|
||||||
sudo ln -s /usr/local/opt/qt@5/plugins /usr/local/plugins
|
update_packager_index: false
|
||||||
|
|
||||||
|
- name: Install boost
|
||||||
|
run: |
|
||||||
|
curl \
|
||||||
|
-L \
|
||||||
|
-o "${{ runner.temp }}/boost.tar.bz2" \
|
||||||
|
"https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.bz2"
|
||||||
|
tar -xf "${{ runner.temp }}/boost.tar.bz2" -C "${{ github.workspace }}/.."
|
||||||
|
mv "${{ github.workspace }}/.."/boost_* "${{ env.boost_path }}"
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v2
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.qt_version }}
|
||||||
|
|
||||||
- name: Install libtorrent
|
- name: Install libtorrent
|
||||||
run: |
|
run: |
|
||||||
git clone --branch ${{ matrix.libt_version }} --depth 1 https://github.com/arvidn/libtorrent.git
|
git clone \
|
||||||
|
--branch v${{ matrix.libt_version }} \
|
||||||
|
--depth 1 \
|
||||||
|
--recurse-submodules \
|
||||||
|
https://github.com/arvidn/libtorrent.git
|
||||||
cd libtorrent
|
cd libtorrent
|
||||||
git submodule update --init --recursive
|
|
||||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
|
||||||
cmake \
|
cmake \
|
||||||
-B build \
|
-B build \
|
||||||
-G "Ninja" \
|
-G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
-DCMAKE_CXX_STANDARD=17 \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DBOOST_ROOT="${{ env.boost_path }}" \
|
||||||
-Ddeprecated-functions=OFF \
|
-Ddeprecated-functions=OFF \
|
||||||
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}"
|
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}"
|
||||||
cmake --build build
|
cmake --build build
|
||||||
sudo cmake --install build
|
sudo cmake --install build
|
||||||
|
|
||||||
- name: Build qBittorrent
|
- name: Build qBittorrent (Qt5)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 5) }}
|
||||||
run: |
|
run: |
|
||||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
lupdate -extensions c,cpp,h,hpp,ui ./
|
||||||
cmake \
|
cmake \
|
||||||
-B build \
|
-B build \
|
||||||
-G "Ninja" \
|
-G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-D${{ matrix.qbt_gui }} \
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DBOOST_ROOT="${{ env.boost_path }}" \
|
||||||
|
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}" \
|
||||||
-DVERBOSE_CONFIGURE=ON \
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}"
|
-D${{ matrix.qbt_gui }}
|
||||||
cmake --build build
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Build qBittorrent (Qt6)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 6) }}
|
||||||
|
run: |
|
||||||
|
lupdate -extensions c,cpp,h,hpp,ui ./
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DBOOST_ROOT="${{ env.boost_path }}" \
|
||||||
|
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}" \
|
||||||
|
-DQT6=ON \
|
||||||
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
|
-D${{ matrix.qbt_gui }}
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Prepare build artifacts
|
||||||
|
run: |
|
||||||
|
mkdir upload
|
||||||
|
mkdir upload/cmake
|
||||||
|
cp build/compile_commands.json upload/cmake
|
||||||
|
mkdir upload/cmake/libtorrent
|
||||||
|
cp libtorrent/build/compile_commands.json upload/cmake/libtorrent
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: qBittorrent-CI_macOS_${{ matrix.qbt_gui }}_libtorrent-${{ matrix.libt_version }}
|
name: build-info_macOS_${{ matrix.qbt_gui }}_libtorrent-${{ matrix.libt_version }}_Qt-${{ matrix.qt_version }}
|
||||||
path: |
|
path: upload
|
||||||
build/qbittorrent.app
|
|
||||||
build/qbittorrent-nox.app
|
|
||||||
|
|||||||
94
.github/workflows/ci_ubuntu.yaml
vendored
@@ -7,78 +7,96 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
|
||||||
libt_version: ["v2.0.4", "v1.2.14"]
|
|
||||||
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
libt_version: ["2.0.5", "1.2.15"]
|
||||||
|
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
||||||
|
qt_version: ["5.15.2", "6.2.0"]
|
||||||
|
exclude:
|
||||||
|
- libt_version: "1.2.15"
|
||||||
|
qt_version: "6.2.0"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
build-essential cmake git ninja-build pkg-config \
|
build-essential cmake ninja-build pkg-config \
|
||||||
libssl-dev libgeoip-dev zlib1g-dev \
|
libboost-dev libssl-dev zlib1g-dev
|
||||||
libboost-dev libboost-chrono-dev libboost-random-dev libboost-system-dev
|
|
||||||
# sudo apt install libqt5svg5-dev qtbase5-dev qttools5-dev # the Qt version in the standard repositories is too old...
|
- name: Setup ccache
|
||||||
|
uses: Chocobo1/setup-ccache-action@v1
|
||||||
|
with:
|
||||||
|
update_packager_index: false
|
||||||
|
ccache_options: |
|
||||||
|
max_size=2G
|
||||||
|
|
||||||
# this will be installed under /opt/qt515. CMake will still find it automatically without additional hints
|
|
||||||
# to speed up the process, only the required components are installed rather than the full qt515-meta-full metapackage
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
run: |
|
uses: jurplel/install-qt-action@v2
|
||||||
sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-focal
|
with:
|
||||||
sudo apt install \
|
version: ${{ matrix.qt_version }}
|
||||||
qt515base qt515svg qt515tools
|
|
||||||
|
|
||||||
- name: Install libtorrent
|
- name: Install libtorrent
|
||||||
run: |
|
run: |
|
||||||
git clone --branch ${{ matrix.libt_version }} --depth 1 https://github.com/arvidn/libtorrent.git
|
git clone \
|
||||||
|
--branch v${{ matrix.libt_version }} \
|
||||||
|
--depth 1 \
|
||||||
|
--recurse-submodules \
|
||||||
|
https://github.com/arvidn/libtorrent.git
|
||||||
cd libtorrent
|
cd libtorrent
|
||||||
git submodule update --init --recursive
|
|
||||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
|
||||||
cmake \
|
cmake \
|
||||||
-B build \
|
-B build \
|
||||||
-G "Ninja" \
|
-G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
-Ddeprecated-functions=OFF \
|
-Ddeprecated-functions=OFF
|
||||||
--graphviz=cmake-build-dir/target_graph.dot
|
|
||||||
cmake --build build
|
cmake --build build
|
||||||
sudo cmake --install build
|
sudo cmake --install build
|
||||||
|
|
||||||
- name: Build qBittorrent
|
- name: Build qBittorrent (Qt5)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 5) }}
|
||||||
run: |
|
run: |
|
||||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
lupdate -extensions c,cpp,h,hpp,ui ./
|
||||||
cmake \
|
cmake \
|
||||||
-B build \
|
-B build \
|
||||||
-G "Ninja" \
|
-G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
-D${{ matrix.qbt_gui }} \
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
-DVERBOSE_CONFIGURE=ON \
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
--graphviz=build/target_graph.dot
|
-D${{ matrix.qbt_gui }}
|
||||||
cmake --build build
|
cmake --build build
|
||||||
|
DESTDIR="qbittorrent" cmake --install build
|
||||||
|
|
||||||
- name: Install qBittorrent
|
- name: Build qBittorrent (Qt6)
|
||||||
run: sudo cmake --install build
|
if: ${{ startsWith(matrix.qt_version, 6) }}
|
||||||
|
run: |
|
||||||
|
lupdate -extensions c,cpp,h,hpp,ui ./
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
|
-DQT6=ON \
|
||||||
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
|
-D${{ matrix.qbt_gui }}
|
||||||
|
cmake --build build
|
||||||
|
DESTDIR="qbittorrent" cmake --install build
|
||||||
|
|
||||||
|
- name: Prepare build artifacts
|
||||||
|
run: |
|
||||||
|
mkdir upload
|
||||||
|
mkdir upload/cmake
|
||||||
|
cp build/compile_commands.json upload/cmake
|
||||||
|
mkdir upload/cmake/libtorrent
|
||||||
|
cp libtorrent/build/compile_commands.json upload/cmake/libtorrent
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: qBittorrent-CI_ubuntu-20.04-x64_${{ matrix.qbt_gui }}_libtorrent-${{ matrix.libt_version }}
|
name: build-info_ubuntu-20.04-x64_${{ matrix.qbt_gui }}_libtorrent-${{ matrix.libt_version }}_Qt-${{ matrix.qt_version }}
|
||||||
path: |
|
path: upload
|
||||||
build/compile_commands.json
|
|
||||||
build/install_manifest.txt
|
|
||||||
build/target_graph.dot
|
|
||||||
build/qbittorrent
|
|
||||||
build/qbittorrent-nox
|
|
||||||
libtorrent/cmake-build-dir/compile_commands.json
|
|
||||||
libtorrent/cmake-build-dir/target_graph.dot
|
|
||||||
|
|||||||
115
.github/workflows/ci_windows.yaml
vendored
@@ -4,12 +4,24 @@ on: [pull_request, push]
|
|||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: windows-2019
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
libt_version: ["2.0.5", "1.2.15"]
|
||||||
|
|
||||||
|
env:
|
||||||
|
boost_path: "${{ github.workspace }}/../boost"
|
||||||
|
libtorrent_path: "${{ github.workspace }}/libtorrent"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup devcmd
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
|
||||||
- name: Install build tools
|
- name: Install build tools
|
||||||
run: |
|
run: |
|
||||||
choco install ninja
|
choco install ninja
|
||||||
@@ -23,9 +35,9 @@ jobs:
|
|||||||
doNotUpdateVcpkg: true # the preinstalled vcpkg is updated regularly
|
doNotUpdateVcpkg: true # the preinstalled vcpkg is updated regularly
|
||||||
setupOnly: true
|
setupOnly: true
|
||||||
|
|
||||||
# tell vcpkg to only build Release variants of the dependencies
|
- name: Install dependencies from vcpkg
|
||||||
- name: Configure vcpkg triplet overlay
|
|
||||||
run: |
|
run: |
|
||||||
|
# tell vcpkg to only build Release variants of the dependencies
|
||||||
New-Item `
|
New-Item `
|
||||||
-Path "${{ github.workspace }}" `
|
-Path "${{ github.workspace }}" `
|
||||||
-Name "triplets_overlay" `
|
-Name "triplets_overlay" `
|
||||||
@@ -36,17 +48,10 @@ jobs:
|
|||||||
Add-Content `
|
Add-Content `
|
||||||
"${{ github.workspace }}/triplets_overlay/x64-windows-static-release.cmake" `
|
"${{ github.workspace }}/triplets_overlay/x64-windows-static-release.cmake" `
|
||||||
-Value "set(VCPKG_BUILD_TYPE release)"
|
-Value "set(VCPKG_BUILD_TYPE release)"
|
||||||
|
# clear buildtrees after each package installation to reduce disk space requirements
|
||||||
# clear buildtrees after each package installation to reduce disk space requirements
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
$packages = `
|
$packages = `
|
||||||
"boost-circular-buffer:x64-windows-static-release",
|
"openssl:x64-windows-static-release",
|
||||||
"libtorrent:x64-windows-static-release",
|
"zlib:x64-windows-static-release"
|
||||||
"qt5-base:x64-windows-static-release",
|
|
||||||
"qt5-svg:x64-windows-static-release",
|
|
||||||
"qt5-tools:x64-windows-static-release",
|
|
||||||
"qt5-winextras:x64-windows-static-release"
|
|
||||||
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg.exe upgrade `
|
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg.exe upgrade `
|
||||||
--overlay-triplets="${{ github.workspace }}/triplets_overlay" `
|
--overlay-triplets="${{ github.workspace }}/triplets_overlay" `
|
||||||
--no-dry-run
|
--no-dry-run
|
||||||
@@ -55,31 +60,95 @@ jobs:
|
|||||||
--clean-after-build `
|
--clean-after-build `
|
||||||
$packages
|
$packages
|
||||||
|
|
||||||
# this is necessary to correctly find and use cl.exe with the Ninja generator for now
|
- name: Install boost
|
||||||
- name: Setup devcmd
|
run: |
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
aria2c `
|
||||||
|
"https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.7z" `
|
||||||
|
-d "${{ runner.temp }}" `
|
||||||
|
-o "boost.7z"
|
||||||
|
7z x "${{ runner.temp }}/boost.7z" -o"${{ github.workspace }}/.."
|
||||||
|
move "${{ github.workspace }}/../boost_*" "${{ env.boost_path }}"
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v2
|
||||||
|
with:
|
||||||
|
version: "5.15.2"
|
||||||
|
|
||||||
|
- name: Install libtorrent
|
||||||
|
run: |
|
||||||
|
git clone `
|
||||||
|
--branch v${{ matrix.libt_version }} `
|
||||||
|
--depth 1 `
|
||||||
|
--recurse-submodules `
|
||||||
|
https://github.com/arvidn/libtorrent.git
|
||||||
|
cd libtorrent
|
||||||
|
cmake `
|
||||||
|
-B build `
|
||||||
|
-G "Ninja" `
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON `
|
||||||
|
-DCMAKE_INSTALL_PREFIX="${{ env.libtorrent_path }}" `
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE="${{ env.RUNVCPKG_VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" `
|
||||||
|
-DBOOST_ROOT="${{ env.boost_path }}" `
|
||||||
|
-DBUILD_SHARED_LIBS=OFF `
|
||||||
|
-Ddeprecated-functions=OFF `
|
||||||
|
-Dstatic_runtime=ON `
|
||||||
|
-DVCPKG_TARGET_TRIPLET=x64-windows-static-release
|
||||||
|
cmake --build build
|
||||||
|
cmake --install build
|
||||||
|
|
||||||
- name: Build qBittorrent
|
- name: Build qBittorrent
|
||||||
run: |
|
run: |
|
||||||
|
lupdate -extensions c,cpp,h,hpp,ui .
|
||||||
cmake `
|
cmake `
|
||||||
-B build `
|
-B build `
|
||||||
-G "Ninja" `
|
-G "Ninja" `
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON `
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON `
|
||||||
-DCMAKE_TOOLCHAIN_FILE="${{ env.RUNVCPKG_VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" `
|
-DCMAKE_TOOLCHAIN_FILE="${{ env.RUNVCPKG_VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" `
|
||||||
|
-DBOOST_ROOT="${{ env.boost_path }}" `
|
||||||
|
-DLibtorrentRasterbar_DIR="${{ env.libtorrent_path }}/lib/cmake/LibtorrentRasterbar" `
|
||||||
-DMSVC_RUNTIME_DYNAMIC=OFF `
|
-DMSVC_RUNTIME_DYNAMIC=OFF `
|
||||||
-DVCPKG_TARGET_TRIPLET=x64-windows-static-release `
|
-DVCPKG_TARGET_TRIPLET=x64-windows-static-release `
|
||||||
-DVERBOSE_CONFIGURE=ON `
|
-DVERBOSE_CONFIGURE=ON `
|
||||||
--graphviz=build/target_graph.dot
|
--graphviz=build/target_graph.dot
|
||||||
cmake --build build
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Prepare build artifacts
|
||||||
|
run: |
|
||||||
|
mkdir upload
|
||||||
|
copy build/qbittorrent.exe upload
|
||||||
|
copy build/qbittorrent.pdb upload
|
||||||
|
copy dist/windows/qt.conf upload
|
||||||
|
# runtimes
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Core.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Gui.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Network.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Sql.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Svg.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Widgets.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5WinExtras.dll" upload
|
||||||
|
copy "${{ env.Qt5_DIR }}/bin/Qt5Xml.dll" upload
|
||||||
|
mkdir upload/plugins/iconengines
|
||||||
|
copy "${{ env.Qt5_DIR }}/plugins/iconengines/qsvgicon.dll" upload/plugins/iconengines
|
||||||
|
mkdir upload/plugins/imageformats
|
||||||
|
copy "${{ env.Qt5_DIR }}/plugins/imageformats/qico.dll" upload/plugins/imageformats
|
||||||
|
copy "${{ env.Qt5_DIR }}/plugins/imageformats/qsvg.dll" upload/plugins/imageformats
|
||||||
|
mkdir upload/plugins/platforms
|
||||||
|
copy "${{ env.Qt5_DIR }}/plugins/platforms/qwindows.dll" upload/plugins/platforms
|
||||||
|
mkdir upload/plugins/sqldrivers
|
||||||
|
copy "${{ env.Qt5_DIR }}/plugins/sqldrivers/qsqlite.dll" upload/plugins/sqldrivers
|
||||||
|
mkdir upload/plugins/styles
|
||||||
|
copy "${{ env.Qt5_DIR }}/plugins/styles/qwindowsvistastyle.dll" upload/plugins/styles
|
||||||
|
# cmake additionals
|
||||||
|
mkdir upload/cmake
|
||||||
|
copy build/compile_commands.json upload/cmake
|
||||||
|
copy build/target_graph.dot upload/cmake
|
||||||
|
mkdir upload/cmake/libtorrent
|
||||||
|
copy libtorrent/build/compile_commands.json upload/cmake/libtorrent
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: qBittorrent-CI_Windows-x64
|
name: qBittorrent-CI_Windows-x64_libtorrent-${{ matrix.libt_version }}
|
||||||
path: |
|
path: upload
|
||||||
build/compile_commands.json
|
|
||||||
build/qbittorrent.exe
|
|
||||||
build/qbittorrent.pdb
|
|
||||||
build/target_graph.dot
|
|
||||||
dist/windows/qt.conf
|
|
||||||
|
|||||||
45
.github/workflows/coverity-scan.yml
vendored
@@ -5,9 +5,6 @@ on:
|
|||||||
- cron: '0 0 1 * *' # Monthly (1st day of month at midnight)
|
- cron: '0 0 1 * *' # Monthly (1st day of month at midnight)
|
||||||
workflow_dispatch: # Mainly for testing. Don't forget the Coverity usage limits.
|
workflow_dispatch: # Mainly for testing. Don't forget the Coverity usage limits.
|
||||||
|
|
||||||
env:
|
|
||||||
LIBTORRENT_VERSION_TAG: v1.2.14
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
coverity_scan:
|
coverity_scan:
|
||||||
name: Scan
|
name: Scan
|
||||||
@@ -20,54 +17,48 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
build-essential cmake git ninja-build pkg-config \
|
build-essential cmake ninja-build pkg-config \
|
||||||
libssl-dev zlib1g-dev libboost-dev libboost-system-dev
|
libboost-dev libssl-dev zlib1g-dev
|
||||||
# sudo apt install libqt5svg5-dev qtbase5-dev qttools5-dev # the Qt version in the standard repositories is too old...
|
|
||||||
|
|
||||||
# this will be installed under /opt/qt515. CMake will still find it automatically without additional hints
|
|
||||||
# to speed up the process, only the required components are installed rather than the full qt515-meta-full metapackage
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
run: |
|
uses: jurplel/install-qt-action@v2
|
||||||
sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-focal
|
with:
|
||||||
sudo apt install \
|
version: "5.15.2"
|
||||||
qt515base qt515svg qt515tools
|
|
||||||
|
|
||||||
- name: Install libtorrent
|
- name: Install libtorrent
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/arvidn/libtorrent
|
git clone \
|
||||||
|
--branch "v2.0.5" \
|
||||||
|
--depth 1 \
|
||||||
|
--recurse-submodules \
|
||||||
|
https://github.com/arvidn/libtorrent.git
|
||||||
cd libtorrent
|
cd libtorrent
|
||||||
git checkout ${{ env.LIBTORRENT_VERSION_TAG }}
|
|
||||||
cmake \
|
cmake \
|
||||||
-B build \
|
-B build \
|
||||||
-G "Ninja" \
|
-G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-Ddeprecated-functions=OFF
|
-Ddeprecated-functions=OFF
|
||||||
cmake --build build
|
cmake --build build
|
||||||
sudo cmake --install build --prefix /usr/local
|
sudo cmake --install build
|
||||||
|
|
||||||
- name: Download Coverity Build Tool
|
- name: Download Coverity Build Tool
|
||||||
run: |
|
run: |
|
||||||
wget \
|
wget \
|
||||||
-q \
|
-q \
|
||||||
https://scan.coverity.com/download/linux64 \
|
https://scan.coverity.com/download/linux64 \
|
||||||
--post-data "token=$TOKEN&project=qbittorrent%2FqBittorrent" \
|
--post-data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=qbittorrent%2FqBittorrent" \
|
||||||
-O coverity_tool.tgz
|
-O coverity_tool.tgz
|
||||||
mkdir coverity_tool
|
mkdir coverity_tool
|
||||||
tar xzf coverity_tool.tgz --strip 1 -C coverity_tool
|
tar xzf coverity_tool.tgz --strip 1 -C coverity_tool
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
|
|
||||||
- name: Configure qBittorrent
|
- name: Build qBittorrent
|
||||||
run: |
|
run: |
|
||||||
cmake \
|
cmake \
|
||||||
-B build \
|
-B build \
|
||||||
-G "Ninja" \
|
-G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DGUI=ON \
|
-DGUI=ON \
|
||||||
-DVERBOSE_CONFIGURE=ON
|
-DVERBOSE_CONFIGURE=ON
|
||||||
|
|
||||||
- name: Build qBittorrent
|
|
||||||
run: |
|
|
||||||
export PATH="$(pwd)/coverity_tool/bin:$PATH"
|
export PATH="$(pwd)/coverity_tool/bin:$PATH"
|
||||||
cov-build --dir cov-int cmake --build build
|
cov-build --dir cov-int cmake --build build
|
||||||
|
|
||||||
@@ -75,11 +66,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
tar caf qbittorrent.xz cov-int
|
tar caf qbittorrent.xz cov-int
|
||||||
curl \
|
curl \
|
||||||
--form token=$TOKEN \
|
--form token="${{ secrets.COVERITY_SCAN_TOKEN }}" \
|
||||||
--form email=sledgehammer999@qbittorrent.org \
|
--form email=sledgehammer999@qbittorrent.org \
|
||||||
--form file=@qbittorrent.tgz \
|
--form file=@qbittorrent.xz \
|
||||||
--form version="$(git rev-parse --short HEAD)" \
|
--form version="$(git rev-parse --short HEAD)" \
|
||||||
--form description="master" \
|
--form description="master" \
|
||||||
https://scan.coverity.com/builds?project=qbittorrent%2FqBittorrent
|
https://scan.coverity.com/builds?project=qbittorrent%2FqBittorrent
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
|
|||||||
85
.github/workflows/file_health.sh
vendored
@@ -1,85 +0,0 @@
|
|||||||
#!/usr/bin/env zsh
|
|
||||||
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
# Assumption: file names don't contain `:` (for the `cut` invocation).
|
|
||||||
# Safe to assume, as such a character in a filename would cause trouble on Windows, a platform we support
|
|
||||||
|
|
||||||
# any regression turn this non-zero
|
|
||||||
regressions=0
|
|
||||||
|
|
||||||
# exclusions (these are just grep extended regular expressions to match against paths relative to the root of the repository)
|
|
||||||
exclusions_nonutf8='(.*(7z|gif|ic(ns|o)|png|qm|zip))'
|
|
||||||
exclusions_bom='src/base/unicodestrings.h'
|
|
||||||
exclusions_tw='(*.ts)|src/webui/www/private/scripts/lib/*'
|
|
||||||
exclusions_trailing_newline='configure'
|
|
||||||
exclusions_no_lf='(*.ts)|(.*svg)|compile_commands.json|src/webui/www/private/scripts/lib/*'
|
|
||||||
|
|
||||||
echo -e "\n*** Detect files not encoded in UTF-8 ***\n"
|
|
||||||
|
|
||||||
find . -path ./build -prune -false -o -path ./.git -prune -false -o -type f -exec file --mime {} \; | sort \
|
|
||||||
| grep -v -e "charset=us-ascii" -e "charset=utf-8" | cut -d ":" -f 1 \
|
|
||||||
| grep -E -v -e "${exclusions_nonutf8}" \
|
|
||||||
| tee >(echo -e "--> Files not encoded in UTF-8: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
echo -e "\n*** Detect files encoded in UTF-8 with BOM ***\n"
|
|
||||||
|
|
||||||
grep --exclude-dir={.git,build} -rIl $'\xEF\xBB\xBF' | sort \
|
|
||||||
| grep -E -v -e "${exclusions_bom}" \
|
|
||||||
| tee >(echo -e "--> Files encoded in UTF-8 with BOM: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
echo -e "\n*** Detect usage of CR byte ***\n"
|
|
||||||
|
|
||||||
grep --exclude-dir={.git,build} -rIlU $'\x0D' | sort \
|
|
||||||
| tee >(echo -e "--> Usage of CR byte: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
echo -e "\n*** Detect trailing whitespace in lines ***\n"
|
|
||||||
|
|
||||||
grep --exclude-dir={.git,build} -rIl "[[:blank:]]$" | sort \
|
|
||||||
| grep -E -v -e "${exclusions_tw}" \
|
|
||||||
| tee >(echo -e "--> Trailing whitespace in lines: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0';
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
echo -e "\n*** Detect too many trailing newlines ***\n"
|
|
||||||
|
|
||||||
find . -path ./build -prune -false -o -path ./.git -prune -false -o -type f -exec file --mime {} \; | sort \
|
|
||||||
| grep -e "charset=us-ascii" -e "charset=utf-8" | cut -d ":" -f 1 \
|
|
||||||
| grep -E -v -e "${exclusions_trailing_newline}" \
|
|
||||||
| xargs -L1 -I my_input bash -c 'test "$(tail -q -c2 "my_input" | hexdump -C | grep "0a 0a")" && echo "my_input"' \
|
|
||||||
| tee >(echo -e "--> Too many trailing newlines: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
echo -e "\n*** Detect no trailing newline ***\n"
|
|
||||||
|
|
||||||
find . -path ./build -prune -false -o -path ./.git -prune -false -o -type f -exec file --mime {} \; | sort \
|
|
||||||
| grep -e "charset=us-ascii" -e "charset=utf-8" | cut -d ":" -f 1 \
|
|
||||||
| grep -E -v -e "${exclusions_no_lf}" \
|
|
||||||
| xargs -L1 -I my_input bash -c 'test "$(tail -q -c1 "my_input" | hexdump -C | grep "0a")" || echo "my_input"' \
|
|
||||||
| tee >(echo -e "--> No trailing newline: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
echo -e "\n*** Detect translation closing tag in new line ***\n"
|
|
||||||
|
|
||||||
grep --exclude-dir={.git,build} -nri "^</translation>" | sort \
|
|
||||||
| cut -d ":" -f 1,2 \
|
|
||||||
| tee >(echo -e "--> Translation closing tag in new line: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
|
|
||||||
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'
|
|
||||||
regressions=$((regressions+$?))
|
|
||||||
|
|
||||||
if [ "$regressions" -ne 0 ]; then
|
|
||||||
regressions=1
|
|
||||||
echo "\nFile health regressions found. Please fix them (or add them as exclusions)."
|
|
||||||
else
|
|
||||||
echo "All OK, no file health regressions found."
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $regressions;
|
|
||||||
55
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: check-translation-tag
|
||||||
|
name: Check newline characters in <translation> tag
|
||||||
|
entry: .github/workflows/check_translation_tag.py
|
||||||
|
language: script
|
||||||
|
types_or:
|
||||||
|
- ts
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks.git
|
||||||
|
rev: v4.0.1
|
||||||
|
hooks:
|
||||||
|
- id: check-json
|
||||||
|
name: Check JSON files
|
||||||
|
|
||||||
|
- id: check-yaml
|
||||||
|
name: Check YAML files
|
||||||
|
|
||||||
|
- id: fix-byte-order-marker
|
||||||
|
name: Check file encoding (UTF-8 without BOM)
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
src/base/unicodestrings.h
|
||||||
|
)$
|
||||||
|
|
||||||
|
- id: mixed-line-ending
|
||||||
|
name: Check line ending character (LF)
|
||||||
|
args: ["--fix=lf"]
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
compile_commands.json |
|
||||||
|
src/webui/www/private/scripts/lib/.*
|
||||||
|
)$
|
||||||
|
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
name: Check trailing newlines
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
compile_commands.json |
|
||||||
|
configure |
|
||||||
|
src/webui/www/private/scripts/lib/.*
|
||||||
|
)$
|
||||||
|
exclude_types:
|
||||||
|
- svg
|
||||||
|
- ts
|
||||||
|
|
||||||
|
- id: trailing-whitespace
|
||||||
|
name: Check trailing whitespaces
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
src/webui/www/private/scripts/lib/.*
|
||||||
|
)$
|
||||||
|
exclude_types:
|
||||||
|
- ts
|
||||||
@@ -12,7 +12,8 @@ project(qBittorrent
|
|||||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
||||||
# version requirements - older versions may work, but you are on your own
|
# version requirements - older versions may work, but you are on your own
|
||||||
set(minBoostVersion 1.65)
|
set(minBoostVersion 1.65)
|
||||||
set(minQtVersion 5.15.2)
|
set(minQt5Version 5.15.2)
|
||||||
|
set(minQt6Version 6.2)
|
||||||
set(minOpenSSLVersion 1.1.1)
|
set(minOpenSSLVersion 1.1.1)
|
||||||
set(minLibtorrent1Version 1.2.14)
|
set(minLibtorrent1Version 1.2.14)
|
||||||
set(minLibtorrentVersion 2.0.4)
|
set(minLibtorrentVersion 2.0.4)
|
||||||
@@ -22,6 +23,7 @@ set(minZlibVersion 1.2.11)
|
|||||||
include(CheckCXXSourceCompiles) # TODO: migrate to CheckSourceCompiles in CMake >= 3.19
|
include(CheckCXXSourceCompiles) # TODO: migrate to CheckSourceCompiles in CMake >= 3.19
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
include(FeatureOptionsSetup)
|
include(FeatureOptionsSetup)
|
||||||
|
feature_option(QT6 "Use Qt6" OFF)
|
||||||
feature_option(STACKTRACE "Enable stacktraces" ON)
|
feature_option(STACKTRACE "Enable stacktraces" ON)
|
||||||
feature_option(GUI "Build GUI application" ON)
|
feature_option(GUI "Build GUI application" ON)
|
||||||
feature_option(WEBUI "Enables built-in HTTP server for headless use" ON)
|
feature_option(WEBUI "Enables built-in HTTP server for headless use" ON)
|
||||||
|
|||||||
@@ -6,22 +6,14 @@ Read the respective section to find out more.
|
|||||||
### Table Of Contents
|
### Table Of Contents
|
||||||
|
|
||||||
* **[Bug reporting etiquette](#bug-reporting-etiquette)**
|
* **[Bug reporting etiquette](#bug-reporting-etiquette)**
|
||||||
|
|
||||||
|
|
||||||
* **[Submitting an issue/bug report](#submitting-an-issuebug-report)**
|
* **[Submitting an issue/bug report](#submitting-an-issuebug-report)**
|
||||||
* [What is an actual bug report?](#what-is-an-actual-bug-report)
|
* [What is an actual bug report?](#what-is-an-actual-bug-report)
|
||||||
* [Before submitting a bug report](#before-submitting-a-bug-report)
|
* [Before submitting a bug report](#before-submitting-a-bug-report)
|
||||||
* [Steps to ensure a good bug report](#steps-to-ensure-a-good-bug-report)
|
* [Steps to ensure a good bug report](#steps-to-ensure-a-good-bug-report)
|
||||||
|
|
||||||
|
|
||||||
* **[Suggesting enhancements/feature requests](#suggesting-enhancementsfeature-requests)**
|
* **[Suggesting enhancements/feature requests](#suggesting-enhancementsfeature-requests)**
|
||||||
* [Before submitting an enhancement/feature request](#before-submitting-an-enhancementfeature-request)
|
* [Before submitting an enhancement/feature request](#before-submitting-an-enhancementfeature-request)
|
||||||
* [Steps to ensure a good enhancement/feature suggestion](#steps-to-ensure-a-good-enhancementfeature-suggestion)
|
* [Steps to ensure a good enhancement/feature suggestion](#steps-to-ensure-a-good-enhancementfeature-suggestion)
|
||||||
|
|
||||||
|
|
||||||
* **[Opening a pull request](#opening-a-pull-request)**
|
* **[Opening a pull request](#opening-a-pull-request)**
|
||||||
* [Must read](#must-read)
|
|
||||||
* [Good to know](#good-to-know)
|
|
||||||
|
|
||||||
# Bug reporting etiquette
|
# Bug reporting etiquette
|
||||||
|
|
||||||
@@ -194,28 +186,26 @@ Following these guidelines helps maintainers and the community understand your s
|
|||||||
|
|
||||||
# Opening a pull request
|
# Opening a pull request
|
||||||
|
|
||||||
### Must read
|
* Consult [coding guidelines][coding-guidelines-url] first. If you are working on translation/i18n, read ["How to translate qBittorrent"][how-to-translate-url].
|
||||||
* Read our [**coding guidelines**][coding-guidelines-url]. There are some scripts to help you: [uncrustify script][uncrustify-script-url], [astyle script][astyle-script-url], [(related thread)][coding-guidelines-thread-url].
|
* Keep your git commit history clean.
|
||||||
* Keep the title **short** and provide a **clear** description about what your pull request does.
|
* Refer to the section about ["Git commit messages"][coding-guidelines-git-commit-message-url] in the coding guidelines.
|
||||||
* Provide **screenshots** for UI related changes.
|
* When merge conflicts arise, do `git rebase <target_branch_name>` and fix the conflicts, don't do `git pull`. Here is a good explanation: [merging-vs-rebasing][merging-vs-rebasing-url].
|
||||||
* Keep your git commit history **clean** and **precise.** Refer to the section about "Git commit messages" in the [**coding guidelines**][coding-guidelines-url].
|
* Keep pull request title concise and provide motivation and "what it does" in the pull request description area. Make it easy to read and understand.
|
||||||
* If your commit fixes a reported issue (for example #4134), add the following message to the commit `Closes #4134.`. Example [here][commit-message-fix-issue-example-url].
|
* Provide screenshots for UI related changes.
|
||||||
|
* If your commit addresses a reported issue (for example issue #8454), append the following text to the commit body `Closes #8454.`. Example [commit][commit-message-fix-issue-example-url].
|
||||||
|
* Search [pull request list][pull-request-list-url] first. Others might have already implemented your idea (or got rejected already).
|
||||||
|
|
||||||
### Good to know
|
|
||||||
* **Search** pull request history! Others might have already implemented your idea and it is waiting to be merged (or got rejected already). Save your precious time by doing a search first.
|
|
||||||
* When resolving merge conflicts, do `git rebase <target_branch_name>`, don't do `git pull`. Then you can start fixing the conflicts. Here is a good explanation: [link][merging-vs-rebasing-url].
|
|
||||||
|
|
||||||
[astyle-script-url]: https://gist.github.com/Chocobo1/539cee860d1eef0acfa6
|
|
||||||
[attachments-howto-url]: https://help.github.com/articles/file-attachments-on-issues-and-pull-requests
|
[attachments-howto-url]: https://help.github.com/articles/file-attachments-on-issues-and-pull-requests
|
||||||
|
[builds-url]: https://sourceforge.net/projects/qbittorrent/files/
|
||||||
[coding-guidelines-url]: https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md
|
[coding-guidelines-url]: https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md
|
||||||
[coding-guidelines-thread-url]: https://github.com/qbittorrent/qBittorrent/issues/2192
|
[coding-guidelines-git-commit-message-url]: https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md#10-git-commit-message
|
||||||
[commit-message-fix-issue-example-url]: https://github.com/qbittorrent/qBittorrent/commit/c07cd440cd46345297debb47cb260f8688975f50
|
[commit-message-fix-issue-example-url]: https://github.com/qbittorrent/qBittorrent/commit/c07cd440cd46345297debb47cb260f8688975f50
|
||||||
[forum-url]: http://forum.qbittorrent.org/
|
[forum-url]: http://forum.qbittorrent.org/
|
||||||
[howto-report-bugs-url]: https://www.chiark.greenend.org.uk/~sgtatham/bugs.html
|
[howto-report-bugs-url]: https://www.chiark.greenend.org.uk/~sgtatham/bugs.html
|
||||||
|
[how-to-translate-url]: https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent
|
||||||
[merging-vs-rebasing-url]: https://www.atlassian.com/git/tutorials/merging-vs-rebasing
|
[merging-vs-rebasing-url]: https://www.atlassian.com/git/tutorials/merging-vs-rebasing
|
||||||
|
[pull-request-list-url]: https://github.com/qbittorrent/qBittorrent/pulls
|
||||||
[python-url]: https://www.python.org/
|
[python-url]: https://www.python.org/
|
||||||
[releases-url]: https://github.com/qbittorrent/qBittorrent/releases
|
[releases-url]: https://github.com/qbittorrent/qBittorrent/releases
|
||||||
[search-plugins-url]: https://github.com/qbittorrent/search-plugins
|
[search-plugins-url]: https://github.com/qbittorrent/search-plugins
|
||||||
[uncrustify-script-url]: https://raw.githubusercontent.com/qbittorrent/qBittorrent/master/uncrustify.cfg
|
|
||||||
[wiki-url]: https://github.com/qbittorrent/qBittorrent/wiki
|
[wiki-url]: https://github.com/qbittorrent/qBittorrent/wiki
|
||||||
[builds-url]: https://sourceforge.net/projects/qbittorrent/files/
|
|
||||||
|
|||||||
375
Changelog
@@ -1,6 +1,256 @@
|
|||||||
Unreleased - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.4.0
|
Tue Mar 22 2022 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.4.2
|
||||||
- FEATURE: Add support for creating v2 torrents(requires libtorrent 2.0.x) (Chocobo1)
|
- FEATURE: Allow to limit max memory working set size (glassez)
|
||||||
|
- BUGFIX: Fix UI crash when torrent is in a non-existent category (Kevin Cox)
|
||||||
|
- BUGFIX: Correctly handle changing of global save paths (glassez)
|
||||||
|
- BUGFIX: Disable performance alert (Chocobo1)
|
||||||
|
- BUGFIX: Prevent loading resume data with inconsistent ID (glassez)
|
||||||
|
- BUGFIX: Properly handle metadata download for an existing torrent (glassez)
|
||||||
|
- BUGFIX: Prevent crash when open torrent destination folder (glassez)
|
||||||
|
- WINDOWS: NSIS: Update Spanish, Spanish International and French translations(Juanjo Jiménez, RqndomHax)
|
||||||
|
|
||||||
|
Tue Feb 15 2022 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.4.1
|
||||||
|
- FEATURE: Restore all torrent settings to the torrent's main context menu (thalieht)
|
||||||
|
- FEATURE: Add confirmation for enabling Auto TMM from context menu (thalieht)
|
||||||
|
- FEATURE: Add tooltip to Automatic Torrent Management context menu action (thalieht)
|
||||||
|
- FEATURE: Add Select All/None buttons in new torrent dialog (thalieht)
|
||||||
|
- BUGFIX: Keep "torrent info" alive while generate .torrent file (glassez)
|
||||||
|
- BUGFIX: Correctly handle Auto TMM in Torrent Files Watcher (glassez)
|
||||||
|
- BUGFIX: Correctly track the root folder name change (glassez)
|
||||||
|
- BUGFIX: Various fixes to the moving torrent code (glassez)
|
||||||
|
- BUGFIX: Update the torrent's download path field when changing category (thalieht)
|
||||||
|
- BUGFIX: Correctly handle received metadata (glassez)
|
||||||
|
- BUGFIX: Store hybrid torrents using legacy filenames (glassez)
|
||||||
|
- BUGFIX: Open correct directory when clicked on Browse button (glassez)
|
||||||
|
- BUGFIX: Fix crash when shutting down and clicing on system tray icon (Chocobo1)
|
||||||
|
- BUGFIX: Fix "Free space on disk" in new torrent dialog (thalieht)
|
||||||
|
- BUGFIX: Optimize completed files handling (Prince Gupta)
|
||||||
|
- BUGFIX: Migrate proxy settings (sledgehammer999)
|
||||||
|
- BUGFIX: Try to recover missing categories (glassez)
|
||||||
|
- WEBUI: WebAPI: fix wrong key used for categories (Chocobo1)
|
||||||
|
- WEBUI: Remove hack for outdated IE 6 browser (Chocobo1)
|
||||||
|
- RSS: Correctly handle XML parsing errors (glassez)
|
||||||
|
|
||||||
|
Thu Jan 06 2022 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.4.0
|
||||||
|
- FEATURE: Support for v2 torrents along with libtorrent 2.0.x support (glassez, Chocobo1)
|
||||||
|
- FEATURE: Support for Qt6 (glassez)
|
||||||
- FEATURE: Expose libtorrent hashing_threads settings (Anton Bershanskiy)
|
- FEATURE: Expose libtorrent hashing_threads settings (Anton Bershanskiy)
|
||||||
|
- FEATURE: Add "Notification timeout" option (kevtechxx)
|
||||||
|
- FEATURE: Add `connection_speed` to advanced settings (Chocobo1)
|
||||||
|
- FEATURE: Announce to all trackers if IP changed (#15001) (zhuangzi926)
|
||||||
|
- FEATURE: Add tooltip for various columns (Chocobo1)
|
||||||
|
- FEATURE: Add context menu to toggle content tab columns (#15164) (AbeniMatteo)
|
||||||
|
- FEATURE: Add filter "Checking" to side panel (#15166) (AbeniMatteo)
|
||||||
|
- FEATURE: Add "Forced metadata downloading" state (#15185) (AbeniMatteo)
|
||||||
|
- FEATURE: Remember last viewed page in Options dialog (#15230) (Chocobo1)
|
||||||
|
- FEATURE: Add tooltip to listening port spinbox (Chocobo1)
|
||||||
|
- FEATURE: Add "Skip hash check" option for watched folders (glassez)
|
||||||
|
- FEATURE: Add "Show torrent options" double-click action (glassez)
|
||||||
|
- FEATURE: Allow setting temp folder per torrent/catergory (glassez)
|
||||||
|
- FEATURE: Support folder based UI Themes (Prince Gupta)
|
||||||
|
- BUGFIX: Save "resume data" once file priority is changed (glassez)
|
||||||
|
- BUGFIX: Show priority menu at top level if there is no other in Add New Torrent dialog (FozzeY)
|
||||||
|
- BUGFIX: Capitalize "peer flags" descriptions (Chocobo1)
|
||||||
|
- BUGFIX: Reorder peer flags (Chocobo1)
|
||||||
|
- BUGFIX: Show "last activity" value under all circumstances (Chocobo1)
|
||||||
|
- BUGFIX: Elide text from the right for all columns' header (smigii)
|
||||||
|
- BUGFIX: Fix startup with different profiles (jagannatharjun)
|
||||||
|
- BUGFIX: Move a few torrent context menu actions into "Torrent options" dialog (thalieht)
|
||||||
|
- BUGFIX: Allow deselecting radio buttons in "Torrent options" for mixed torrents (thalieht)
|
||||||
|
- BUGFIX: Apply file priority changes correctly (a-sum-duma, Chocobo1)
|
||||||
|
- BUGFIX: Use proper string for Korean language (OctopusET)
|
||||||
|
- BUGFIX: Disable "add peers" menu items instead of hiding it (Chocobo1)
|
||||||
|
- BUGFIX: Disable system tray icon menu when app is exiting (Chocobo1)
|
||||||
|
- BUGFIX: Show GUI lock icon after system tray icon is initialized (Chocobo1)
|
||||||
|
- BUGFIX: Apply selected layout to displayed torrent content in "Add New Torrent" dialog (glassez)
|
||||||
|
- WEBUI: Add reverse proxy source IP resolution (#15047) (HiFiPhile)
|
||||||
|
- WEBUI: Support navigating UI tables with arrow keys (Thomas Piccirello)
|
||||||
|
- WEBUI: Support expanding/collapsing UI folders with arrow keys (Thomas Piccirello)
|
||||||
|
- WEBUI: Support sorting UI tables via touch (#15205) (Tom Piccirello)
|
||||||
|
- WEBUI: Add pieces progress bar to General tab (Jesse Smick)
|
||||||
|
- WEBUI: Update authors page (Chocobo1)
|
||||||
|
- WEBUI: Set icon sizes attribute (Daniel Aleksandersen)
|
||||||
|
- WEBUI: Add meta application name (Daniel Aleksandersen)
|
||||||
|
- WEBUI: Sort WebUI language selection values (Chocobo1)
|
||||||
|
- WEBUI: Use correct URL scheme in user prompt when HTTPS is enabled (Chocobo1)
|
||||||
|
- RSS: Stick Unread row to top in RSS feed list (Prince Gupta)
|
||||||
|
- RSS: Correctly use fallback icons for RSS feed in GUI (jagannatharjun)
|
||||||
|
- SEARCH: Add context menu for tabs in search widget (#14926) (Anton)
|
||||||
|
- SEARCH: Add more download options to torrent search result right-click menu (a-sum-duma)
|
||||||
|
- WINDOWS: Add windows-clang support (#15115) (Biswapriyo Nath)
|
||||||
|
- WINDOWS: Update python installer URL for Windows (xavier2k6)
|
||||||
|
- WINDOWS: NSIS: Update Simplified Chinese translation (Losiki)
|
||||||
|
- LINUX: Prolong wait time for shutdown for qbittorrent-nox (Chocobo1)
|
||||||
|
- LINUX: Install vector program icon (Chocobo1)
|
||||||
|
- LINUX: Add detection for OpenBSD, Haiku in configure script (Chocobo1)
|
||||||
|
- MACOS: Update Mac icons for Big Sur (17jiangz1)
|
||||||
|
- EXPERIMENTAL: Setting to store/load fastresume/torrent files in an SQLite database (glassez)
|
||||||
|
- OTHER: Many internal code refactorings and bug fixing by many people
|
||||||
|
|
||||||
|
Sun Oct 31 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.9
|
||||||
|
- BUGFIX: Fix "no action" option on torrent double click (Jose M. Abuin)
|
||||||
|
- BUGFIX: Fix broken behavior of "priority by shown file order" (Chocobo1)
|
||||||
|
- WEBUI: Fix WebUI crash when tracker URL is invalid (Chocobo1)
|
||||||
|
- WEBUI: Revert "WebUI: group trackers by hostname" (Chocobo1)
|
||||||
|
- WINDOWS: Remove Windows Vista support from manifest (xavier2k6)
|
||||||
|
- WINDOWS: NSIS: Update Korean, Indonesian and Traditional Chinese translation (JungHee Lee, Faisal Al-Munawar Fathur Rahman, SiderealArt)
|
||||||
|
|
||||||
|
Sun Aug 29 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.8
|
||||||
|
- BUGFIX: Delay processing of watched folders (#15282) (glassez)
|
||||||
|
- BUGFIX: Use the same icon for selecting folders/files (Chocobo1)
|
||||||
|
- BUGFIX: Use default upper limits for ddns entries (Chocobo1)
|
||||||
|
- WEBUI: Expose SSRF mitigation (#15247) (Sylvain Finot)
|
||||||
|
- WEBUI: Update webui libraries (Chocobo1)
|
||||||
|
- WEBUI: Group trackers by hostname (#15264) (Mengyang Li)
|
||||||
|
- WEBUI: Improve "last activity" calculation in WebAPI (#15339) (Chocobo1)
|
||||||
|
- WINDOWS: NSIS: Add Polish translation (#15262) (Matthaiks)
|
||||||
|
|
||||||
|
Tue Aug 03 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.7
|
||||||
|
- BUGFIX: Don't forget to start Watched folders timer (glassez)
|
||||||
|
- BUGFIX: Don't close tags menu when toggling items (tgregerson)
|
||||||
|
- BUGFIX: Don't overwrite tracker message (glassez)
|
||||||
|
- BUGFIX: Bump file pool size (#14966) (An0n)
|
||||||
|
- BUGFIX: Properly create "clean path" for watched folder (glassez)
|
||||||
|
- WEBUI: Disconnect comment links (Daniel Aleksandersen)
|
||||||
|
- WINDOWS: NSIS: Update Danish translation (scootergrisen)
|
||||||
|
|
||||||
|
Sat Jun 26 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.6
|
||||||
|
- FEATURE: New languages: Mongolian, Persian, Thai
|
||||||
|
- BUGFIX: Provide correct error description in "upload mode" (glassez)
|
||||||
|
- BUGFIX: Allow adding torrents with relative save path (glassez)
|
||||||
|
- BUGFIX: Fix main window turns blank after restoring from tray (#15031) (Chocobo1)
|
||||||
|
- BUGFIX: Remove the lockfile on exit (#14997) (brvphoenix)
|
||||||
|
- BUGFIX: Improve "Watched folders" feature (glassez)
|
||||||
|
- BUGFIX: Keep sub-sorting order (#15074) (Dmitry Khlestkov)
|
||||||
|
- BUGFIX: Properly add torrent with new tags (glassez)
|
||||||
|
- WINDOWS: NSIS: Update Japanese, Turkish, Hungarian, Swedish translation (maboroshin, Burak Yavuz, xkrstudio, nonew-star)
|
||||||
|
|
||||||
|
Sun May 02 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.5
|
||||||
|
- BUGFIX: Move cursor to the end when autofilling URL/hash in "Download from URLs" dialog (Chocobo1)
|
||||||
|
- BUGFIX: Sort invalid QDateTime values after valid values (Chocobo1)
|
||||||
|
- BUGFIX: Fix tabChangesFocus attribute in "Edit trackers" dialog (Christoph Rackwitz)
|
||||||
|
- BUGFIX: Update DynDNS register url (zhuangzi926)
|
||||||
|
- BUGFIX: Handle "not enough disk space" error more graciously (glassez)
|
||||||
|
- BUGFIX: Correctly draw progress background with stylesheet (jagannatharjun)
|
||||||
|
- WEBUI: Fix magnet url from the search facility (Chocobo1)
|
||||||
|
- WEBUI: Revise folder monitoring functions (Chocobo1)
|
||||||
|
- WEBUI: Fix magnet url from the browser (brvphoenix)
|
||||||
|
- WEBUI: Allow to specify file indexes in torrents/files API (glassez)
|
||||||
|
- WINDOWS: NSIS: Allow more strings to translated (bovirus, Chocobo1)
|
||||||
|
- WINDOWS: NSIS: Update Italian, German, Estonian, Russian, PortugueseBR translations (bovirus, Henry Water, PriitUring, Долматов Алексей, Felipe)
|
||||||
|
- LINUX: Fix D-Bus Notification `desktop-entry` field (Chocobo1)
|
||||||
|
- MACOS: Don't use executable name as CFBundleName value (Nick Korotysh)
|
||||||
|
- OTHER: Lower Qt requirement to 5.11 (sledgehammer999)
|
||||||
|
- OTHER: Clarify that the license is GPLv2+ (sledgehammer999)
|
||||||
|
|
||||||
|
Wed Mar 24 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.4.1
|
||||||
|
- BUGFIX: Correctly draw progress bar (glassez)
|
||||||
|
- WEBUI: Fix javascript code which broke the UI (Chocobo1)
|
||||||
|
|
||||||
|
Tue Mar 23 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.4
|
||||||
|
- FEATURE: Add ability to prioritize selected items by shown file order (Chocobo1)
|
||||||
|
- FEATURE: Allow tab to escape the text box in "Edit trackers" dialog (Christoph Rackwitz)
|
||||||
|
- FEATURE: Support sub-sorting in Transferlist (jagannatharjun)
|
||||||
|
- FEATURE: Expose ToS setting from libtorrent (Chocobo1)
|
||||||
|
- FEATURE: Improve tracker entries handling (glassez)
|
||||||
|
- BUGFIX: Drop extension from generated content folder name (glassez)
|
||||||
|
- BUGFIX: Change qBittorrent Updater window title (xavier2k6)
|
||||||
|
- BUGFIX: Validate HTTPS Tracker Certificate by default (an0n666)
|
||||||
|
- BUGFIX: Don't let "program update" dialog steal focus (Chocobo1)
|
||||||
|
- BUGFIX: Disable expand on double click in TorrentContentTreeView (jagannatharjun)
|
||||||
|
- BUGFIX: Add hyperlink to Transifex on translator list (Si Yong Kim)
|
||||||
|
- BUGFIX: Enlarge "speed limit" icon slightly (Chocobo1)
|
||||||
|
- BUGFIX: Don't prevent system sleep due to errored torrents (dyumin)
|
||||||
|
- BUGFIX: Use stable sorting in transfer list (Chocobo1)
|
||||||
|
- BUGFIX: Allow "missing files" torrents to save more resume data (glassez)
|
||||||
|
- BUGFIX: Restart "missing files" torrents after changing location (glassez)
|
||||||
|
- BUGFIX: Show proper string when torrent availability is not available (Chocobo1)
|
||||||
|
- BUGFIX: Apply "Hide zero/infinity values" to "Time Active", "Down/Up Limit" and ETA columns (Chocobo1)
|
||||||
|
- BUGFIX: Fix potential out-of-bounds access (Chocobo1)
|
||||||
|
- BUGFIX: Make SpeedPlotView averager time aware (jagannatharjun)
|
||||||
|
- BUGFIX: Add a 3-Hour graph (jagannatharjun)
|
||||||
|
- BUGFIX: Add an option to disable icons in menus (always disabled on MacOS) (Michał Kopeć)
|
||||||
|
- BUGFIX: Improve detection of filename extension of audio/video files (Chocobo1)
|
||||||
|
- BUGFIX: Various drawing improvements of progress bar (Chocobo1)
|
||||||
|
- BUGFIX: Properly stop torrent creation if aborted (Chocobo1)
|
||||||
|
- BUGFIX: Replace external program parameters in one step (Chocobo1)
|
||||||
|
- BUGFIX: Improve "save resume data" handling (glassez)
|
||||||
|
- BUGFIX: Fix bad IPv6 address format for outgoingInterfaces (treysis)
|
||||||
|
- WEBUI: Properly decode strings (brvphoenix)
|
||||||
|
- WEBUI: Accept "share limits" when adding torrent using WebAPI (glassez)
|
||||||
|
- WEBUI: Add seeding time to the active time column (thalieht)
|
||||||
|
- WEBUI: Fix incorrect seeding time string in General tab (thalieht)
|
||||||
|
- WEBUI: Allow >100 days in WebUI function "friendlyDuration" (thalieht)
|
||||||
|
- WEBUI: Avoid decoding strings repeatedly (brvphoenix)
|
||||||
|
- RSS: Add category button on AutomatedRSSDownloader on GUI (Si Yong Kim)
|
||||||
|
- WINDOWS: NSIS: Update Czech translation (slrslr)
|
||||||
|
- WINDOWS: NSIS: Update Portuguese BR translation (Alex)
|
||||||
|
- WINDOWS: NSIS: Add Estonian translation (PriitUring)
|
||||||
|
- WINDOWS: Allow change-case-only file renaming (glassez)
|
||||||
|
- LINUX: Systemd: wait for mounting of local filesystems (Juraj Oršulić)
|
||||||
|
- OTHER: Raise minimum libtorrent version to 1.2.12 (glassez)
|
||||||
|
- OTHER: Raise minimum Qt version to 5.12 (glassez)
|
||||||
|
|
||||||
|
Tue Jan 19 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.3
|
||||||
|
- FEATURE: New languages: Azerbaijani, Estonian
|
||||||
|
- BUGFIX: Unify global speed dialogs for normal/alternative speeds (thalieht)
|
||||||
|
- BUGFIX: Increase maximum global speed limits ~2 GiB/s (thalieht)
|
||||||
|
- BUGFIX: Save fastresume when setting torrent speed limits (thalieht)
|
||||||
|
- BUGFIX: Group several torrent options into one dialog (thalieht)
|
||||||
|
- BUGFIX: Capitalize locale names (Chocobo1)
|
||||||
|
- BUGFIX: Improve content file/folder names handling (glassez)
|
||||||
|
- BUGFIX: Drop notification about move storage finished or failed (glassez)
|
||||||
|
- BUGFIX: Reload "missing files" torrent instead of re-checking (glassez)
|
||||||
|
- BUGFIX: Remember dialog sizes (Chocobo1)
|
||||||
|
- BUGFIX: Improve detection of file extension string (Chocobo1)
|
||||||
|
- WEBUI: Don't call non-existent elements (glassez)
|
||||||
|
- WEBUI: Update "Keep top-level folder" in WebUI options (thalieht)
|
||||||
|
- MACOS: QMake: Raise minimal macOS target version to 10.14 (glassez)
|
||||||
|
- LINUX: Use legacy 'data' directory only as a fallback (lbilli)
|
||||||
|
- OTHER: Bump project requirement to C++17 (Chocobo1)
|
||||||
|
|
||||||
|
Sun Dec 27 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.2
|
||||||
|
- FEATURE: Allow to add root folder to torrent content (glassez)
|
||||||
|
- FEATURE: "HTTPS tracker validation" option is available on all platforms with latest libtorrent (Chocobo1)
|
||||||
|
- FEATURE: Option for supporting internationalized domain names (IDNs) (Chocobo1)
|
||||||
|
- BUGFIX: Fix broken sorting on some columns (Chocobo1)
|
||||||
|
- BUGFIX: Fix availability per file value (Chocobo1)
|
||||||
|
- BUGFIX: Fix status of torrents without metadata (sledgehammer999)
|
||||||
|
- BUGFIX: Don't try to remove folders for a torrent without metadata (sledgehammer999)
|
||||||
|
- BUGFIX: Lift upper limit of "Max concurrent HTTP announces" option (Chocobo1)
|
||||||
|
- BUGFIX: Add links to libtorrent documentation (Chocobo1)
|
||||||
|
- BUGFIX: Move "embedded tracker" options to qbt section (Chocobo1)
|
||||||
|
- BUGFIX: Properly handle "Append extension" option changing (glassez)
|
||||||
|
- BUGFIX: Correctly save paused torrent state (glassez)
|
||||||
|
- BUGFIX: Fix bug of "move storage job" can be performed multiple times (glassez)
|
||||||
|
- WEBUI: Add ability to use 'shift+delete' to delete torrents (Chocobo1)
|
||||||
|
- WEBUI: Allow to attach tags while adding torrents (Jesse Chan)
|
||||||
|
- WEBUI: Bump version to 2.6.2 (Jesse Chan)
|
||||||
|
- WEBUI: Remove unnecessary restriction on input length (Chocobo1)
|
||||||
|
- WINDOWS: NSIS: Update Russian translation (Andrei Stepanov)
|
||||||
|
- WINDOWS: NSIS: Update Italian translation (Alessandro Simonelli)
|
||||||
|
- OTHER: Drop support for building with libtorrent < 1.2.11 (Vladimir Golovnev)
|
||||||
|
|
||||||
|
Wed Nov 25 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.1
|
||||||
|
- FEATURE: Allow progress bar styling from custom themes (jagannatharjun)
|
||||||
|
- FEATURE: Allow adding torrents using "Paste" key sequence (Chocobo1)
|
||||||
|
- FEATURE: Add Latgalian translation (sledgehammer999)
|
||||||
|
- BUGFIX: Prevent resume data to be saved for removed torrent (glassez)
|
||||||
|
- BUGFIX: Clarify connection protocol choice label (FranciscoPombal)
|
||||||
|
- BUGFIX: Fix crash when clicked outside the table of torrent content view (jagannatharjun)
|
||||||
|
- BUGFIX: Don't resume "paused" torrents when put into "checking" state by libtorrent (glassez)
|
||||||
|
- BUGFIX: Fix torrent state calculation (glassez)
|
||||||
|
- BUGFIX: Align integer data to right in torrent content view (jagannatharjun)
|
||||||
|
- WEBUI: Place WebUI RSS description in sandboxed iframe (Sepro)
|
||||||
|
- WEBUI: Avoid settings being reset via WebAPI (Chocobo1)
|
||||||
|
- WEBUI: Fix toggling advanced option in WebUI (thalieht)
|
||||||
|
- WEBUI: Expose contentPath in WebAPI torrents/info (FranciscoPombal)
|
||||||
|
- WEBUI: Fix the issue that IPv6 address can't be banned (brvphoenix)
|
||||||
|
- RSS: Fix confusion in date format description (Thomas De Rocker)
|
||||||
|
- WINDOWS: Update dutch.nsi (Thomas De Rocker)
|
||||||
|
- LINUX: Update .desktop file translations (sledgehammer999)
|
||||||
|
|
||||||
|
Thu Oct 22 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.0.1
|
||||||
|
- WINDOWS: NSIS: Update Italian translation (bovirus)
|
||||||
|
|
||||||
Sun Oct 18 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.0
|
Sun Oct 18 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.0
|
||||||
- FEATURE: Many UI elements colors are themeable now (jagannatharjun)
|
- FEATURE: Many UI elements colors are themeable now (jagannatharjun)
|
||||||
@@ -55,6 +305,127 @@ Sun Oct 18 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.0
|
|||||||
- OTHER: Support for libtorrent 1.1.x is dropped (Chocobo1)
|
- OTHER: Support for libtorrent 1.1.x is dropped (Chocobo1)
|
||||||
- OTHER: Many code cleanups and improvements (FranciscoPombal, Chocobo1, glassez)
|
- OTHER: Many code cleanups and improvements (FranciscoPombal, Chocobo1, glassez)
|
||||||
|
|
||||||
|
Sat Apr 25 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.5
|
||||||
|
- BUGFIX: Fix crash when torrent is deleted on limit reached (glassez)
|
||||||
|
- BUGFIX: Register datatype properly (Chocobo1)
|
||||||
|
- WEBUI: Add ability to send custom HTTP headers (Chocobo1)
|
||||||
|
- WEBUI: Expand RSS related API (Sepro)
|
||||||
|
- WINDOWS: Installer: Update german translation (schnurlos)
|
||||||
|
|
||||||
|
Wed Apr 22 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.4
|
||||||
|
- BUGFIX: Fix sub-sorting of Transfer list (glassez)
|
||||||
|
- BUGFIX: Fix wrong logic that disables "prevent sleeping" timer (Chocobo1)
|
||||||
|
- BUGFIX: Set disk cache size for older libtorrent versions (NotTsunami)
|
||||||
|
- BUGFIX: Sort locale language list (Chocobo1)
|
||||||
|
- BUGFIX: Remove white outline around mascot.png (adem)
|
||||||
|
- BUGFIX: Various fixes in configuring the chosen network interface and not leaking the IP (Raif Atef, an0n666)
|
||||||
|
- BUGFIX: Save "resume data" when torrent storage is moved (glassez)
|
||||||
|
- BUGFIX: Avoid holding encoded resume data in memory (Chocobo1)
|
||||||
|
- BUGFIX: Fix date format for "Last seen complete" (Chocobo1)
|
||||||
|
- BUGFIX: Remove deprecated strict super seeding mode from advanced settings (an0n666)
|
||||||
|
- BUGFIX: Change default stop_tracker_timeout settings (an0n666)
|
||||||
|
- BUGFIX: Convert the Log widget to use custom View/Model (jagannatharjun)
|
||||||
|
- BUGFIX: Change default upload slot choking limits (an0n666)
|
||||||
|
- BUGFIX: Don't uncheck Authentication checkbox when changing proxy type (thalieht)
|
||||||
|
- BUGFIX: Reduce ambiguity for selecting tray icons (Chocobo1)
|
||||||
|
- WEBUI: Fix unable to add multiple peers in WebUI (Sepro)
|
||||||
|
- WEBUI: Fix UPnP lease duration get/set (NotTsunami)
|
||||||
|
- SEARCH: Detect python3 executable on Windows (József Sallai)
|
||||||
|
|
||||||
|
Wed Apr 01 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.3
|
||||||
|
- FEATURE: Add logging for SOCKS5 proxy errors (Chocobo1)
|
||||||
|
- FEATURE: Add UPnP lease duration advanced option (NotTsunami)
|
||||||
|
- BUGFIX: Allow to translate error messages (Chocobo1)
|
||||||
|
- BUGFIX: Don't round scaling factor (Nick Korotysh)
|
||||||
|
- BUGFIX: Save log file in UTF-8 encoding (Chocobo1)
|
||||||
|
- BUGFIX: Avoid log file excessive flushing (Chocobo1)
|
||||||
|
- BUGFIX: Fix regression when fastresume contains network path (Tester798)
|
||||||
|
- BUGFIX: Fix broken UNC paths in fastresumes on Windows (sledgehammer999)
|
||||||
|
- BUGFIX: Prevent multiple instances for the same app config (glassez)
|
||||||
|
- BUGFIX: Fix unexpected torrent resume after app restart with libtorrent 1.1.x (glassez)
|
||||||
|
- WEBUI: Add alt and title tags for WebUI footer (LameLemon)
|
||||||
|
- WINDOWS: Installer: Update Finnish translation (Roope Jukkara)
|
||||||
|
- WINDOWS: Installer: Update Japanese translation (maboroshin)
|
||||||
|
- WINDOWS: Installer: Update Turkish translation (Burak Yavuz)
|
||||||
|
- WINDOWS: Installer: Update Russian translation (Andrei Stepanov)
|
||||||
|
|
||||||
|
Tue Mar 24 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.2
|
||||||
|
- FEATURE: Allow transfer list text color changes through QSS (Prince Gupta)
|
||||||
|
- FEATURE: Option to show console when external program is run (sledgehammer999)
|
||||||
|
- FEATURE: Rename Country column to "Country / Region" (Thomas Piccirello)
|
||||||
|
- FEATURE: Change the defaults of some settings (FranciscoPombal)
|
||||||
|
- FEATURE: Refactored Transfer List code to allow theming. As a sideffect the row height has more padding. (glassez)
|
||||||
|
- FEATURE: Allow double-click in preview dialog (thalieht)
|
||||||
|
- FEATURE: Expose stop_tracker_timeout in advanced settings (an0n666)
|
||||||
|
- FEATURE: Add piece_extent_affinity to AdvancedSettings (FranciscoPombal)
|
||||||
|
- FEATURE: Reorganize UI theme selection (Prince Gupta)
|
||||||
|
- FEATURE: Show any multiple connections from the same IP in peer list (thalieht)
|
||||||
|
- FEATURE: Add stalled filters to GUI and Web API/UI (FranciscoPombal)
|
||||||
|
- FEATURE: Use IP geolocation database by DB-IP instead of MaxMind (sledgehammer999)
|
||||||
|
- FEATURE: Allow to save downloaded metadata as torrent file (glassez)
|
||||||
|
- FEATURE: Allow single app instance per configuration (glassez)
|
||||||
|
- PERFORMANCE: Move multiple torrents one by one (glassez)
|
||||||
|
- BUGFIX: Disable Torrent Queue by default for new users (an0n666)
|
||||||
|
- BUGFIX: Update free disk space label on Category change in Auto Mode (Medvedishce)
|
||||||
|
- BUGFIX: Save resume data after recheck (glassez)
|
||||||
|
- BUGFIX: Tracker is errored only if all local endpoints fail (sledgehammer999)
|
||||||
|
- BUGFIX: Change placement of stop tracker timeout setting (An0n)
|
||||||
|
- BUGFIX: Redesign torrent startup handling (glassez)
|
||||||
|
- BUGFIX: Show "∞" instead of " -1" in Preferences (Sakib-Abrar)
|
||||||
|
- BUGFIX: Improve code efficiency for reverse resolution of peers (Chocobo1)
|
||||||
|
- BUGFIX: Handle HTTP redirection to magnet URI (glassez)
|
||||||
|
- BUGFIX: Various fixes for portable mode (Tester798)
|
||||||
|
- BUGFIX: Include resume folder path in exception message (Chocobo1)
|
||||||
|
- BUGFIX: Change placeholder text in torrent list's filter (djt3)
|
||||||
|
- BUGFIX: Improvements in the embedded tracker to be more spec compliant (FranciscoPombal)
|
||||||
|
- BUGFIX: Improve the options tooltips (NotTsunami)
|
||||||
|
- BUGFIX: Check if file exists in seed mode (an0n666)
|
||||||
|
- BUGFIX: Delegate GUI scaling work to Qt (Nick Korotysh)
|
||||||
|
- BUGFIX: Fix crash when renaming torrent contents (Chocobo1)
|
||||||
|
- BUGFIX: Fix total connected peers count calculation (FranciscoPombal)
|
||||||
|
- BUGFIX: Allow other keypresses in LogListWidget (NotTsunami)
|
||||||
|
- BUGFIX: Disable Auto TMM when not using default savepath from monitored folder (thalieht)
|
||||||
|
- WEBUI: Fix first row renaming in files tab (Denis)
|
||||||
|
- WEBUI: Use SVG image for WebUI favicon (Nick Korotysh)
|
||||||
|
- WEBUI: Inherit text color for filter list elements (Nick Korotysh)
|
||||||
|
- WEBUI: Expose WebUI ban counter to users (Chocobo1)
|
||||||
|
- WEBUI: Expose WebUI ban duration to users (Chocobo1)
|
||||||
|
- WEBUI: Implement "Secure" flag for session cookie (FranciscoPombal)
|
||||||
|
- WEBUI: Remove unused/deprecated option (FranciscoPombal)
|
||||||
|
- WEBUI: Prevent excessive sync requests (FranciscoPombal)
|
||||||
|
- WEBUI: Fix populating statistics window (FranciscoPombal)
|
||||||
|
- WEBUI: Fix matching uncategorized torrents (FranciscoPombal)
|
||||||
|
- WEBUI: Always allow whitespace in category names (FranciscoPombal)
|
||||||
|
- SEARCH: Bump python version for new installation (Chocobo1)
|
||||||
|
- SEARCH: Fix missing string (Chocobo1)
|
||||||
|
- SEARCH: Drop python2 support (Chocobo1)
|
||||||
|
- WINDOWS: Installer: Option to start qBittorrent on Windows start up (An0n)
|
||||||
|
- WINDOWS: Installer: Improve Czech translation (slrslr)
|
||||||
|
- WINDOWS: Installer: Update French translation (zywo)
|
||||||
|
- WINDOWS: Installer: Update German translation (schnurlos)
|
||||||
|
- WINDOWS: Installer: Update Japanese translation (maboroshin)
|
||||||
|
- WINDOWS: Path length limitation is removed on Windows 10 1607 onwards (an0n666)
|
||||||
|
|
||||||
|
Wed Dec 18 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.1
|
||||||
|
- FEATURE: Enable portable mode if "profile" directory exists (Tester798)
|
||||||
|
- FEATURE: Enable "Apply rate limit to peers on LAN" option by default (Chocobo1)
|
||||||
|
- BUGFIX: Sync translations from Transifex and run lupdate (sledgehammer999)
|
||||||
|
- BUGFIX: Don't unnecessarily delete OS files in folders (sledgehammer999)
|
||||||
|
- BUGFIX: Use the incomplete folder where appropriate (sledgehammer999)
|
||||||
|
- BUGFIX: Align Properties tab bar correctly on window resize (Prince Gupta)
|
||||||
|
- BUGFIX: Rework the listening IP/interface selection code (sledgehammer999)
|
||||||
|
- BUGFIX: Fix inconsistent icon for deleting torrent (Chocobo1)
|
||||||
|
- BUGFIX: Show torrent error message in transfer list (Chocobo1)
|
||||||
|
- BUGFIX: Fix stuck in wrong torrent state (Chocobo1)
|
||||||
|
- BUGFIX: Expand single-item folders in torrent content (warren)
|
||||||
|
- WEBUI: Bump Web API version (sledgehammer999)
|
||||||
|
- WEBUI: Add ability to rename torrent files from the WebUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Mention lack of HTTPS in WebUI magnet link warning (nl6720)
|
||||||
|
- WEBUI: Fix HTML elements size in search tab (Chocobo1)
|
||||||
|
- SEARCH: Fix incorrect translation displayed after language change (Chocobo1)
|
||||||
|
- SEARCH: Fix missing translations in search plugins dialog (Chocobo1)
|
||||||
|
- WINDOWS: Update russian translation of the installer (Andrei Stepanov)
|
||||||
|
|
||||||
Tue Dec 03 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.0
|
Tue Dec 03 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.0
|
||||||
- FEATURE: Libtorrent 1.2.x series are supported now (glassez)
|
- FEATURE: Libtorrent 1.2.x series are supported now (glassez)
|
||||||
- FEATURE: Add OpenSSL version to GUI and stackdump (Chocobo1)
|
- FEATURE: Add OpenSSL version to GUI and stackdump (Chocobo1)
|
||||||
|
|||||||
2
INSTALL
@@ -11,7 +11,7 @@ qBittorrent - A BitTorrent client in C++ / Qt
|
|||||||
|
|
||||||
- OpenSSL >= 1.1.1
|
- OpenSSL >= 1.1.1
|
||||||
|
|
||||||
- Qt 5.15.2 - 5.x
|
- Qt 5.15.2 - 5.x || 6.2.0 - 6.x
|
||||||
|
|
||||||
- zlib >= 1.2.11
|
- zlib >= 1.2.11
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Please report any bug (or feature request) to:
|
|||||||
http://bugs.qbittorrent.org
|
http://bugs.qbittorrent.org
|
||||||
|
|
||||||
Official IRC channel:
|
Official IRC channel:
|
||||||
`#qbittorrent on irc.libera.chat`
|
[#qbittorrent on irc.libera.chat](ircs://irc.libera.chat:6697/qbittorrent)
|
||||||
|
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
sledgehammer999 <sledgehammer999@qbittorrent.org>
|
sledgehammer999 \<sledgehammer999@qbittorrent.org\>
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ macro(qbt_common_config)
|
|||||||
$<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG_OUTPUT>
|
$<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG_OUTPUT>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
target_compile_definitions(qbt_common_cfg INTERFACE
|
||||||
|
_DARWIN_FEATURE_64_BIT_INODE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
target_compile_definitions(qbt_common_cfg INTERFACE
|
target_compile_definitions(qbt_common_cfg INTERFACE
|
||||||
NTDDI_VERSION=0x06010000
|
NTDDI_VERSION=0x06010000
|
||||||
|
|||||||
67
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.71 for qbittorrent v4.4.0alpha.
|
# Generated by GNU Autoconf 2.71 for qbittorrent v4.4.2.
|
||||||
#
|
#
|
||||||
# Report bugs to <bugs.qbittorrent.org>.
|
# Report bugs to <bugs.qbittorrent.org>.
|
||||||
#
|
#
|
||||||
@@ -611,8 +611,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.4.0alpha'
|
PACKAGE_VERSION='v4.4.2'
|
||||||
PACKAGE_STRING='qbittorrent v4.4.0alpha'
|
PACKAGE_STRING='qbittorrent v4.4.2'
|
||||||
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
||||||
PACKAGE_URL='https://www.qbittorrent.org/'
|
PACKAGE_URL='https://www.qbittorrent.org/'
|
||||||
|
|
||||||
@@ -1329,7 +1329,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.4.0alpha to adapt to many kinds of systems.
|
\`configure' configures qbittorrent v4.4.2 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1400,7 +1400,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.4.0alpha:";;
|
short | recursive ) echo "Configuration of qbittorrent v4.4.2:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1533,7 +1533,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.4.0alpha
|
qbittorrent configure v4.4.2
|
||||||
generated by GNU Autoconf 2.71
|
generated by GNU Autoconf 2.71
|
||||||
|
|
||||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||||
@@ -1648,7 +1648,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.4.0alpha, which was
|
It was created by qbittorrent $as_me v4.4.2, which was
|
||||||
generated by GNU Autoconf 2.71. Invocation command line was
|
generated by GNU Autoconf 2.71. Invocation command line was
|
||||||
|
|
||||||
$ $0$ac_configure_args_raw
|
$ $0$ac_configure_args_raw
|
||||||
@@ -4779,7 +4779,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='qbittorrent'
|
PACKAGE='qbittorrent'
|
||||||
VERSION='v4.4.0alpha'
|
VERSION='v4.4.2'
|
||||||
|
|
||||||
|
|
||||||
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
|
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
|
||||||
@@ -5188,29 +5188,38 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
# Detect OS
|
# Detect OS
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OS is FreeBSD" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable specific tweaks for current host \"$host_os\"" >&5
|
||||||
printf %s "checking whether OS is FreeBSD... " >&6; }
|
printf %s "checking whether to enable specific tweaks for current host \"$host_os\"... " >&6; }
|
||||||
if expr "$host_os" : ".*freebsd.*" > /dev/null
|
case "$host_os" in
|
||||||
then :
|
*darwin*)
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
printf "%s\n" "yes" >&6; }
|
printf "%s\n" "yes" >&6; }
|
||||||
LIBS="-lexecinfo $LIBS"
|
enable_qt_dbus=no
|
||||||
else $as_nop
|
;;
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
|
||||||
printf "%s\n" "no" >&6; }
|
|
||||||
fi
|
|
||||||
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OS is macOS" >&5
|
*freebsd*)
|
||||||
printf %s "checking whether OS is macOS... " >&6; }
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
if expr "$host_os" : ".*darwin.*" > /dev/null
|
|
||||||
then :
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
|
||||||
printf "%s\n" "yes" >&6; }
|
printf "%s\n" "yes" >&6; }
|
||||||
enable_qt_dbus=no
|
LIBS="-lexecinfo $LIBS"
|
||||||
else $as_nop
|
;;
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
|
||||||
|
*haiku*)
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
printf "%s\n" "yes" >&6; }
|
||||||
|
LIBS="-lnetwork $LIBS"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*openbsd*)
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
printf "%s\n" "yes" >&6; }
|
||||||
|
LIBS="-lexecinfo $LIBS"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Require 0.23 pkg-config
|
# Require 0.23 pkg-config
|
||||||
|
|
||||||
@@ -7245,7 +7254,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.4.0alpha, which was
|
This file was extended by qbittorrent $as_me v4.4.2, which was
|
||||||
generated by GNU Autoconf 2.71. Invocation command line was
|
generated by GNU Autoconf 2.71. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -7305,7 +7314,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config='$ac_cs_config_escaped'
|
ac_cs_config='$ac_cs_config_escaped'
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
qbittorrent config.status v4.4.0alpha
|
qbittorrent config.status v4.4.2
|
||||||
configured by $0, generated by GNU Autoconf 2.71,
|
configured by $0, generated by GNU Autoconf 2.71,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
38
configure.ac
@@ -1,5 +1,4 @@
|
|||||||
|
AC_INIT([qbittorrent], [v4.4.2], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
|
||||||
AC_INIT([qbittorrent], [v4.4.0alpha], [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])
|
||||||
: ${CFLAGS=""}
|
: ${CFLAGS=""}
|
||||||
@@ -54,17 +53,32 @@ AC_ARG_ENABLE(qt-dbus,
|
|||||||
[enable_qt_dbus=yes])
|
[enable_qt_dbus=yes])
|
||||||
|
|
||||||
# Detect OS
|
# Detect OS
|
||||||
AC_MSG_CHECKING([whether OS is FreeBSD])
|
AC_MSG_CHECKING([whether to enable specific tweaks for current host "$host_os"])
|
||||||
AS_IF([expr "$host_os" : ".*freebsd.*" > /dev/null],
|
case "$host_os" in
|
||||||
[AC_MSG_RESULT([yes])
|
*darwin*)
|
||||||
LIBS="-lexecinfo $LIBS"],
|
AC_MSG_RESULT([yes])
|
||||||
[AC_MSG_RESULT([no])])
|
enable_qt_dbus=no
|
||||||
|
;;
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether OS is macOS])
|
*freebsd*)
|
||||||
AS_IF([expr "$host_os" : ".*darwin.*" > /dev/null],
|
AC_MSG_RESULT([yes])
|
||||||
[AC_MSG_RESULT([yes])
|
LIBS="-lexecinfo $LIBS"
|
||||||
enable_qt_dbus=no],
|
;;
|
||||||
[AC_MSG_RESULT([no])])
|
|
||||||
|
*haiku*)
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
LIBS="-lnetwork $LIBS"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*openbsd*)
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
LIBS="-lexecinfo $LIBS"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Require 0.23 pkg-config
|
# Require 0.23 pkg-config
|
||||||
PKG_PROG_PKG_CONFIG([0.23])
|
PKG_PROG_PKG_CONFIG([0.23])
|
||||||
|
|||||||
4
dist/mac/Info.plist
vendored
@@ -55,7 +55,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.4.0</string>
|
<string>4.4.2</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>${EXECUTABLE_NAME}</string>
|
<string>${EXECUTABLE_NAME}</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
<key>NSAppleScriptEnabled</key>
|
<key>NSAppleScriptEnabled</key>
|
||||||
<string>YES</string>
|
<string>YES</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2006-2021 The qBittorrent project</string>
|
<string>Copyright © 2006-2022 The qBittorrent project</string>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
BIN
dist/unix/menuicons/128x128/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.3 KiB |
BIN
dist/unix/menuicons/16x16/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 775 B After Width: | Height: | Size: 750 B |
|
Before Width: | Height: | Size: 775 B After Width: | Height: | Size: 750 B |
BIN
dist/unix/menuicons/192x192/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
BIN
dist/unix/menuicons/22x22/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
dist/unix/menuicons/24x24/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
dist/unix/menuicons/32x32/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
dist/unix/menuicons/36x36/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
dist/unix/menuicons/48x48/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.8 KiB |
BIN
dist/unix/menuicons/64x64/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
dist/unix/menuicons/72x72/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.1 KiB |
BIN
dist/unix/menuicons/96x96/apps/qbittorrent.png
vendored
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.4 KiB |
@@ -74,6 +74,6 @@
|
|||||||
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
|
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
|
||||||
<content_rating type="oars-1.1"/>
|
<content_rating type="oars-1.1"/>
|
||||||
<releases>
|
<releases>
|
||||||
<release version="4.4.0" date="2020-10-18"/>
|
<release version="4.4.2" date="2022-03-22"/>
|
||||||
</releases>
|
</releases>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
117
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
@@ -16,15 +16,12 @@ Keywords=bittorrent;torrent;magnet;download;p2p;
|
|||||||
|
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Comment[oc]=Telecargar e partejar de fichièrs amb BitTorrent
|
|
||||||
GenericName[oc]=Client BitTorrent
|
|
||||||
Name[oc]=qBittorrent
|
|
||||||
Comment[af]=Aflaai en deel lêers oor BitTorrent
|
Comment[af]=Aflaai en deel lêers oor BitTorrent
|
||||||
GenericName[af]=BitTorrent kliënt
|
GenericName[af]=BitTorrent kliënt
|
||||||
Name[af]=qBittorrent
|
Name[af]=qBittorrent
|
||||||
Comment[ar]=نزّل وشارك الملفات عبر كيوبتتورنت
|
Comment[ar]=نزّل وشارك الملفات عبر كيوبتتورنت
|
||||||
GenericName[ar]=عميل بتتورنت
|
GenericName[ar]=عميل بتتورنت
|
||||||
Name[ar]=كيوبتتورنت
|
Name[ar]=qBittorrent
|
||||||
Comment[be]=Спампоўванне і раздача файлаў праз пратакол BitTorrent
|
Comment[be]=Спампоўванне і раздача файлаў праз пратакол BitTorrent
|
||||||
GenericName[be]=Кліент BitTorrent
|
GenericName[be]=Кліент BitTorrent
|
||||||
Name[be]=qBittorrent
|
Name[be]=qBittorrent
|
||||||
@@ -33,7 +30,10 @@ GenericName[bg]=BitTorrent клиент
|
|||||||
Name[bg]=qBittorrent
|
Name[bg]=qBittorrent
|
||||||
Comment[bn]=বিটটরেন্টে ফাইল ডাউনলোড এবং শেয়ার করুন
|
Comment[bn]=বিটটরেন্টে ফাইল ডাউনলোড এবং শেয়ার করুন
|
||||||
GenericName[bn]=বিটটরেন্ট ক্লায়েন্ট
|
GenericName[bn]=বিটটরেন্ট ক্লায়েন্ট
|
||||||
Name[bn]=কিউবি্টটরেন্ট
|
Name[bn]=qBittorrent
|
||||||
|
Comment[zh]=通过 BitTorrent 下载和分享文件
|
||||||
|
GenericName[zh]=BitTorrent 客户端
|
||||||
|
Name[zh]=qBittorrent
|
||||||
Comment[bs]=Preuzmi i dijeli datoteke preko BitTorrent-a
|
Comment[bs]=Preuzmi i dijeli datoteke preko BitTorrent-a
|
||||||
GenericName[bs]=BitTorrent klijent
|
GenericName[bs]=BitTorrent klijent
|
||||||
Name[bs]=qBittorrent
|
Name[bs]=qBittorrent
|
||||||
@@ -49,8 +49,8 @@ Name[da]=qBittorrent
|
|||||||
Comment[de]=Über BitTorrent Dateien herunterladen und teilen
|
Comment[de]=Über BitTorrent Dateien herunterladen und teilen
|
||||||
GenericName[de]=BitTorrent Client
|
GenericName[de]=BitTorrent Client
|
||||||
Name[de]=qBittorrent
|
Name[de]=qBittorrent
|
||||||
Comment[el]=Κάντε λήψη και ανταλλάξτε αρχεία μέσω BitTorrent
|
Comment[el]=Κάντε λήψη και μοιραστείτε αρχεία μέσω BitTorrent
|
||||||
GenericName[el]=Πελάτης BitTorrent
|
GenericName[el]=BitTorrent client
|
||||||
Name[el]=qBittorrent
|
Name[el]=qBittorrent
|
||||||
Comment[en_GB]=Download and share files over BitTorrent
|
Comment[en_GB]=Download and share files over BitTorrent
|
||||||
GenericName[en_GB]=BitTorrent client
|
GenericName[en_GB]=BitTorrent client
|
||||||
@@ -66,11 +66,11 @@ GenericName[eu]=BitTorrent bezeroa
|
|||||||
Name[eu]=qBittorrent
|
Name[eu]=qBittorrent
|
||||||
Comment[fa]=دانلود و به اشتراک گذاری فایل های بوسیله بیت تورنت
|
Comment[fa]=دانلود و به اشتراک گذاری فایل های بوسیله بیت تورنت
|
||||||
GenericName[fa]=بیت تورنت نسخه کلاینت
|
GenericName[fa]=بیت تورنت نسخه کلاینت
|
||||||
Name[fa]=کیو بیت تورنت
|
Name[fa]=qBittorrent
|
||||||
Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen
|
Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen
|
||||||
GenericName[fi]=BitTorrent-asiakasohjelma
|
GenericName[fi]=BitTorrent-asiakasohjelma
|
||||||
Name[fi]=qBittorrent
|
Name[fi]=qBittorrent
|
||||||
Comment[fr]=Télécharger et partager des fichiers avec BitTorrent
|
Comment[fr]=Télécharger et partager des fichiers sur BitTorrent
|
||||||
GenericName[fr]=Client BitTorrent
|
GenericName[fr]=Client BitTorrent
|
||||||
Name[fr]=qBittorrent
|
Name[fr]=qBittorrent
|
||||||
Comment[gl]=Descargar e compartir ficheiros co protocolo BitTorrent
|
Comment[gl]=Descargar e compartir ficheiros co protocolo BitTorrent
|
||||||
@@ -78,7 +78,7 @@ GenericName[gl]=Cliente BitTorrent
|
|||||||
Name[gl]=qBittorrent
|
Name[gl]=qBittorrent
|
||||||
Comment[gu]=બિટ્ટોરેંટ પર ફાઈલો ડાઉનલોડ અને શેર કરો
|
Comment[gu]=બિટ્ટોરેંટ પર ફાઈલો ડાઉનલોડ અને શેર કરો
|
||||||
GenericName[gu]=બિટ્ટોરેંટ ક્લાયન્ટ
|
GenericName[gu]=બિટ્ટોરેંટ ક્લાયન્ટ
|
||||||
Name[gu]=ક્યૂ-બિટ્ટોરેંટ
|
Name[gu]=qBittorrent
|
||||||
Comment[he]=הורד ושתף קבצים על גבי ביטורנט
|
Comment[he]=הורד ושתף קבצים על גבי ביטורנט
|
||||||
GenericName[he]=לקוח ביטורנט
|
GenericName[he]=לקוח ביטורנט
|
||||||
Name[he]=qBittorrent
|
Name[he]=qBittorrent
|
||||||
@@ -106,27 +106,21 @@ Name[ja]=qBittorrent
|
|||||||
Comment[ka]=ჩამოტვირთე და გააზიარე ფაილები Bittorrent-ის საშუალებით
|
Comment[ka]=ჩამოტვირთე და გააზიარე ფაილები Bittorrent-ის საშუალებით
|
||||||
GenericName[ka]=BitTorrent კლიენტი
|
GenericName[ka]=BitTorrent კლიენტი
|
||||||
Name[ka]=qBittorrent
|
Name[ka]=qBittorrent
|
||||||
Comment[ko]=비트토렌트를 통해 파일을 받고 공유합니다
|
Comment[ko]=BitTorrent를 통해 파일 받기 및 공유
|
||||||
GenericName[ko]=비트토렌트 클라이언트
|
GenericName[ko]=BitTorrent 클라이언트
|
||||||
Name[ko]=qBittorrent
|
Name[ko]=qBittorrent
|
||||||
Comment[zh]=通过 BitTorrent 下载和分享文件
|
|
||||||
GenericName[zh]=BitTorrent 客户端
|
|
||||||
Name[zh]=qBittorrent
|
|
||||||
Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle
|
Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle
|
||||||
GenericName[lt]=BitTorrent klientas
|
GenericName[lt]=BitTorrent klientas
|
||||||
Name[lt]=qBittorrent
|
Name[lt]=qBittorrent
|
||||||
Comment[mk]=Превземајте и споделувајте фајлови преку BitTorrent
|
Comment[mk]=Превземајте и споделувајте фајлови преку BitTorrent
|
||||||
GenericName[mk]=BitTorrent клиент
|
GenericName[mk]=BitTorrent клиент
|
||||||
Name[mk]=qBittorrent
|
Name[mk]=qBittorrent
|
||||||
Comment[en_AU]=Download and share files over BitTorrent
|
Comment[my]=တောရန့်ဖြင့်ဖိုင်များဒေါင်းလုဒ်ဆွဲရန်နှင့်မျှဝေရန်
|
||||||
GenericName[en_AU]=BitTorrent client
|
GenericName[my]=တောရန့်စီမံခန့်ခွဲသည့်အရာ
|
||||||
Name[en_AU]=qBittorrent
|
Name[my]=qBittorrent
|
||||||
Comment[nb]=Last ned og del filer over BitTorrent
|
Comment[nb]=Last ned og del filer over BitTorrent
|
||||||
GenericName[nb]=BitTorrent-klient
|
GenericName[nb]=BitTorrent-klient
|
||||||
Name[nb]=qBittorrent
|
Name[nb]=qBittorrent
|
||||||
Comment[nqo]=ߞߐߕߐ߯ߘߐ ߟߎ߬ ߟߊߖߌ߰ ߞߊ߬ ߓߊ߲߫ ߞߵߊ߬ߟߎ߬ ߘߐߕߟߊ߫ ߓߌߙߏߙߍ߲ߕ ߞߊ߲߬
|
|
||||||
GenericName[nqo]=ߓߌߙߏߙߍ߲ߕ ߕߣߐ߬ߓߐ߬ߟߊ
|
|
||||||
Name[nqo]=ߞߎ߳ߓߌߕߏߙߍ߲ߕ
|
|
||||||
Comment[nl]=Bestanden downloaden en delen via BitTorrent
|
Comment[nl]=Bestanden downloaden en delen via BitTorrent
|
||||||
GenericName[nl]=BitTorrent-client
|
GenericName[nl]=BitTorrent-client
|
||||||
Name[nl]=qBittorrent
|
Name[nl]=qBittorrent
|
||||||
@@ -151,14 +145,62 @@ Name[sk]=qBittorrent
|
|||||||
Comment[sl]=Prenesite in delite datoteke preko BitTorrenta
|
Comment[sl]=Prenesite in delite datoteke preko BitTorrenta
|
||||||
GenericName[sl]=BitTorrent odjemalec
|
GenericName[sl]=BitTorrent odjemalec
|
||||||
Name[sl]=qBittorrent
|
Name[sl]=qBittorrent
|
||||||
|
Name[sq]=qBittorrent
|
||||||
Comment[sr]=Преузимајте и делите фајлове преко BitTorrent протокола
|
Comment[sr]=Преузимајте и делите фајлове преко BitTorrent протокола
|
||||||
GenericName[sr]=BitTorrent-клијент
|
GenericName[sr]=BitTorrent-клијент
|
||||||
|
Name[sr]=qBittorrent
|
||||||
Comment[sr@latin]=Preuzimanje i deljenje fajlova preko BitTorrent-a
|
Comment[sr@latin]=Preuzimanje i deljenje fajlova preko BitTorrent-a
|
||||||
GenericName[sr@latin]=BitTorrent klijent
|
GenericName[sr@latin]=BitTorrent klijent
|
||||||
Name[sr@latin]=qBittorrent
|
Name[sr@latin]=qBittorrent
|
||||||
Comment[sv]=Hämta och dela filer över BitTorrent
|
Comment[sv]=Hämta och dela filer över BitTorrent
|
||||||
GenericName[sv]=BitTorrent-klient
|
GenericName[sv]=BitTorrent-klient
|
||||||
Name[sv]=qBittorrent
|
Name[sv]=qBittorrent
|
||||||
|
Comment[ta]=BitTorrent வழியாக கோப்புகளை பதிவிறக்க மற்றும் பகிர
|
||||||
|
GenericName[ta]=BitTorrent வாடிக்கையாளர்
|
||||||
|
Name[ta]=qBittorrent
|
||||||
|
Comment[te]=క్యు బిట్ టొరెంట్ తో ఫైల్స్ దిగుమతి చేసుకోండి , పంచుకోండి
|
||||||
|
GenericName[te]=క్యు బిట్ టొరెంట్ క్లయింట్
|
||||||
|
Name[te]=qBittorrent
|
||||||
|
Comment[th]=ดาวน์โหลดและแชร์ไฟล์ผ่าน BitTorrent
|
||||||
|
GenericName[th]=ไคลเอนต์ BitTorrent
|
||||||
|
Name[th]=qBittorrent
|
||||||
|
Comment[tr]=Dosyaları BitTorrent üzerinden indirin ve paylaşın
|
||||||
|
GenericName[tr]=BitTorrent istemcisi
|
||||||
|
Name[tr]=qBittorrent
|
||||||
|
Comment[ur]=BitTorrent پر فائلوں کو ڈاؤن لوڈ کریں اور اشتراک کریں
|
||||||
|
GenericName[ur]=قیو بٹ ٹورنٹ کلائنٹ
|
||||||
|
Name[ur]=qBittorrent
|
||||||
|
Comment[uk]=Завантажуйте та поширюйте файли через BitTorrent
|
||||||
|
GenericName[uk]=BitTorrent-клієнт
|
||||||
|
Name[uk]=qBittorrent
|
||||||
|
Comment[vi]=Tải về và chia sẻ tệp qua BitTorrent
|
||||||
|
GenericName[vi]=Máy khách BitTorrent
|
||||||
|
Name[vi]=qBittorrent
|
||||||
|
Comment[zh_HK]=經由BitTorrent下載並分享檔案
|
||||||
|
GenericName[zh_HK]=BitTorrent用戶端
|
||||||
|
Name[zh_HK]=qBittorrent
|
||||||
|
Comment[zh_TW]=經由 BitTorrent 下載並分享檔案
|
||||||
|
GenericName[zh_TW]=BitTorrent 客戶端
|
||||||
|
Name[zh_TW]=qBittorrent
|
||||||
|
Comment[eo]=Elŝutu kaj kunhavigu dosierojn per BitTorrent
|
||||||
|
GenericName[eo]=BitTorrent-kliento
|
||||||
|
Name[eo]=qBittorrent
|
||||||
|
Comment[kk]=BitTorrent арқылы файл жүктеу және бөлісу
|
||||||
|
GenericName[kk]=BitTorrent клиенті
|
||||||
|
Name[kk]=qBittorrent
|
||||||
|
Comment[en_AU]=Download and share files over BitTorrent
|
||||||
|
GenericName[en_AU]=BitTorrent client
|
||||||
|
Name[en_AU]=qBittorrent
|
||||||
|
Name[rm]=qBittorrent
|
||||||
|
Name[jv]=qBittorrent
|
||||||
|
Comment[oc]=Telecargar e partejar de fichièrs amb BitTorrent
|
||||||
|
GenericName[oc]=Client BitTorrent
|
||||||
|
Name[oc]=qBittorrent
|
||||||
|
Name[ug]=qBittorrent
|
||||||
|
Name[yi]=qBittorrent
|
||||||
|
Comment[nqo]=ߞߐߕߐ߯ߘߐ ߟߎ߬ ߟߊߖߌ߰ ߞߊ߬ ߓߊ߲߫ ߞߵߊ߬ߟߎ߬ ߘߐߕߟߊ߫ ߓߌߙߏߙߍ߲ߕ ߞߊ߲߬
|
||||||
|
GenericName[nqo]=ߓߌߙߏߙߍ߲ߕ ߕߣߐ߬ߓߐ߬ߟߊ
|
||||||
|
Name[nqo]=qBittorrent
|
||||||
Comment[uz@Latn]=BitTorrent orqali fayllarni yuklab olish va baham ko‘rish
|
Comment[uz@Latn]=BitTorrent orqali fayllarni yuklab olish va baham ko‘rish
|
||||||
GenericName[uz@Latn]=BitTorrent mijozi
|
GenericName[uz@Latn]=BitTorrent mijozi
|
||||||
Name[uz@Latn]=qBittorrent
|
Name[uz@Latn]=qBittorrent
|
||||||
@@ -167,52 +209,23 @@ GenericName[ltg]=BitTorrent klients
|
|||||||
Name[ltg]=qBittorrent
|
Name[ltg]=qBittorrent
|
||||||
Comment[hi_IN]=BitTorrent द्वारा फाइल डाउनलोड व सहभाजन
|
Comment[hi_IN]=BitTorrent द्वारा फाइल डाउनलोड व सहभाजन
|
||||||
GenericName[hi_IN]=Bittorrent साधन
|
GenericName[hi_IN]=Bittorrent साधन
|
||||||
Name[hi_IN]=क्यूबिटटाॅरेंट
|
Name[hi_IN]=qBittorrent
|
||||||
Comment[tr]=Dosyaları BitTorrent üzerinden indirin ve paylaşın
|
|
||||||
GenericName[tr]=BitTorrent istemcisi
|
|
||||||
Name[tr]=qBittorrent
|
|
||||||
Comment[ur]=BitTorrent پر فائلوں کو ڈاؤن لوڈ کریں اور اشتراک کریں
|
|
||||||
GenericName[ur]=قیو بٹ ٹورنٹ کلائنٹ
|
|
||||||
Name[ur]=قیو بٹ ٹورنٹ
|
|
||||||
Comment[uk]=Завантажуйте та поширюйте файли через BitTorrent
|
|
||||||
GenericName[uk]=BitTorrent-клієнт
|
|
||||||
Name[uk]=qBittorrent
|
|
||||||
Comment[vi]=Tải về và chia sẻ tệp qua BitTorrent
|
|
||||||
GenericName[vi]=Máy khách BitTorrent
|
|
||||||
Name[vi]=qBittorrent
|
|
||||||
Comment[az@latin]=Faylları BitTorrent vasitəsilə göndərin və paylaşın
|
Comment[az@latin]=Faylları BitTorrent vasitəsilə göndərin və paylaşın
|
||||||
GenericName[az@latin]=BitTorrent client
|
GenericName[az@latin]=BitTorrent client
|
||||||
Name[az@latin]=qBittorrent
|
Name[az@latin]=qBittorrent
|
||||||
Comment[zh_HK]=經由BitTorrent下載並分享檔案
|
|
||||||
GenericName[zh_HK]=BitTorrent用戶端
|
|
||||||
Name[zh_HK]=qBittorrent
|
|
||||||
Comment[zh_TW]=經由 BitTorrent 下載並分享檔案
|
|
||||||
GenericName[zh_TW]=BitTorrent 客戶端
|
|
||||||
Name[zh_TW]=qBittorrent
|
|
||||||
Comment[lv_LV]=Lejupielādēt un koplietot failus ar BitTorrent
|
Comment[lv_LV]=Lejupielādēt un koplietot failus ar BitTorrent
|
||||||
GenericName[lv_LV]=BitTorrent klients
|
GenericName[lv_LV]=BitTorrent klients
|
||||||
Name[lv_LV]=qBittorrent
|
Name[lv_LV]=qBittorrent
|
||||||
Comment[ms_MY]=Muat turun dan kongsi fail melalui BitTorrent
|
Comment[ms_MY]=Muat turun dan kongsi fail melalui BitTorrent
|
||||||
GenericName[ms_MY]=Klien BitTorrent
|
GenericName[ms_MY]=Klien BitTorrent
|
||||||
Name[ms_MY]=qBittorrent
|
Name[ms_MY]=qBittorrent
|
||||||
Comment[eo]=Elŝutu kaj kunhavigu dosierojn per BitTorrent
|
|
||||||
GenericName[eo]=BitTorrent-kliento
|
|
||||||
Name[eo]=qBittorrent
|
|
||||||
Comment[mn_MN]=BitTorrent-оор файлуудаа тат, түгээ
|
Comment[mn_MN]=BitTorrent-оор файлуудаа тат, түгээ
|
||||||
GenericName[mn_MN]=BitTorrent татагч
|
GenericName[mn_MN]=BitTorrent татагч
|
||||||
Name[mn_MN]=qBittorrent
|
Name[mn_MN]=qBittorrent
|
||||||
Comment[ta]=BitTorrent வழியாக கோப்புகளை பதிவிறக்க மற்றும் பகிர
|
|
||||||
GenericName[ta]=BitTorrent வாடிக்கையாளர்
|
|
||||||
Name[ta]=qBittorrent
|
|
||||||
Comment[ne_NP]=फाइलहरू डाउनलोड गर्नुहोस् र BitTorrent मा साझा गर्नुहोस्
|
Comment[ne_NP]=फाइलहरू डाउनलोड गर्नुहोस् र BitTorrent मा साझा गर्नुहोस्
|
||||||
GenericName[ne_NP]=BitTorrent क्लाइन्ट
|
GenericName[ne_NP]=BitTorrent क्लाइन्ट
|
||||||
Name[ne_NP]=qBittorrent
|
Name[ne_NP]=qBittorrent
|
||||||
Comment[te]=క్యు బిట్ టొరెంట్ తో ఫైల్స్ దిగుమతి చేసుకోండి , పంచుకోండి
|
|
||||||
GenericName[te]=క్యు బిట్ టొరెంట్ క్లయింట్
|
|
||||||
Name[te]=క్యు బిట్ టొరెంట్
|
|
||||||
Comment[pt_PT]=Transferir e partilhar ficheiros por BitTorrent
|
Comment[pt_PT]=Transferir e partilhar ficheiros por BitTorrent
|
||||||
GenericName[pt_PT]=Cliente BitTorrent
|
GenericName[pt_PT]=Cliente BitTorrent
|
||||||
Name[pt_PT]=qBittorrent
|
Name[pt_PT]=qBittorrent
|
||||||
Comment[th]=ดาวน์โหลดและแชร์ไฟล์ด้วยบิททอเร้น
|
Name[si_LK]=qBittorrent
|
||||||
GenericName[th]=โปรแกรมบิททอเร้น
|
|
||||||
Name[th]=qBittorrent
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Type=simple
|
|||||||
PrivateTmp=false
|
PrivateTmp=false
|
||||||
User=%i
|
User=%i
|
||||||
ExecStart=@EXPAND_BINDIR@/qbittorrent-nox
|
ExecStart=@EXPAND_BINDIR@/qbittorrent-nox
|
||||||
|
TimeoutStopSec=1800
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
36
dist/windows/installer-translations/french.nsi
vendored
@@ -3,27 +3,27 @@
|
|||||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||||
LangString inst_qbt_req ${LANG_FRENCH} "qBittorrent (requis)"
|
LangString inst_qbt_req ${LANG_FRENCH} "qBittorrent (requis)"
|
||||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||||
LangString inst_dekstop ${LANG_FRENCH} "Créer Raccourci Bureau"
|
LangString inst_dekstop ${LANG_FRENCH} "Créer un Raccourci sur le Bureau"
|
||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_FRENCH} "Créer Raccourci dans le Menu Démarrer"
|
LangString inst_startmenu ${LANG_FRENCH} "Créer un Raccourci dans le Menu Démarrer"
|
||||||
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
||||||
LangString inst_startup ${LANG_FRENCH} "Démarrez qBittorrent au démarrage de Windows"
|
LangString inst_startup ${LANG_FRENCH} "Démarrez qBittorrent au démarrage de Windows"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_FRENCH} "Ouvrir fichiers .torrent avec qBittorrent"
|
LangString inst_torrent ${LANG_FRENCH} "Ouvrir les fichiers .torrent avec qBittorrent"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
LangString inst_magnet ${LANG_FRENCH} "Ouvrir liens magnet avec qBittorrent"
|
LangString inst_magnet ${LANG_FRENCH} "Ouvrir les liens magnet avec qBittorrent"
|
||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_FRENCH} "Ajouter règle Pare-Feu Windows"
|
LangString inst_firewall ${LANG_FRENCH} "Ajouter une règle au Pare-Feu de Windows"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_FRENCH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_FRENCH} "Désactiver la limite de taille du chemin de Windows (limitation de MAX_PATH 260 caractères, nécessite Windows 10 1607 ou plus)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_FRENCH} "Ajout règle Pare-Feu Windows"
|
LangString inst_firewallinfo ${LANG_FRENCH} "Ajout d'une règle au Pare-Feu de Windows"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant l'installation."
|
LangString inst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant l'installation."
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
||||||
LangString inst_uninstall_question ${LANG_FRENCH} "Une installation précédente a été détectée. Elle sera désinstallée sans supprimer les réglages utilisateur."
|
LangString inst_uninstall_question ${LANG_FRENCH} "Une installation précédente a été détectée. Elle sera désinstallée en conservant les réglages utilisateur."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_FRENCH} "Désinstallation de la version précédente."
|
LangString inst_unist ${LANG_FRENCH} "Désinstallation de la version antérieure."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_FRENCH} "Lancer qBittorrent."
|
LangString launch_qbt ${LANG_FRENCH} "Lancer qBittorrent."
|
||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
@@ -31,27 +31,27 @@ LangString inst_requires_64bit ${LANG_FRENCH} "Cet installateur ne fonctionne qu
|
|||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_FRENCH} "Cette version de qBittorrent nécessite au moins Windows 7."
|
LangString inst_requires_win7 ${LANG_FRENCH} "Cette version de qBittorrent nécessite au moins Windows 7."
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_FRENCH} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_FRENCH} "Désinstaller qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
|
|
||||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||||
LangString remove_files ${LANG_FRENCH} "Supprimer fichiers"
|
LangString remove_files ${LANG_FRENCH} "Supprimer les fichiers"
|
||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_FRENCH} "Supprimer raccourcis"
|
LangString remove_shortcuts ${LANG_FRENCH} "Supprimer les raccourcis"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_FRENCH} "Supprimer associations de fichiers"
|
LangString remove_associations ${LANG_FRENCH} "Supprimer les associations de fichiers"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_FRENCH} "Supprimer clés de registre"
|
LangString remove_registry ${LANG_FRENCH} "Supprimer les clés de registre"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
LangString remove_conf ${LANG_FRENCH} "Supprimer fichiers de configuration"
|
LangString remove_conf ${LANG_FRENCH} "Supprimer les fichiers de configuration"
|
||||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||||
LangString remove_firewall ${LANG_FRENCH} "Supprimer règle Pare-Feu Windows"
|
LangString remove_firewall ${LANG_FRENCH} "Supprimer la règle du Pare-Feu de Windows"
|
||||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||||
LangString remove_firewallinfo ${LANG_FRENCH} "Suppression règle Pare-Feu Windows"
|
LangString remove_firewallinfo ${LANG_FRENCH} "Suppression de la règle du Pare-Feu de Windows"
|
||||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||||
LangString remove_cache ${LANG_FRENCH} "Supprimer torrents et données cachées"
|
LangString remove_cache ${LANG_FRENCH} "Supprimer les torrents et données cachées"
|
||||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||||
LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant la désinstallation."
|
LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant la désinstallation."
|
||||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
;Installer strings
|
;Installer strings
|
||||||
|
|
||||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||||
LangString inst_qbt_req ${LANG_INDONESIAN} "qBittorrent (required)"
|
LangString inst_qbt_req ${LANG_INDONESIAN} "qBittorrent (diperlukan)"
|
||||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||||
LangString inst_dekstop ${LANG_INDONESIAN} "Create Desktop Shortcut"
|
LangString inst_dekstop ${LANG_INDONESIAN} "Buat Pintasan Desktop"
|
||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_INDONESIAN} "Create Start Menu Shortcut"
|
LangString inst_startmenu ${LANG_INDONESIAN} "Buat Pintasan Menu"
|
||||||
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
||||||
LangString inst_startup ${LANG_INDONESIAN} "Start qBittorrent on Windows start up"
|
LangString inst_startup ${LANG_INDONESIAN} "Jalankan qBittorrent pada start up Windows"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_INDONESIAN} "Open .torrent files with qBittorrent"
|
LangString inst_torrent ${LANG_INDONESIAN} "Buka file .torrent dengan qBittorrent"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
LangString inst_magnet ${LANG_INDONESIAN} "Open magnet links with qBittorrent"
|
LangString inst_magnet ${LANG_INDONESIAN} "Buka link magnet dengan qBittorrent"
|
||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_INDONESIAN} "Add Windows Firewall rule"
|
LangString inst_firewall ${LANG_INDONESIAN} "Tambahkan aturan Windows Firewall"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_INDONESIAN} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_INDONESIAN} "Matikan batasan panjang path Windows (limitasi MAX_PATH 260 karaker, membutuhkan Windows 10 1607 atau lebih baru)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_INDONESIAN} "Adding Windows Firewall rule"
|
LangString inst_firewallinfo ${LANG_INDONESIAN} "Menambahkan aturan Windows Firewall"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_INDONESIAN} "qBittorrent is running. Please close the application before installing."
|
LangString inst_warning ${LANG_INDONESIAN} "qBittorrent berjalan. Mohon tutup aplikasi sebelum memasang."
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
||||||
LangString inst_uninstall_question ${LANG_INDONESIAN} "Current version will be uninstalled. User settings and torrents will remain intact."
|
LangString inst_uninstall_question ${LANG_INDONESIAN} "Versi saat ini akan dicopot. Pengaturan pengguna dan torrent akan tetap utuh."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_INDONESIAN} "Uninstalling previous version."
|
LangString inst_unist ${LANG_INDONESIAN} "Mencopot versi sebelumnya."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_INDONESIAN} "Launch qBittorrent."
|
LangString launch_qbt ${LANG_INDONESIAN} "Buka qBittorrent."
|
||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
LangString inst_requires_64bit ${LANG_INDONESIAN} "This installer works only in 64-bit Windows versions."
|
LangString inst_requires_64bit ${LANG_INDONESIAN} "Aplikasi ini hanya berjalan pada versi Windows 64-bit."
|
||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_INDONESIAN} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_INDONESIAN} "Versi qBittorrent ini membutuhkan setidaknya Windows 7."
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_INDONESIAN} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_INDONESIAN} "Copot qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
|
|
||||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||||
LangString remove_files ${LANG_INDONESIAN} "Remove files"
|
LangString remove_files ${LANG_INDONESIAN} "Hapus file"
|
||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_INDONESIAN} "Remove shortcuts"
|
LangString remove_shortcuts ${LANG_INDONESIAN} "Hapus pintasan"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_INDONESIAN} "Remove file associations"
|
LangString remove_associations ${LANG_INDONESIAN} "Hapus asosiasi file"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_INDONESIAN} "Remove registry keys"
|
LangString remove_registry ${LANG_INDONESIAN} "Hapus key registri"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
LangString remove_conf ${LANG_INDONESIAN} "Remove configuration files"
|
LangString remove_conf ${LANG_INDONESIAN} "Hapus file konfigurasi"
|
||||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||||
LangString remove_firewall ${LANG_INDONESIAN} "Remove Windows Firewall rule"
|
LangString remove_firewall ${LANG_INDONESIAN} "Hapus aturan Windows Firewall"
|
||||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||||
LangString remove_firewallinfo ${LANG_INDONESIAN} "Removing Windows Firewall rule"
|
LangString remove_firewallinfo ${LANG_INDONESIAN} "Menghapus aturan Windows Firewall"
|
||||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||||
LangString remove_cache ${LANG_INDONESIAN} "Remove torrents and cached data"
|
LangString remove_cache ${LANG_INDONESIAN} "Hapus torrent dan data ter-cache"
|
||||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||||
LangString uninst_warning ${LANG_INDONESIAN} "qBittorrent is running. Please close the application before uninstalling."
|
LangString uninst_warning ${LANG_INDONESIAN} "qBittorrent berjalan. Mohon tutup aplikasi sebelum mencopot."
|
||||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||||
LangString uninst_tor_warn ${LANG_INDONESIAN} "Not removing .torrent association. It is associated with:"
|
LangString uninst_tor_warn ${LANG_INDONESIAN} "Tidak menghapus asosiasi .torrent. Terasosiasi dengan:"
|
||||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||||
LangString uninst_mag_warn ${LANG_INDONESIAN} "Not removing magnet association. It is associated with:"
|
LangString uninst_mag_warn ${LANG_INDONESIAN} "Tidak menghapus asosiasi magnet. Terasosiasi dengan:"
|
||||||
|
|||||||
54
dist/windows/installer-translations/korean.nsi
vendored
@@ -1,60 +1,60 @@
|
|||||||
;Installer strings
|
;Installer strings
|
||||||
|
|
||||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||||
LangString inst_qbt_req ${LANG_KOREAN} "qBittorrent (required)"
|
LangString inst_qbt_req ${LANG_KOREAN} "qBittorrent (필요함)"
|
||||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||||
LangString inst_dekstop ${LANG_KOREAN} "Create Desktop Shortcut"
|
LangString inst_dekstop ${LANG_KOREAN} "바탕화면 바로가기 만들기"
|
||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_KOREAN} "Create Start Menu Shortcut"
|
LangString inst_startmenu ${LANG_KOREAN} "시작 메뉴 바로가기 만들기"
|
||||||
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
||||||
LangString inst_startup ${LANG_KOREAN} "Start qBittorrent on Windows start up"
|
LangString inst_startup ${LANG_KOREAN} "Windows 시작 시 qBittorrent 시작"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_KOREAN} "Open .torrent files with qBittorrent"
|
LangString inst_torrent ${LANG_KOREAN} "qBittorrent로 .torrent 파일 열기"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
LangString inst_magnet ${LANG_KOREAN} "Open magnet links with qBittorrent"
|
LangString inst_magnet ${LANG_KOREAN} "qBittorrent로 자석 링크 열기"
|
||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_KOREAN} "Add Windows Firewall rule"
|
LangString inst_firewall ${LANG_KOREAN} "Windows 방화벽 규칙 추가"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_KOREAN} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_KOREAN} "Windows 경로 길이 제한 비활성화(260자 MAX_PATH 제한, Windows 10 1607 이상 필요)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_KOREAN} "Adding Windows Firewall rule"
|
LangString inst_firewallinfo ${LANG_KOREAN} "Windows 방화벽 규칙 추가하는 중"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_KOREAN} "qBittorrent is running. Please close the application before installing."
|
LangString inst_warning ${LANG_KOREAN} "qBittorrent가 실행 중입니다. 설치하기 전에 응용 프로그램을 닫으십시오."
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
||||||
LangString inst_uninstall_question ${LANG_KOREAN} "Current version will be uninstalled. User settings and torrents will remain intact."
|
LangString inst_uninstall_question ${LANG_KOREAN} "현재 버전이 삭제됩니다. 사용자 설정과 토렌트는 그대로 유지됩니다."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_KOREAN} "Uninstalling previous version."
|
LangString inst_unist ${LANG_KOREAN} "이전 버전을 삭제하는 중입니다."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_KOREAN} "Launch qBittorrent."
|
LangString launch_qbt ${LANG_KOREAN} "qBittorrent를 실행합니다."
|
||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
LangString inst_requires_64bit ${LANG_KOREAN} "This installer works only in 64-bit Windows versions."
|
LangString inst_requires_64bit ${LANG_KOREAN} "이 설치 프로그램은 64비트 윈도우즈 버전에서만 작동합니다."
|
||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_KOREAN} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_KOREAN} "이 qBittorrent 버전에는 Windows 7 이상이 필요합니다."
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_KOREAN} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_KOREAN} "qBittorrent 삭제"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
|
|
||||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||||
LangString remove_files ${LANG_KOREAN} "Remove files"
|
LangString remove_files ${LANG_KOREAN} "파일 제거"
|
||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_KOREAN} "Remove shortcuts"
|
LangString remove_shortcuts ${LANG_KOREAN} "바로가기 제거"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_KOREAN} "Remove file associations"
|
LangString remove_associations ${LANG_KOREAN} "파일 연결 제거"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_KOREAN} "Remove registry keys"
|
LangString remove_registry ${LANG_KOREAN} "레지스트리 키 제거"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
LangString remove_conf ${LANG_KOREAN} "Remove configuration files"
|
LangString remove_conf ${LANG_KOREAN} "구성 파일 제거"
|
||||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||||
LangString remove_firewall ${LANG_KOREAN} "Remove Windows Firewall rule"
|
LangString remove_firewall ${LANG_KOREAN} "Windows 방화벽 규칙 제거"
|
||||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||||
LangString remove_firewallinfo ${LANG_KOREAN} "Removing Windows Firewall rule"
|
LangString remove_firewallinfo ${LANG_KOREAN} "Windows 방화벽 규칙 제거하는 중"
|
||||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||||
LangString remove_cache ${LANG_KOREAN} "Remove torrents and cached data"
|
LangString remove_cache ${LANG_KOREAN} "토렌트 및 캐시된 데이터 제거"
|
||||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||||
LangString uninst_warning ${LANG_KOREAN} "qBittorrent is running. Please close the application before uninstalling."
|
LangString uninst_warning ${LANG_KOREAN} "qBittorrent가 실행 중입니다. 삭제하기 전에 응용 프로그램을 닫으십시오."
|
||||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||||
LangString uninst_tor_warn ${LANG_KOREAN} "Not removing .torrent association. It is associated with:"
|
LangString uninst_tor_warn ${LANG_KOREAN} ".torrent 연결을 제거하지 않습니다. 관련 항목:"
|
||||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||||
LangString uninst_mag_warn ${LANG_KOREAN} "Not removing magnet association. It is associated with:"
|
LangString uninst_mag_warn ${LANG_KOREAN} "자석 연결을 제거하지 않습니다. 관련 항목:"
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
;Installer strings
|
;Installer strings
|
||||||
|
|
||||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||||
LangString inst_qbt_req ${LANG_SIMPCHINESE} "qBittorrent (必要)"
|
LangString inst_qbt_req ${LANG_SIMPCHINESE} "qBittorrent 主程序 (必要)"
|
||||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||||
LangString inst_dekstop ${LANG_SIMPCHINESE} "创建桌面快捷方式"
|
LangString inst_dekstop ${LANG_SIMPCHINESE} "创建桌面快捷方式"
|
||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_SIMPCHINESE} "创建开始菜单快捷方式"
|
LangString inst_startmenu ${LANG_SIMPCHINESE} "创建开始菜单快捷方式"
|
||||||
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
||||||
LangString inst_startup ${LANG_SIMPCHINESE} "在Windows上启动qBittorrent进行启动"
|
LangString inst_startup ${LANG_SIMPCHINESE} "qBittorrent 开机自启动"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_SIMPCHINESE} "用 qBittorrent 打开.torrent文件"
|
LangString inst_torrent ${LANG_SIMPCHINESE} "用 qBittorrent 打开.torrent文件"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
LangString inst_magnet ${LANG_SIMPCHINESE} "用 qBittorrent 打开磁力链接"
|
LangString inst_magnet ${LANG_SIMPCHINESE} "用 qBittorrent 打开磁力链接"
|
||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_SIMPCHINESE} "添加Windows防火墙规则"
|
LangString inst_firewall ${LANG_SIMPCHINESE} "添加 Windows 防火墙规则"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_SIMPCHINESE} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_SIMPCHINESE} "解除 Windows 的 PATH 长度限制 (解除 MAX_PATH 为 260 的限制, 需要 Windows 10 1607 或更新版本)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_SIMPCHINESE} "正在添加Windows防火墙规则"
|
LangString inst_firewallinfo ${LANG_SIMPCHINESE} "正在添加 Windows 防火墙规则"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 安装前请关闭应用程序。"
|
LangString inst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 安装前请先关闭它。"
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
||||||
LangString inst_uninstall_question ${LANG_SIMPCHINESE} "检测到以前的安装。 它将被卸载但不删除用户设置。"
|
LangString inst_uninstall_question ${LANG_SIMPCHINESE} "当前版本会被卸载。 用户设置和种子会被完整保留。"
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_SIMPCHINESE} "卸载以前的版本。"
|
LangString inst_unist ${LANG_SIMPCHINESE} "卸载以前的版本。"
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_SIMPCHINESE} "启动 qBittorrent."
|
LangString launch_qbt ${LANG_SIMPCHINESE} "启动 qBittorrent。"
|
||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
LangString inst_requires_64bit ${LANG_SIMPCHINESE} "此安装程序只能在64位的Windows上工作。"
|
LangString inst_requires_64bit ${LANG_SIMPCHINESE} "此安装程序仅支持 64 位 Windows 系统。"
|
||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_SIMPCHINESE} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_SIMPCHINESE} "这个版本的 qBittorrent 仅支持 Windows 7 及更新的系统。"
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_SIMPCHINESE} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_SIMPCHINESE} "卸载 qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
@@ -41,20 +41,20 @@ LangString remove_files ${LANG_SIMPCHINESE} "删除文件"
|
|||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_SIMPCHINESE} "删除快捷方式"
|
LangString remove_shortcuts ${LANG_SIMPCHINESE} "删除快捷方式"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_SIMPCHINESE} "删除文件关联"
|
LangString remove_associations ${LANG_SIMPCHINESE} "解除文件关联"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_SIMPCHINESE} "删除注册表键"
|
LangString remove_registry ${LANG_SIMPCHINESE} "删除注册表键"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
LangString remove_conf ${LANG_SIMPCHINESE} "删除配置文件"
|
LangString remove_conf ${LANG_SIMPCHINESE} "删除配置文件"
|
||||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||||
LangString remove_firewall ${LANG_SIMPCHINESE} "删除Windows防火墙规则"
|
LangString remove_firewall ${LANG_SIMPCHINESE} "删除 Windows 防火墙规则"
|
||||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||||
LangString remove_firewallinfo ${LANG_SIMPCHINESE} "正在删除Windows防火墙规则"
|
LangString remove_firewallinfo ${LANG_SIMPCHINESE} "正在删除 Windows 防火墙规则"
|
||||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||||
LangString remove_cache ${LANG_SIMPCHINESE} "删除种子和缓存数据"
|
LangString remove_cache ${LANG_SIMPCHINESE} "删除种子和缓存数据"
|
||||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||||
LangString uninst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 卸载前请关闭程序。"
|
LangString uninst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 卸载前请关闭程序。"
|
||||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||||
LangString uninst_tor_warn ${LANG_SIMPCHINESE} "不删除 .torrent 关联。 关联的是:"
|
LangString uninst_tor_warn ${LANG_SIMPCHINESE} "未解除与 .torrent 的关联。 它已与另一程序关联:"
|
||||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||||
LangString uninst_mag_warn ${LANG_SIMPCHINESE} "不删除磁力关联。 关联的是:"
|
LangString uninst_mag_warn ${LANG_SIMPCHINESE} "未解除与 磁力链接 的关联。 它已与另一程序关联:"
|
||||||
|
|||||||
10
dist/windows/installer-translations/spanish.nsi
vendored
@@ -7,7 +7,7 @@ LangString inst_dekstop ${LANG_SPANISH} "Crear un acceso directo en el escritori
|
|||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_SPANISH} "Crear un acceso directo en el menú inicio"
|
LangString inst_startmenu ${LANG_SPANISH} "Crear un acceso directo en el menú inicio"
|
||||||
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
||||||
LangString inst_startup ${LANG_SPANISH} "Inicie qBittorrent en el inicio de Windows"
|
LangString inst_startup ${LANG_SPANISH} "Iniciar qBittorrent en el inicio de Windows"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_SPANISH} "Abrir archivos .torrent con qBittorrent"
|
LangString inst_torrent ${LANG_SPANISH} "Abrir archivos .torrent con qBittorrent"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
@@ -15,7 +15,7 @@ LangString inst_magnet ${LANG_SPANISH} "Abrir enlaces magnet con qBittorrent"
|
|||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_SPANISH} "Añadir regla al Firewall de Windows"
|
LangString inst_firewall ${LANG_SPANISH} "Añadir regla al Firewall de Windows"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_SPANISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_SPANISH} "Deshabilitar límite de caracteres del PATH de Windows (limitación MAX_PATH de 260 caracteres, requiere Windows 10 1607 o superior)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_SPANISH} "Añadiendo regla al Firewall de Windows"
|
LangString inst_firewallinfo ${LANG_SPANISH} "Añadiendo regla al Firewall de Windows"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
@@ -29,9 +29,9 @@ LangString launch_qbt ${LANG_SPANISH} "Iniciar qBittorrent."
|
|||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
LangString inst_requires_64bit ${LANG_SPANISH} "Este instalador solo funciona en versiones de 64-bit de Windows."
|
LangString inst_requires_64bit ${LANG_SPANISH} "Este instalador solo funciona en versiones de 64-bit de Windows."
|
||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_SPANISH} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_SPANISH} "Esta versión de qBittorrent requiere Windows 7 o superior."
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_SPANISH} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_SPANISH} "Desinstalar qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
@@ -41,7 +41,7 @@ LangString remove_files ${LANG_SPANISH} "Quitar archivos"
|
|||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_SPANISH} "Quitar accesos directos"
|
LangString remove_shortcuts ${LANG_SPANISH} "Quitar accesos directos"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_SPANISH} "Deshacer asociaciones"
|
LangString remove_associations ${LANG_SPANISH} "Deshacer asociaciones de archivos"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_SPANISH} "Eliminar claves del registro"
|
LangString remove_registry ${LANG_SPANISH} "Eliminar claves del registro"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ LangString inst_dekstop ${LANG_SPANISHINTERNATIONAL} "Crear un acceso directo en
|
|||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_SPANISHINTERNATIONAL} "Crear un acceso directo en el menú inicio"
|
LangString inst_startmenu ${LANG_SPANISHINTERNATIONAL} "Crear un acceso directo en el menú inicio"
|
||||||
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
|
||||||
LangString inst_startup ${LANG_SPANISHINTERNATIONAL} "Inicie qBittorrent en el inicio de Windows"
|
LangString inst_startup ${LANG_SPANISHINTERNATIONAL} "Iniciar qBittorrent en el inicio de Windows"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_SPANISHINTERNATIONAL} "Abrir archivos .torrent con qBittorrent"
|
LangString inst_torrent ${LANG_SPANISHINTERNATIONAL} "Abrir archivos .torrent con qBittorrent"
|
||||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||||
@@ -15,7 +15,7 @@ LangString inst_magnet ${LANG_SPANISHINTERNATIONAL} "Abrir enlaces magnet con qB
|
|||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_SPANISHINTERNATIONAL} "Añadir regla al Firewall de Windows"
|
LangString inst_firewall ${LANG_SPANISHINTERNATIONAL} "Añadir regla al Firewall de Windows"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_SPANISHINTERNATIONAL} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_SPANISHINTERNATIONAL} "Deshabilitar límite de caracteres del PATH de Windows (limitación MAX_PATH de 260 caracteres, requiere Windows 10 1607 o superior)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_SPANISHINTERNATIONAL} "Añadiendo regla al Firewall de Windows"
|
LangString inst_firewallinfo ${LANG_SPANISHINTERNATIONAL} "Añadiendo regla al Firewall de Windows"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
@@ -29,9 +29,9 @@ LangString launch_qbt ${LANG_SPANISHINTERNATIONAL} "Iniciar qBittorrent."
|
|||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
LangString inst_requires_64bit ${LANG_SPANISHINTERNATIONAL} "Este instalador solo funciona en versiones de 64-bit de Windows."
|
LangString inst_requires_64bit ${LANG_SPANISHINTERNATIONAL} "Este instalador solo funciona en versiones de 64-bit de Windows."
|
||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_SPANISHINTERNATIONAL} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_SPANISHINTERNATIONAL} "Esta versión de qBittorrent requiere Windows 7 o superior."
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_SPANISHINTERNATIONAL} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_SPANISHINTERNATIONAL} "Desinstalar qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
@@ -41,7 +41,7 @@ LangString remove_files ${LANG_SPANISHINTERNATIONAL} "Quitar archivos"
|
|||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_SPANISHINTERNATIONAL} "Quitar accesos directos"
|
LangString remove_shortcuts ${LANG_SPANISHINTERNATIONAL} "Quitar accesos directos"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_SPANISHINTERNATIONAL} "Deshacer asociaciones"
|
LangString remove_associations ${LANG_SPANISHINTERNATIONAL} "Deshacer asociaciones de archivos"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_SPANISHINTERNATIONAL} "Eliminar claves del registro"
|
LangString remove_registry ${LANG_SPANISHINTERNATIONAL} "Eliminar claves del registro"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
|
|||||||
@@ -15,21 +15,21 @@ LangString inst_magnet ${LANG_TRADCHINESE} "使用 qBittorrent 開啟 magnet 連
|
|||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_TRADCHINESE} "建立 Windows 防火牆規則"
|
LangString inst_firewall ${LANG_TRADCHINESE} "建立 Windows 防火牆規則"
|
||||||
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
||||||
LangString inst_pathlimit ${LANG_TRADCHINESE} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_TRADCHINESE} "停用 Windows 路徑長度限制 (MAX_PATH 260 字元限制,需 Windows 10 1607 以上版本)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_TRADCHINESE} "正在建立 Windows 防火牆規則"
|
LangString inst_firewallinfo ${LANG_TRADCHINESE} "正在建立 Windows 防火牆規則"
|
||||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||||
LangString inst_warning ${LANG_TRADCHINESE} "qBittorrent 正在執行中,請先關閉後再進行安裝。"
|
LangString inst_warning ${LANG_TRADCHINESE} "qBittorrent 正在執行中,請先關閉後再進行安裝。"
|
||||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
||||||
LangString inst_uninstall_question ${LANG_TRADCHINESE} "Current version will be uninstalled. User settings and torrents will remain intact."
|
LangString inst_uninstall_question ${LANG_TRADCHINESE} "目前版本將被解除安裝。使用者設定及 torrent 將保留。"
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_TRADCHINESE} "正在移除先前版本"
|
LangString inst_unist ${LANG_TRADCHINESE} "正在移除先前版本"
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_TRADCHINESE} "啟動 qBittorrent"
|
LangString launch_qbt ${LANG_TRADCHINESE} "啟動 qBittorrent"
|
||||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||||
LangString inst_requires_64bit ${LANG_TRADCHINESE} "This installer works only in 64-bit Windows versions."
|
LangString inst_requires_64bit ${LANG_TRADCHINESE} "此安裝程式僅支援 64 位元版本的 Windows。"
|
||||||
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
|
||||||
LangString inst_requires_win7 ${LANG_TRADCHINESE} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_TRADCHINESE} "此 qBittorrent 版本僅支援 Windows 7 以上的系統。"
|
||||||
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
|
||||||
LangString inst_uninstall_link_description ${LANG_TRADCHINESE} "移除 qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_TRADCHINESE} "移除 qBittorrent"
|
||||||
|
|
||||||
|
|||||||
4
dist/windows/options.nsi
vendored
@@ -28,7 +28,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.4.0"
|
!define PROG_VERSION "4.4.2"
|
||||||
|
|
||||||
!define MUI_FINISHPAGE_RUN
|
!define MUI_FINISHPAGE_RUN
|
||||||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
||||||
@@ -51,7 +51,7 @@ 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-2021 The qBittorrent project"
|
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2022 The qBittorrent project"
|
||||||
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
||||||
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ else {
|
|||||||
|
|
||||||
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
|
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
|
||||||
|
|
||||||
|
DEFINES += _DARWIN_FEATURE_64_BIT_INODE
|
||||||
|
|
||||||
LIBS += -framework Carbon -framework IOKit -framework AppKit
|
LIBS += -framework Carbon -framework IOKit -framework AppKit
|
||||||
|
|
||||||
QT_LANG_PATH = ../dist/qt-translations
|
QT_LANG_PATH = ../dist/qt-translations
|
||||||
|
|||||||
@@ -43,13 +43,24 @@ set_property(CACHE LibtorrentRasterbar_DIR PROPERTY TYPE PATH)
|
|||||||
find_package(Boost ${minBoostVersion} REQUIRED)
|
find_package(Boost ${minBoostVersion} REQUIRED)
|
||||||
find_package(OpenSSL ${minOpenSSLVersion} REQUIRED)
|
find_package(OpenSSL ${minOpenSSLVersion} REQUIRED)
|
||||||
find_package(ZLIB ${minZlibVersion} REQUIRED)
|
find_package(ZLIB ${minZlibVersion} REQUIRED)
|
||||||
find_package(Qt5 ${minQtVersion} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools)
|
if (QT6)
|
||||||
if (DBUS)
|
find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools)
|
||||||
find_package(Qt5 ${minQtVersion} REQUIRED COMPONENTS DBus)
|
if (DBUS)
|
||||||
set_package_properties(Qt5DBus PROPERTIES
|
find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS DBus)
|
||||||
DESCRIPTION "Qt5 module for inter-process communication over the D-Bus protocol"
|
set_package_properties(Qt6DBus PROPERTIES
|
||||||
PURPOSE "Required by the DBUS feature"
|
DESCRIPTION "Qt6 module for inter-process communication over the D-Bus protocol"
|
||||||
)
|
PURPOSE "Required by the DBUS feature"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools)
|
||||||
|
if (DBUS)
|
||||||
|
find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS DBus)
|
||||||
|
set_package_properties(Qt5DBus PROPERTIES
|
||||||
|
DESCRIPTION "Qt5 module for inter-process communication over the D-Bus protocol"
|
||||||
|
PURPOSE "Required by the DBUS feature"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# automatically call Qt moc, rcc and uic as needed for all targets by default
|
# automatically call Qt moc, rcc and uic as needed for all targets by default
|
||||||
@@ -68,10 +79,15 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|||||||
add_subdirectory(base)
|
add_subdirectory(base)
|
||||||
|
|
||||||
if (GUI)
|
if (GUI)
|
||||||
find_package(Qt5 ${minQtVersion} REQUIRED COMPONENTS Widgets Svg)
|
if (QT6)
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Widgets Svg)
|
||||||
find_package(Qt5 ${minQtVersion} REQUIRED COMPONENTS WinExtras)
|
else()
|
||||||
|
find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS Widgets Svg)
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS WinExtras)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(gui)
|
add_subdirectory(gui)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
# Based on https://gist.github.com/giraldeau/546ba5512a74dfe9d8ea0862d66db412
|
# Based on https://gist.github.com/giraldeau/546ba5512a74dfe9d8ea0862d66db412
|
||||||
file(GLOB QBT_TS_FILES "${qBittorrent_SOURCE_DIR}/src/lang/*.ts")
|
file(GLOB QBT_TS_FILES "${qBittorrent_SOURCE_DIR}/src/lang/*.ts")
|
||||||
set_source_files_properties(${QBT_TS_FILES} PROPERTIES OUTPUT_LOCATION "${qBittorrent_BINARY_DIR}/src/lang")
|
set_source_files_properties(${QBT_TS_FILES} PROPERTIES OUTPUT_LOCATION "${qBittorrent_BINARY_DIR}/src/lang")
|
||||||
qt5_add_translation(QBT_QM_FILES ${QBT_TS_FILES} OPTIONS -silent)
|
qt_add_translation(QBT_QM_FILES ${QBT_TS_FILES} OPTIONS -silent)
|
||||||
configure_file("${qBittorrent_SOURCE_DIR}/src/lang/lang.qrc" "${qBittorrent_BINARY_DIR}/src/lang/lang.qrc" COPYONLY)
|
configure_file("${qBittorrent_SOURCE_DIR}/src/lang/lang.qrc" "${qBittorrent_BINARY_DIR}/src/lang/lang.qrc" COPYONLY)
|
||||||
|
|
||||||
if (WEBUI)
|
if (WEBUI)
|
||||||
file(GLOB QBT_WEBUI_TS_FILES "${qBittorrent_SOURCE_DIR}/src/webui/www/translations/*.ts")
|
file(GLOB QBT_WEBUI_TS_FILES "${qBittorrent_SOURCE_DIR}/src/webui/www/translations/*.ts")
|
||||||
set_source_files_properties(${QBT_WEBUI_TS_FILES}
|
set_source_files_properties(${QBT_WEBUI_TS_FILES}
|
||||||
PROPERTIES OUTPUT_LOCATION "${qBittorrent_BINARY_DIR}/src/webui/www/translations")
|
PROPERTIES OUTPUT_LOCATION "${qBittorrent_BINARY_DIR}/src/webui/www/translations")
|
||||||
qt5_add_translation(QBT_WEBUI_QM_FILES ${QBT_WEBUI_TS_FILES} OPTIONS -silent)
|
qt_add_translation(QBT_WEBUI_QM_FILES ${QBT_WEBUI_TS_FILES} OPTIONS -silent)
|
||||||
configure_file("${qBittorrent_SOURCE_DIR}/src/webui/www/translations/webui_translations.qrc"
|
configure_file("${qBittorrent_SOURCE_DIR}/src/webui/www/translations/webui_translations.qrc"
|
||||||
"${qBittorrent_BINARY_DIR}/src/webui/www/translations/webui_translations.qrc" COPYONLY)
|
"${qBittorrent_BINARY_DIR}/src/webui/www/translations/webui_translations.qrc" COPYONLY)
|
||||||
endif()
|
endif()
|
||||||
@@ -139,7 +139,7 @@ endif()
|
|||||||
if (GUI)
|
if (GUI)
|
||||||
target_link_libraries(qbt_app PRIVATE qbt_gui)
|
target_link_libraries(qbt_app PRIVATE qbt_gui)
|
||||||
if ((CMAKE_SYSTEM_NAME STREQUAL "Windows") OR (CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
|
if ((CMAKE_SYSTEM_NAME STREQUAL "Windows") OR (CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
|
||||||
qt_import_plugins(qbt_app INCLUDE Qt5::QSvgIconPlugin Qt5::QSvgPlugin)
|
qt_import_plugins(qbt_app INCLUDE Qt::QSvgIconPlugin Qt::QSvgPlugin)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/torrent.h"
|
#include "base/bittorrent/torrent.h"
|
||||||
#include "base/exceptions.h"
|
#include "base/exceptions.h"
|
||||||
|
#include "base/global.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"
|
||||||
@@ -100,22 +101,10 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
#define SETTINGS_KEY(name) "Application/" name
|
#define SETTINGS_KEY(name) "Application/" name
|
||||||
|
#define FILELOGGER_SETTINGS_KEY(name) (SETTINGS_KEY("FileLogger/") name)
|
||||||
// FileLogger properties keys
|
|
||||||
#define FILELOGGER_SETTINGS_KEY(name) QStringLiteral(SETTINGS_KEY("FileLogger/") name)
|
|
||||||
const QString KEY_FILELOGGER_ENABLED = FILELOGGER_SETTINGS_KEY("Enabled");
|
|
||||||
const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path");
|
|
||||||
const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup");
|
|
||||||
const QString KEY_FILELOGGER_DELETEOLD = FILELOGGER_SETTINGS_KEY("DeleteOld");
|
|
||||||
const QString KEY_FILELOGGER_MAXSIZEBYTES = FILELOGGER_SETTINGS_KEY("MaxSizeBytes");
|
|
||||||
const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age");
|
|
||||||
const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType");
|
|
||||||
|
|
||||||
// just a shortcut
|
|
||||||
inline SettingsStorage *settings() { return SettingsStorage::instance(); }
|
|
||||||
|
|
||||||
const QString LOG_FOLDER = QStringLiteral("logs");
|
const QString LOG_FOLDER = QStringLiteral("logs");
|
||||||
const QChar PARAMS_SEPARATOR = '|';
|
const QChar PARAMS_SEPARATOR = QLatin1Char('|');
|
||||||
|
|
||||||
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QStringLiteral("profile");
|
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QStringLiteral("profile");
|
||||||
|
|
||||||
@@ -133,6 +122,16 @@ Application::Application(int &argc, char **argv)
|
|||||||
, m_running(false)
|
, m_running(false)
|
||||||
, m_shutdownAct(ShutdownDialogAction::Exit)
|
, m_shutdownAct(ShutdownDialogAction::Exit)
|
||||||
, m_commandLineArgs(parseCommandLine(this->arguments()))
|
, m_commandLineArgs(parseCommandLine(this->arguments()))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
, m_storeMemoryWorkingSetLimit(SETTINGS_KEY("MemoryWorkingSetLimit"))
|
||||||
|
#endif
|
||||||
|
, m_storeFileLoggerEnabled(FILELOGGER_SETTINGS_KEY("Enabled"))
|
||||||
|
, m_storeFileLoggerBackup(FILELOGGER_SETTINGS_KEY("Backup"))
|
||||||
|
, m_storeFileLoggerDeleteOld(FILELOGGER_SETTINGS_KEY("DeleteOld"))
|
||||||
|
, m_storeFileLoggerMaxSize(FILELOGGER_SETTINGS_KEY("MaxSizeBytes"))
|
||||||
|
, m_storeFileLoggerAge(FILELOGGER_SETTINGS_KEY("Age"))
|
||||||
|
, m_storeFileLoggerAgeType(FILELOGGER_SETTINGS_KEY("AgeType"))
|
||||||
|
, m_storeFileLoggerPath(FILELOGGER_SETTINGS_KEY("Path"))
|
||||||
{
|
{
|
||||||
qRegisterMetaType<Log::Msg>("Log::Msg");
|
qRegisterMetaType<Log::Msg>("Log::Msg");
|
||||||
qRegisterMetaType<Log::Peer>("Log::Peer");
|
qRegisterMetaType<Log::Peer>("Log::Peer");
|
||||||
@@ -141,7 +140,9 @@ Application::Application(int &argc, char **argv)
|
|||||||
setOrganizationDomain("qbittorrent.org");
|
setOrganizationDomain("qbittorrent.org");
|
||||||
#if !defined(DISABLE_GUI)
|
#if !defined(DISABLE_GUI)
|
||||||
setDesktopFileName("org.qbittorrent.qBittorrent");
|
setDesktopFileName("org.qbittorrent.qBittorrent");
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
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
|
||||||
|
#endif
|
||||||
setQuitOnLastWindowClosed(false);
|
setQuitOnLastWindowClosed(false);
|
||||||
QPixmapCache::setCacheLimit(PIXMAP_CACHE_SIZE);
|
QPixmapCache::setCacheLimit(PIXMAP_CACHE_SIZE);
|
||||||
#endif
|
#endif
|
||||||
@@ -152,17 +153,11 @@ Application::Application(int &argc, char **argv)
|
|||||||
const QString profileDir = portableModeEnabled
|
const QString profileDir = portableModeEnabled
|
||||||
? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR)
|
? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR)
|
||||||
: m_commandLineArgs.profileDir;
|
: m_commandLineArgs.profileDir;
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
const QString instanceId = (profileDir + (m_commandLineArgs.configurationName.isEmpty() ? QString {} : ('/' + m_commandLineArgs.configurationName))).toLower();
|
|
||||||
#else
|
|
||||||
const QString instanceId = profileDir + (m_commandLineArgs.configurationName.isEmpty() ? QString {} : ('/' + m_commandLineArgs.configurationName));
|
|
||||||
#endif
|
|
||||||
const QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString() + '@' + instanceId;
|
|
||||||
m_instanceManager = new ApplicationInstanceManager {appId, this};
|
|
||||||
|
|
||||||
Profile::initInstance(profileDir, m_commandLineArgs.configurationName,
|
Profile::initInstance(profileDir, m_commandLineArgs.configurationName,
|
||||||
(m_commandLineArgs.relativeFastresumePaths || portableModeEnabled));
|
(m_commandLineArgs.relativeFastresumePaths || portableModeEnabled));
|
||||||
|
|
||||||
|
m_instanceManager = new ApplicationInstanceManager {Profile::instance()->location(SpecialFolder::Config), this};
|
||||||
|
|
||||||
Logger::initInstance();
|
Logger::initInstance();
|
||||||
SettingsStorage::initInstance();
|
SettingsStorage::initInstance();
|
||||||
Preferences::initInstance();
|
Preferences::initInstance();
|
||||||
@@ -213,9 +208,25 @@ const QBtCommandLineParameters &Application::commandLineArgs() const
|
|||||||
return m_commandLineArgs;
|
return m_commandLineArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
int Application::memoryWorkingSetLimit() const
|
||||||
|
{
|
||||||
|
return m_storeMemoryWorkingSetLimit.get(512);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::setMemoryWorkingSetLimit(const int size)
|
||||||
|
{
|
||||||
|
if (size == memoryWorkingSetLimit())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_storeMemoryWorkingSetLimit = size;
|
||||||
|
applyMemoryWorkingSetLimit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Application::isFileLoggerEnabled() const
|
bool Application::isFileLoggerEnabled() const
|
||||||
{
|
{
|
||||||
return settings()->loadValue(KEY_FILELOGGER_ENABLED, true);
|
return m_storeFileLoggerEnabled.get(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerEnabled(const bool value)
|
void Application::setFileLoggerEnabled(const bool value)
|
||||||
@@ -224,49 +235,48 @@ void Application::setFileLoggerEnabled(const bool value)
|
|||||||
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()));
|
||||||
else if (!value)
|
else if (!value)
|
||||||
delete m_fileLogger;
|
delete m_fileLogger;
|
||||||
settings()->storeValue(KEY_FILELOGGER_ENABLED, value);
|
m_storeFileLoggerEnabled = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Application::fileLoggerPath() const
|
QString Application::fileLoggerPath() const
|
||||||
{
|
{
|
||||||
return settings()->loadValue(KEY_FILELOGGER_PATH
|
return m_storeFileLoggerPath.get(QDir(specialFolderLocation(SpecialFolder::Data)).absoluteFilePath(LOG_FOLDER));
|
||||||
, QString {specialFolderLocation(SpecialFolder::Data) + LOG_FOLDER});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerPath(const QString &path)
|
void Application::setFileLoggerPath(const QString &path)
|
||||||
{
|
{
|
||||||
if (m_fileLogger)
|
if (m_fileLogger)
|
||||||
m_fileLogger->changePath(path);
|
m_fileLogger->changePath(path);
|
||||||
settings()->storeValue(KEY_FILELOGGER_PATH, path);
|
m_storeFileLoggerPath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::isFileLoggerBackup() const
|
bool Application::isFileLoggerBackup() const
|
||||||
{
|
{
|
||||||
return settings()->loadValue(KEY_FILELOGGER_BACKUP, true);
|
return m_storeFileLoggerBackup.get(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerBackup(const bool value)
|
void Application::setFileLoggerBackup(const bool value)
|
||||||
{
|
{
|
||||||
if (m_fileLogger)
|
if (m_fileLogger)
|
||||||
m_fileLogger->setBackup(value);
|
m_fileLogger->setBackup(value);
|
||||||
settings()->storeValue(KEY_FILELOGGER_BACKUP, value);
|
m_storeFileLoggerBackup = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::isFileLoggerDeleteOld() const
|
bool Application::isFileLoggerDeleteOld() const
|
||||||
{
|
{
|
||||||
return settings()->loadValue(KEY_FILELOGGER_DELETEOLD, true);
|
return m_storeFileLoggerDeleteOld.get(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerDeleteOld(const bool value)
|
void Application::setFileLoggerDeleteOld(const bool value)
|
||||||
{
|
{
|
||||||
if (value && m_fileLogger)
|
if (value && m_fileLogger)
|
||||||
m_fileLogger->deleteOld(fileLoggerAge(), static_cast<FileLogger::FileLogAgeType>(fileLoggerAgeType()));
|
m_fileLogger->deleteOld(fileLoggerAge(), static_cast<FileLogger::FileLogAgeType>(fileLoggerAgeType()));
|
||||||
settings()->storeValue(KEY_FILELOGGER_DELETEOLD, value);
|
m_storeFileLoggerDeleteOld = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::fileLoggerMaxSize() const
|
int Application::fileLoggerMaxSize() const
|
||||||
{
|
{
|
||||||
const int val = settings()->loadValue(KEY_FILELOGGER_MAXSIZEBYTES, DEFAULT_FILELOG_SIZE);
|
const int val = m_storeFileLoggerMaxSize.get(DEFAULT_FILELOG_SIZE);
|
||||||
return std::min(std::max(val, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
|
return std::min(std::max(val, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,29 +285,29 @@ void Application::setFileLoggerMaxSize(const int bytes)
|
|||||||
const int clampedValue = std::min(std::max(bytes, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
|
const int clampedValue = std::min(std::max(bytes, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
|
||||||
if (m_fileLogger)
|
if (m_fileLogger)
|
||||||
m_fileLogger->setMaxSize(clampedValue);
|
m_fileLogger->setMaxSize(clampedValue);
|
||||||
settings()->storeValue(KEY_FILELOGGER_MAXSIZEBYTES, clampedValue);
|
m_storeFileLoggerMaxSize = clampedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::fileLoggerAge() const
|
int Application::fileLoggerAge() const
|
||||||
{
|
{
|
||||||
const int val = settings()->loadValue(KEY_FILELOGGER_AGE, 1);
|
const int val = m_storeFileLoggerAge.get(1);
|
||||||
return std::min(std::max(val, 1), 365);
|
return std::min(std::max(val, 1), 365);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerAge(const int value)
|
void Application::setFileLoggerAge(const int value)
|
||||||
{
|
{
|
||||||
settings()->storeValue(KEY_FILELOGGER_AGE, std::min(std::max(value, 1), 365));
|
m_storeFileLoggerAge = std::min(std::max(value, 1), 365);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::fileLoggerAgeType() const
|
int Application::fileLoggerAgeType() const
|
||||||
{
|
{
|
||||||
const int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1);
|
const int val = m_storeFileLoggerAgeType.get(1);
|
||||||
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);
|
m_storeFileLoggerAgeType = ((value < 0) || (value > 2)) ? 1 : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::processMessage(const QString &message)
|
void Application::processMessage(const QString &message)
|
||||||
@@ -612,6 +622,10 @@ void Application::processParams(const QStringList ¶ms)
|
|||||||
|
|
||||||
int Application::exec(const QStringList ¶ms)
|
int Application::exec(const QStringList ¶ms)
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
applyMemoryWorkingSetLimit();
|
||||||
|
#endif
|
||||||
|
|
||||||
Net::ProxyConfigurationManager::initInstance();
|
Net::ProxyConfigurationManager::initInstance();
|
||||||
Net::DownloadManager::initInstance();
|
Net::DownloadManager::initInstance();
|
||||||
IconProvider::initInstance();
|
IconProvider::initInstance();
|
||||||
@@ -655,18 +669,19 @@ int Application::exec(const QStringList ¶ms)
|
|||||||
|
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
#ifndef DISABLE_WEBUI
|
#ifndef DISABLE_WEBUI
|
||||||
Preferences *const pref = Preferences::instance();
|
const Preferences *pref = Preferences::instance();
|
||||||
// Display some information to the user
|
|
||||||
|
const auto scheme = QString::fromLatin1(pref->isWebUiHttpsEnabled() ? "https" : "http");
|
||||||
|
const auto url = QString::fromLatin1("%1://localhost:%2\n").arg(scheme, QString::number(pref->getWebUiPort()));
|
||||||
const QString mesg = QString::fromLatin1("\n******** %1 ********\n").arg(tr("Information"))
|
const QString mesg = QString::fromLatin1("\n******** %1 ********\n").arg(tr("Information"))
|
||||||
+ tr("To control qBittorrent, access the Web UI at %1")
|
+ tr("To control qBittorrent, access the WebUI at: %1").arg(url);
|
||||||
.arg(QString("http://localhost:") + QString::number(pref->getWebUiPort())) + '\n';
|
printf("%s\n", qUtf8Printable(mesg));
|
||||||
printf("%s", qUtf8Printable(mesg));
|
|
||||||
|
|
||||||
if (pref->getWebUIPassword() == "ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtHAjU9b3b7uB8NR1Gur2hmQCvCDpm39Q+PsJRJPaCU51dEiz+dTzh8qbPsL8WkFljQYFQ==")
|
if (pref->getWebUIPassword() == "ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtHAjU9b3b7uB8NR1Gur2hmQCvCDpm39Q+PsJRJPaCU51dEiz+dTzh8qbPsL8WkFljQYFQ==")
|
||||||
{
|
{
|
||||||
const QString warning = tr("The Web UI administrator username is: %1").arg(pref->getWebUiUsername()) + '\n'
|
const QString warning = tr("The Web UI administrator username is: %1").arg(pref->getWebUiUsername()) + '\n'
|
||||||
+ tr("The Web UI administrator password is still the default one: %1").arg("adminadmin") + '\n'
|
+ tr("The Web UI administrator password has not been changed from the default: %1").arg("adminadmin") + '\n'
|
||||||
+ tr("This is a security risk, please consider changing your password from program preferences.") + '\n';
|
+ tr("This is a security risk, please change your password in program preferences.") + '\n';
|
||||||
printf("%s", qUtf8Printable(warning));
|
printf("%s", qUtf8Printable(warning));
|
||||||
}
|
}
|
||||||
#endif // DISABLE_WEBUI
|
#endif // DISABLE_WEBUI
|
||||||
@@ -780,6 +795,29 @@ void Application::shutdownCleanup(QSessionManager &manager)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
void Application::applyMemoryWorkingSetLimit()
|
||||||
|
{
|
||||||
|
const SIZE_T UNIT_SIZE = 1024 * 1024; // MiB
|
||||||
|
const SIZE_T maxSize = memoryWorkingSetLimit() * UNIT_SIZE;
|
||||||
|
const SIZE_T minSize = std::min<SIZE_T>((64 * UNIT_SIZE), (maxSize / 2));
|
||||||
|
if (!::SetProcessWorkingSetSizeEx(::GetCurrentProcess(), minSize, maxSize, QUOTA_LIMITS_HARDWS_MAX_ENABLE))
|
||||||
|
{
|
||||||
|
const DWORD errorCode = ::GetLastError();
|
||||||
|
QString message;
|
||||||
|
LPVOID lpMsgBuf = nullptr;
|
||||||
|
if (::FormatMessageW((FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS)
|
||||||
|
, nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&lpMsgBuf), 0, nullptr))
|
||||||
|
{
|
||||||
|
message = QString::fromWCharArray(reinterpret_cast<LPWSTR>(lpMsgBuf)).trimmed();
|
||||||
|
::LocalFree(lpMsgBuf);
|
||||||
|
}
|
||||||
|
LogMsg(tr("Failed to set physical memory (RAM) usage limit. Error code: %1. Error message: \"%2\"")
|
||||||
|
.arg(QString::number(errorCode), message), Log::WARNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Application::cleanup()
|
void Application::cleanup()
|
||||||
{
|
{
|
||||||
// cleanup() can be called multiple times during shutdown. We only need it once.
|
// cleanup() can be called multiple times during shutdown. We only need it once.
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class QSessionManager;
|
|||||||
using BaseApplication = QCoreApplication;
|
using BaseApplication = QCoreApplication;
|
||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
|
#include "base/settingvalue.h"
|
||||||
#include "base/types.h"
|
#include "base/types.h"
|
||||||
#include "cmdoptions.h"
|
#include "cmdoptions.h"
|
||||||
|
|
||||||
@@ -87,6 +88,11 @@ public:
|
|||||||
|
|
||||||
const QBtCommandLineParameters &commandLineArgs() const;
|
const QBtCommandLineParameters &commandLineArgs() const;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
int memoryWorkingSetLimit() const;
|
||||||
|
void setMemoryWorkingSetLimit(int size);
|
||||||
|
#endif
|
||||||
|
|
||||||
// FileLogger properties
|
// FileLogger properties
|
||||||
bool isFileLoggerEnabled() const;
|
bool isFileLoggerEnabled() const;
|
||||||
void setFileLoggerEnabled(bool value);
|
void setFileLoggerEnabled(bool value);
|
||||||
@@ -120,6 +126,14 @@ private slots:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
void applyMemoryWorkingSetLimit();
|
||||||
|
#endif
|
||||||
|
void initializeTranslation();
|
||||||
|
void processParams(const QStringList ¶ms);
|
||||||
|
void runExternalProgram(const BitTorrent::Torrent *torrent) const;
|
||||||
|
void sendNotificationEmail(const BitTorrent::Torrent *torrent);
|
||||||
|
|
||||||
ApplicationInstanceManager *m_instanceManager = nullptr;
|
ApplicationInstanceManager *m_instanceManager = nullptr;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
ShutdownDialogAction m_shutdownAct;
|
ShutdownDialogAction m_shutdownAct;
|
||||||
@@ -140,8 +154,14 @@ private:
|
|||||||
QTranslator m_translator;
|
QTranslator m_translator;
|
||||||
QStringList m_paramsQueue;
|
QStringList m_paramsQueue;
|
||||||
|
|
||||||
void initializeTranslation();
|
#ifdef Q_OS_WIN
|
||||||
void processParams(const QStringList ¶ms);
|
SettingValue<int> m_storeMemoryWorkingSetLimit;
|
||||||
void runExternalProgram(const BitTorrent::Torrent *torrent) const;
|
#endif
|
||||||
void sendNotificationEmail(const BitTorrent::Torrent *torrent);
|
SettingValue<bool> m_storeFileLoggerEnabled;
|
||||||
|
SettingValue<bool> m_storeFileLoggerBackup;
|
||||||
|
SettingValue<bool> m_storeFileLoggerDeleteOld;
|
||||||
|
SettingValue<int> m_storeFileLoggerMaxSize;
|
||||||
|
SettingValue<int> m_storeFileLoggerAge;
|
||||||
|
SettingValue<int> m_storeFileLoggerAgeType;
|
||||||
|
SettingValue<QString> m_storeFileLoggerPath;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,24 +28,27 @@
|
|||||||
|
|
||||||
#include "applicationinstancemanager.h"
|
#include "applicationinstancemanager.h"
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSharedMemory>
|
#include <QSharedMemory>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "qtlocalpeer/qtlocalpeer.h"
|
#include "qtlocalpeer/qtlocalpeer.h"
|
||||||
|
|
||||||
ApplicationInstanceManager::ApplicationInstanceManager(const QString &appId, QObject *parent)
|
ApplicationInstanceManager::ApplicationInstanceManager(const QString &instancePath, QObject *parent)
|
||||||
: QObject {parent}
|
: QObject {parent}
|
||||||
, m_peer {new QtLocalPeer {this, appId}}
|
, m_peer {new QtLocalPeer {instancePath, this}}
|
||||||
, m_isFirstInstance {!m_peer->isClient()}
|
, m_isFirstInstance {!m_peer->isClient()}
|
||||||
{
|
{
|
||||||
connect(m_peer, &QtLocalPeer::messageReceived, this, &ApplicationInstanceManager::messageReceived);
|
connect(m_peer, &QtLocalPeer::messageReceived, this, &ApplicationInstanceManager::messageReceived);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
auto sharedMem = new QSharedMemory {appId + QLatin1String {"-shared-memory-key"}, this};
|
const QString sharedMemoryKey = instancePath + QLatin1String {"/shared-memory"};
|
||||||
|
auto sharedMem = new QSharedMemory {sharedMemoryKey, this};
|
||||||
if (m_isFirstInstance)
|
if (m_isFirstInstance)
|
||||||
{
|
{
|
||||||
// First instance creates shared memory and store PID
|
// First instance creates shared memory and store PID
|
||||||
@@ -79,8 +82,3 @@ bool ApplicationInstanceManager::sendMessage(const QString &message, const int t
|
|||||||
{
|
{
|
||||||
return m_peer->sendMessage(message, timeout);
|
return m_peer->sendMessage(message, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ApplicationInstanceManager::appId() const
|
|
||||||
{
|
|
||||||
return m_peer->applicationId();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,16 +32,15 @@
|
|||||||
|
|
||||||
class QtLocalPeer;
|
class QtLocalPeer;
|
||||||
|
|
||||||
class ApplicationInstanceManager : public QObject
|
class ApplicationInstanceManager final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(ApplicationInstanceManager)
|
Q_DISABLE_COPY_MOVE(ApplicationInstanceManager)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ApplicationInstanceManager(const QString &appId, QObject *parent = nullptr);
|
explicit ApplicationInstanceManager(const QString &instancePath, QObject *parent = nullptr);
|
||||||
|
|
||||||
bool isFirstInstance() const;
|
bool isFirstInstance() const;
|
||||||
QString appId() const;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool sendMessage(const QString &message, int timeout = 5000);
|
bool sendMessage(const QString &message, int timeout = 5000);
|
||||||
|
|||||||
@@ -526,55 +526,55 @@ QString makeUsage(const QString &prgName)
|
|||||||
QTextStream stream(&text, QIODevice::WriteOnly);
|
QTextStream stream(&text, QIODevice::WriteOnly);
|
||||||
QString indentation = QString(USAGE_INDENTATION, ' ');
|
QString indentation = QString(USAGE_INDENTATION, ' ');
|
||||||
|
|
||||||
stream << QObject::tr("Usage:") << '\n';
|
stream << QObject::tr("Usage:") << '\n'
|
||||||
stream << indentation << prgName << QLatin1String(" [options] [(<filename> | <url>)...]") << '\n';
|
<< indentation << prgName << QLatin1String(" [options] [(<filename> | <url>)...]") << '\n'
|
||||||
|
|
||||||
stream << QObject::tr("Options:") << '\n';
|
<< QObject::tr("Options:") << '\n'
|
||||||
#if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
|
#if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
|
||||||
stream << SHOW_VERSION_OPTION.usage() << wrapText(QObject::tr("Display program version and exit")) << '\n';
|
<< SHOW_VERSION_OPTION.usage() << wrapText(QObject::tr("Display program version and exit")) << '\n'
|
||||||
#endif
|
#endif
|
||||||
stream << SHOW_HELP_OPTION.usage() << wrapText(QObject::tr("Display this help message and exit")) << '\n';
|
<< SHOW_HELP_OPTION.usage() << wrapText(QObject::tr("Display this help message and exit")) << '\n'
|
||||||
stream << WEBUI_PORT_OPTION.usage(QObject::tr("port"))
|
<< WEBUI_PORT_OPTION.usage(QObject::tr("port"))
|
||||||
<< wrapText(QObject::tr("Change the Web UI port"))
|
<< wrapText(QObject::tr("Change the Web UI port"))
|
||||||
<< '\n';
|
<< '\n'
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
stream << NO_SPLASH_OPTION.usage() << wrapText(QObject::tr("Disable splash screen")) << '\n';
|
<< NO_SPLASH_OPTION.usage() << wrapText(QObject::tr("Disable splash screen")) << '\n'
|
||||||
#elif !defined(Q_OS_WIN)
|
#elif !defined(Q_OS_WIN)
|
||||||
stream << DAEMON_OPTION.usage() << wrapText(QObject::tr("Run in daemon-mode (background)")) << '\n';
|
<< DAEMON_OPTION.usage() << wrapText(QObject::tr("Run in daemon-mode (background)")) << '\n'
|
||||||
#endif
|
#endif
|
||||||
//: Use appropriate short form or abbreviation of "directory"
|
//: Use appropriate short form or abbreviation of "directory"
|
||||||
stream << PROFILE_OPTION.usage(QObject::tr("dir"))
|
<< PROFILE_OPTION.usage(QObject::tr("dir"))
|
||||||
<< wrapText(QObject::tr("Store configuration files in <dir>")) << '\n';
|
<< wrapText(QObject::tr("Store configuration files in <dir>")) << '\n'
|
||||||
stream << CONFIGURATION_OPTION.usage(QObject::tr("name"))
|
<< CONFIGURATION_OPTION.usage(QObject::tr("name"))
|
||||||
<< wrapText(QObject::tr("Store configuration files in directories qBittorrent_<name>")) << '\n';
|
<< wrapText(QObject::tr("Store configuration files in directories qBittorrent_<name>")) << '\n'
|
||||||
stream << RELATIVE_FASTRESUME.usage()
|
<< RELATIVE_FASTRESUME.usage()
|
||||||
<< wrapText(QObject::tr("Hack into libtorrent fastresume files and make file paths relative "
|
<< wrapText(QObject::tr("Hack into libtorrent fastresume files and make file paths relative "
|
||||||
"to the profile directory")) << '\n';
|
"to the profile directory")) << '\n'
|
||||||
stream << Option::padUsageText(QObject::tr("files or URLs"))
|
<< Option::padUsageText(QObject::tr("files or URLs"))
|
||||||
<< wrapText(QObject::tr("Download the torrents passed by the user")) << '\n'
|
<< wrapText(QObject::tr("Download the torrents passed by the user")) << '\n'
|
||||||
<< '\n';
|
<< '\n'
|
||||||
|
|
||||||
stream << wrapText(QObject::tr("Options when adding new torrents:"), 0) << '\n';
|
<< wrapText(QObject::tr("Options when adding new torrents:"), 0) << '\n'
|
||||||
stream << SAVE_PATH_OPTION.usage(QObject::tr("path")) << wrapText(QObject::tr("Torrent save path")) << '\n';
|
<< SAVE_PATH_OPTION.usage(QObject::tr("path")) << wrapText(QObject::tr("Torrent save path")) << '\n'
|
||||||
stream << PAUSED_OPTION.usage() << wrapText(QObject::tr("Add torrents as started or paused")) << '\n';
|
<< PAUSED_OPTION.usage() << wrapText(QObject::tr("Add torrents as started or paused")) << '\n'
|
||||||
stream << SKIP_HASH_CHECK_OPTION.usage() << wrapText(QObject::tr("Skip hash check")) << '\n';
|
<< SKIP_HASH_CHECK_OPTION.usage() << wrapText(QObject::tr("Skip hash check")) << '\n'
|
||||||
stream << CATEGORY_OPTION.usage(QObject::tr("name"))
|
<< CATEGORY_OPTION.usage(QObject::tr("name"))
|
||||||
<< wrapText(QObject::tr("Assign torrents to category. If the category doesn't exist, it will be "
|
<< wrapText(QObject::tr("Assign torrents to category. If the category doesn't exist, it will be "
|
||||||
"created.")) << '\n';
|
"created.")) << '\n'
|
||||||
stream << SEQUENTIAL_OPTION.usage() << wrapText(QObject::tr("Download files in sequential order")) << '\n';
|
<< SEQUENTIAL_OPTION.usage() << wrapText(QObject::tr("Download files in sequential order")) << '\n'
|
||||||
stream << FIRST_AND_LAST_OPTION.usage()
|
<< FIRST_AND_LAST_OPTION.usage()
|
||||||
<< wrapText(QObject::tr("Download first and last pieces first")) << '\n';
|
<< wrapText(QObject::tr("Download first and last pieces first")) << '\n'
|
||||||
stream << SKIP_DIALOG_OPTION.usage()
|
<< SKIP_DIALOG_OPTION.usage()
|
||||||
<< wrapText(QObject::tr("Specify whether the \"Add New Torrent\" dialog opens when adding a "
|
<< wrapText(QObject::tr("Specify whether the \"Add New Torrent\" dialog opens when adding a "
|
||||||
"torrent.")) << '\n';
|
"torrent.")) << '\n'
|
||||||
stream << '\n';
|
<< '\n'
|
||||||
|
|
||||||
stream << wrapText(QObject::tr("Option values may be supplied via environment variables. For option named "
|
<< wrapText(QObject::tr("Option values may be supplied via environment variables. For option named "
|
||||||
"'parameter-name', environment variable name is 'QBT_PARAMETER_NAME' (in upper "
|
"'parameter-name', environment variable name is 'QBT_PARAMETER_NAME' (in upper "
|
||||||
"case, '-' replaced with '_'). To pass flag values, set the variable to '1' or "
|
"case, '-' replaced with '_'). To pass flag values, set the variable to '1' or "
|
||||||
"'TRUE'. For example, to disable the splash screen: "), 0) << "\n"
|
"'TRUE'. For example, to disable the splash screen: "), 0) << "\n"
|
||||||
<< QLatin1String("QBT_NO_SPLASH=1 ") << prgName << '\n'
|
<< QLatin1String("QBT_NO_SPLASH=1 ") << prgName << '\n'
|
||||||
<< wrapText(QObject::tr("Command line parameters take precedence over environment variables"), 0) << '\n';
|
<< wrapText(QObject::tr("Command line parameters take precedence over environment variables"), 0) << '\n';
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ void FileLogger::openLogFile()
|
|||||||
{
|
{
|
||||||
if (!m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)
|
if (!m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)
|
||||||
|| !m_logFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner))
|
|| !m_logFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner))
|
||||||
{
|
{
|
||||||
m_logFile.close();
|
m_logFile.close();
|
||||||
LogMsg(tr("An error occurred while trying to open the log file. Logging to file is disabled."), Log::CRITICAL);
|
LogMsg(tr("An error occurred while trying to open the log file. Logging to file is disabled."), Log::CRITICAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ int main(int argc, char *argv[])
|
|||||||
// We must save it here because QApplication constructor may change it
|
// We must save it here because QApplication constructor may change it
|
||||||
bool isOneArg = (argc == 2);
|
bool isOneArg = (argc == 2);
|
||||||
|
|
||||||
#if !defined(DISABLE_GUI)
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && !defined(DISABLE_GUI)
|
||||||
// Attribute Qt::AA_EnableHighDpiScaling must be set before QCoreApplication is created
|
// Attribute Qt::AA_EnableHighDpiScaling must be set before QCoreApplication is created
|
||||||
if (qgetenv("QT_ENABLE_HIGHDPI_SCALING").isEmpty() && qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR").isEmpty())
|
if (qgetenv("QT_ENABLE_HIGHDPI_SCALING").isEmpty() && qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR").isEmpty())
|
||||||
Application::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
Application::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||||
@@ -188,7 +188,6 @@ int main(int argc, char *argv[])
|
|||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
if (!userAgreesWithLegalNotice())
|
if (!userAgreesWithLegalNotice())
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
if (_isatty(_fileno(stdin))
|
if (_isatty(_fileno(stdin))
|
||||||
&& _isatty(_fileno(stdout))
|
&& _isatty(_fileno(stdout))
|
||||||
@@ -201,6 +200,8 @@ int main(int argc, char *argv[])
|
|||||||
&& !userAgreesWithLegalNotice())
|
&& !userAgreesWithLegalNotice())
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
setCurrentMigrationVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if qBittorrent is already running for this user
|
// Check if qBittorrent is already running for this user
|
||||||
|
|||||||
@@ -68,20 +68,16 @@
|
|||||||
|
|
||||||
#include "qtlocalpeer.h"
|
#include "qtlocalpeer.h"
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX)
|
#include <QtGlobal>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
#if defined(Q_OS_WIN)
|
||||||
#include <unistd.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QDir>
|
#include <QFileInfo>
|
||||||
#include <QLocalServer>
|
#include <QLocalServer>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QRegularExpression>
|
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
|
||||||
|
|
||||||
namespace QtLP_Private
|
namespace QtLP_Private
|
||||||
{
|
{
|
||||||
@@ -94,75 +90,49 @@ namespace QtLP_Private
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* QtLocalPeer::ack = "ack";
|
const char ACK[] = "ack";
|
||||||
|
|
||||||
QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId)
|
QtLocalPeer::QtLocalPeer(const QString &path, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, id(appId)
|
, m_socketName(path + QLatin1String("/ipc-socket"))
|
||||||
|
, m_server(new QLocalServer(this))
|
||||||
{
|
{
|
||||||
QString prefix = id;
|
m_server->setSocketOptions(QLocalServer::UserAccessOption);
|
||||||
if (id.isEmpty())
|
|
||||||
{
|
|
||||||
id = QCoreApplication::applicationFilePath();
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
id = id.toLower();
|
|
||||||
#endif
|
|
||||||
prefix = id.section(QLatin1Char('/'), -1);
|
|
||||||
}
|
|
||||||
prefix.remove(QRegularExpression("[^a-zA-Z]"));
|
|
||||||
prefix.truncate(6);
|
|
||||||
|
|
||||||
QByteArray idc = id.toUtf8();
|
m_lockFile.setFileName(path + QLatin1String("/lockfile"));
|
||||||
quint16 idNum = qChecksum(idc.constData(), idc.size());
|
m_lockFile.open(QIODevice::ReadWrite);
|
||||||
socketName = QLatin1String("qtsingleapp-") + prefix
|
|
||||||
+ QLatin1Char('-') + QString::number(idNum, 16);
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
DWORD sessionId = 0;
|
|
||||||
::ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
|
|
||||||
socketName += (QLatin1Char('-') + QString::number(sessionId, 16));
|
|
||||||
#else
|
|
||||||
socketName += (QLatin1Char('-') + QString::number(::getuid(), 16));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
server = new QLocalServer(this);
|
|
||||||
server->setSocketOptions(QLocalServer::UserAccessOption);
|
|
||||||
QString lockName = QDir(QDir::tempPath()).absolutePath()
|
|
||||||
+ QLatin1Char('/') + socketName
|
|
||||||
+ QLatin1String("-lockfile");
|
|
||||||
lockFile.setFileName(lockName);
|
|
||||||
lockFile.open(QIODevice::ReadWrite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtLocalPeer::~QtLocalPeer()
|
QtLocalPeer::~QtLocalPeer()
|
||||||
{
|
{
|
||||||
if (!isClient())
|
if (!isClient())
|
||||||
{
|
{
|
||||||
lockFile.unlock();
|
m_lockFile.unlock();
|
||||||
lockFile.remove();
|
m_lockFile.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtLocalPeer::isClient()
|
bool QtLocalPeer::isClient()
|
||||||
{
|
{
|
||||||
if (lockFile.isLocked())
|
if (m_lockFile.isLocked())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
|
if (!m_lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool res = server->listen(socketName);
|
bool res = m_server->listen(m_socketName);
|
||||||
#if defined(Q_OS_UNIX)
|
#if defined(Q_OS_UNIX)
|
||||||
// ### Workaround
|
// ### Workaround
|
||||||
if (!res && server->serverError() == QAbstractSocket::AddressInUseError)
|
if (!res && m_server->serverError() == QAbstractSocket::AddressInUseError)
|
||||||
{
|
{
|
||||||
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
|
QFile::remove(m_socketName);
|
||||||
res = server->listen(socketName);
|
res = m_server->listen(m_socketName);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!res)
|
if (!res)
|
||||||
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
|
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qUtf8Printable(m_server->errorString()));
|
||||||
connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection);
|
|
||||||
|
connect(m_server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +146,7 @@ bool QtLocalPeer::sendMessage(const QString &message, const int timeout)
|
|||||||
for(int i = 0; i < 2; i++)
|
for(int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
// Try twice, in case the other instance is just starting up
|
// Try twice, in case the other instance is just starting up
|
||||||
socket.connectToServer(socketName);
|
socket.connectToServer(m_socketName);
|
||||||
connOk = socket.waitForConnected(timeout/2);
|
connOk = socket.waitForConnected(timeout/2);
|
||||||
if (connOk || i)
|
if (connOk || i)
|
||||||
break;
|
break;
|
||||||
@@ -199,19 +169,14 @@ bool QtLocalPeer::sendMessage(const QString &message, const int timeout)
|
|||||||
{
|
{
|
||||||
res &= socket.waitForReadyRead(timeout); // wait for ack
|
res &= socket.waitForReadyRead(timeout); // wait for ack
|
||||||
if (res)
|
if (res)
|
||||||
res &= (socket.read(qstrlen(ack)) == ack);
|
res &= (socket.read(qstrlen(ACK)) == ACK);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtLocalPeer::applicationId() const
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtLocalPeer::receiveConnection()
|
void QtLocalPeer::receiveConnection()
|
||||||
{
|
{
|
||||||
QLocalSocket* socket = server->nextPendingConnection();
|
QLocalSocket *socket = m_server->nextPendingConnection();
|
||||||
if (!socket)
|
if (!socket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -255,7 +220,7 @@ void QtLocalPeer::receiveConnection()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString message(QString::fromUtf8(uMsg));
|
QString message(QString::fromUtf8(uMsg));
|
||||||
socket->write(ack, qstrlen(ack));
|
socket->write(ACK, qstrlen(ACK));
|
||||||
socket->waitForBytesWritten(1000);
|
socket->waitForBytesWritten(1000);
|
||||||
socket->waitForDisconnected(1000); // make sure client reads ack
|
socket->waitForDisconnected(1000); // make sure client reads ack
|
||||||
delete socket;
|
delete socket;
|
||||||
|
|||||||
@@ -68,34 +68,32 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "qtlockedfile.h"
|
#include "qtlockedfile.h"
|
||||||
|
|
||||||
class QLocalServer;
|
class QLocalServer;
|
||||||
|
|
||||||
class QtLocalPeer : public QObject
|
class QtLocalPeer final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY_MOVE(QtLocalPeer)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QtLocalPeer(QObject *parent = nullptr, const QString &appId = QString());
|
QtLocalPeer(const QString &path, QObject *parent = nullptr);
|
||||||
~QtLocalPeer() override;
|
~QtLocalPeer() override;
|
||||||
|
|
||||||
bool isClient();
|
bool isClient();
|
||||||
bool sendMessage(const QString &message, int timeout);
|
bool sendMessage(const QString &message, int timeout);
|
||||||
QString applicationId() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void messageReceived(const QString &message);
|
void messageReceived(const QString &message);
|
||||||
|
|
||||||
protected slots:
|
private slots:
|
||||||
void receiveConnection();
|
void receiveConnection();
|
||||||
|
|
||||||
protected:
|
|
||||||
QString id;
|
|
||||||
QString socketName;
|
|
||||||
QLocalServer *server = nullptr;
|
|
||||||
QtLP_Private::QtLockedFile lockFile;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const char* ack;
|
QString m_socketName;
|
||||||
|
QLocalServer *m_server = nullptr;
|
||||||
|
QtLP_Private::QtLockedFile m_lockFile;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -108,11 +108,7 @@
|
|||||||
|
|
||||||
\sa QFile::QFile()
|
\sa QFile::QFile()
|
||||||
*/
|
*/
|
||||||
QtLockedFile::QtLockedFile()
|
QtLockedFile::QtLockedFile() = default;
|
||||||
: QFile()
|
|
||||||
{
|
|
||||||
m_lock_mode = NoLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs an unlocked QtLockedFile object with file \a name. This
|
Constructs an unlocked QtLockedFile object with file \a name. This
|
||||||
@@ -124,7 +120,6 @@ QtLockedFile::QtLockedFile()
|
|||||||
QtLockedFile::QtLockedFile(const QString &name)
|
QtLockedFile::QtLockedFile(const QString &name)
|
||||||
: QFile(name)
|
: QFile(name)
|
||||||
{
|
{
|
||||||
m_lock_mode = NoLock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -142,7 +137,8 @@ QtLockedFile::QtLockedFile(const QString &name)
|
|||||||
*/
|
*/
|
||||||
bool QtLockedFile::open(const OpenMode mode)
|
bool QtLockedFile::open(const OpenMode mode)
|
||||||
{
|
{
|
||||||
if (mode & QIODevice::Truncate) {
|
if (mode & QIODevice::Truncate)
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::open(): Truncate mode not allowed.");
|
qWarning("QtLockedFile::open(): Truncate mode not allowed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -157,7 +153,7 @@ bool QtLockedFile::open(const OpenMode mode)
|
|||||||
*/
|
*/
|
||||||
bool QtLockedFile::isLocked() const
|
bool QtLockedFile::isLocked() const
|
||||||
{
|
{
|
||||||
return m_lock_mode != NoLock;
|
return m_lockMode != NoLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -168,7 +164,7 @@ bool QtLockedFile::isLocked() const
|
|||||||
*/
|
*/
|
||||||
QtLockedFile::LockMode QtLockedFile::lockMode() const
|
QtLockedFile::LockMode QtLockedFile::lockMode() const
|
||||||
{
|
{
|
||||||
return m_lock_mode;
|
return m_lockMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -100,14 +101,14 @@ namespace QtLP_Private
|
|||||||
private:
|
private:
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
Qt::HANDLE getMutexHandle(int idx, bool doCreate);
|
Qt::HANDLE getMutexHandle(int idx, bool doCreate);
|
||||||
bool waitMutex(Qt::HANDLE mutex, bool doBlock);
|
bool waitMutex(Qt::HANDLE mutex, bool doBlock) const;
|
||||||
|
|
||||||
Qt::HANDLE wmutex = nullptr;
|
Qt::HANDLE m_writeMutex = nullptr;
|
||||||
Qt::HANDLE rmutex = nullptr;
|
Qt::HANDLE m_readMutex = nullptr;
|
||||||
QVector<Qt::HANDLE> rmutexes;
|
QVector<Qt::HANDLE> m_readMutexes;
|
||||||
QString mutexname;
|
QString m_mutexName;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LockMode m_lock_mode;
|
LockMode m_lockMode = NoLock;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,9 +73,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
bool QtLockedFile::lock(LockMode mode, bool block)
|
bool QtLockedFile::lock(const LockMode mode, const bool block)
|
||||||
{
|
{
|
||||||
if (!isOpen()) {
|
if (!isOpen())
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::lock(): file is not opened");
|
qWarning("QtLockedFile::lock(): file is not opened");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -83,10 +84,10 @@ bool QtLockedFile::lock(LockMode mode, bool block)
|
|||||||
if (mode == NoLock)
|
if (mode == NoLock)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (mode == m_lock_mode)
|
if (mode == m_lockMode)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (m_lock_mode != NoLock)
|
if (m_lockMode != NoLock)
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
struct flock fl;
|
struct flock fl;
|
||||||
@@ -97,19 +98,21 @@ bool QtLockedFile::lock(LockMode mode, bool block)
|
|||||||
int cmd = block ? F_SETLKW : F_SETLK;
|
int cmd = block ? F_SETLKW : F_SETLK;
|
||||||
int ret = fcntl(handle(), cmd, &fl);
|
int ret = fcntl(handle(), cmd, &fl);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1)
|
||||||
|
{
|
||||||
if (errno != EINTR && errno != EAGAIN)
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lock_mode = mode;
|
m_lockMode = mode;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtLockedFile::unlock()
|
bool QtLockedFile::unlock()
|
||||||
{
|
{
|
||||||
if (!isOpen()) {
|
if (!isOpen())
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::unlock(): file is not opened");
|
qWarning("QtLockedFile::unlock(): file is not opened");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -124,12 +127,13 @@ bool QtLockedFile::unlock()
|
|||||||
fl.l_type = F_UNLCK;
|
fl.l_type = F_UNLCK;
|
||||||
int ret = fcntl(handle(), F_SETLKW, &fl);
|
int ret = fcntl(handle(), F_SETLKW, &fl);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1)
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lock_mode = NoLock;
|
m_lockMode = NoLock;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,64 +70,73 @@
|
|||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
#define MUTEX_PREFIX "QtLockedFile mutex "
|
#include "base/global.h"
|
||||||
|
|
||||||
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
|
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
|
||||||
#define MAX_READERS MAXIMUM_WAIT_OBJECTS
|
const int MAX_READERS = MAXIMUM_WAIT_OBJECTS;
|
||||||
|
|
||||||
#define QT_WA(unicode, ansi) unicode
|
Qt::HANDLE QtLockedFile::getMutexHandle(const int idx, const bool doCreate)
|
||||||
|
|
||||||
Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
|
|
||||||
{
|
{
|
||||||
if (mutexname.isEmpty()) {
|
if (m_mutexName.isEmpty())
|
||||||
|
{
|
||||||
QFileInfo fi(*this);
|
QFileInfo fi(*this);
|
||||||
mutexname = QString::fromLatin1(MUTEX_PREFIX)
|
m_mutexName = QString::fromLatin1("QtLockedFile mutex ") + fi.absoluteFilePath().toLower();
|
||||||
+ fi.absoluteFilePath().toLower();
|
|
||||||
}
|
}
|
||||||
QString mname(mutexname);
|
|
||||||
|
QString mname = m_mutexName;
|
||||||
if (idx >= 0)
|
if (idx >= 0)
|
||||||
mname += QString::number(idx);
|
mname += QString::number(idx);
|
||||||
|
|
||||||
Qt::HANDLE mutex;
|
if (doCreate)
|
||||||
if (doCreate) {
|
{
|
||||||
QT_WA( { mutex = CreateMutexW(NULL, FALSE, reinterpret_cast<const TCHAR *>(mname.utf16())); },
|
const Qt::HANDLE mutex = ::CreateMutexW(NULL, FALSE, reinterpret_cast<const TCHAR *>(mname.utf16()));
|
||||||
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
|
if (!mutex)
|
||||||
if (!mutex) {
|
{
|
||||||
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mutex;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, reinterpret_cast<const TCHAR *>(mname.utf16())); },
|
{
|
||||||
{ mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
|
const Qt::HANDLE mutex = ::OpenMutexW((SYNCHRONIZE | MUTEX_MODIFY_STATE), FALSE, reinterpret_cast<const TCHAR *>(mname.utf16()));
|
||||||
if (!mutex) {
|
if (!mutex)
|
||||||
|
{
|
||||||
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||||
qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
|
qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mutex;
|
||||||
}
|
}
|
||||||
return mutex;
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
|
bool QtLockedFile::waitMutex(const Qt::HANDLE mutex, const bool doBlock) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(mutex);
|
Q_ASSERT(mutex);
|
||||||
DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
|
|
||||||
switch (res) {
|
const DWORD res = ::WaitForSingleObject(mutex, (doBlock ? INFINITE : 0));
|
||||||
|
switch (res)
|
||||||
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
case WAIT_ABANDONED:
|
case WAIT_ABANDONED:
|
||||||
return true;
|
return true;
|
||||||
break;
|
|
||||||
case WAIT_TIMEOUT:
|
case WAIT_TIMEOUT:
|
||||||
break;
|
return false;
|
||||||
default:
|
default:
|
||||||
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
|
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtLockedFile::lock(LockMode mode, bool block)
|
bool QtLockedFile::lock(const LockMode mode, const bool block)
|
||||||
{
|
{
|
||||||
if (!isOpen()) {
|
if (!isOpen())
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::lock(): file is not opened");
|
qWarning("QtLockedFile::lock(): file is not opened");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -135,72 +144,85 @@ bool QtLockedFile::lock(LockMode mode, bool block)
|
|||||||
if (mode == NoLock)
|
if (mode == NoLock)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (mode == m_lock_mode)
|
if (mode == m_lockMode)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (m_lock_mode != NoLock)
|
if (m_lockMode != NoLock)
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
|
if (!m_writeMutex && !(m_writeMutex = getMutexHandle(-1, true)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!waitMutex(wmutex, block))
|
if (!waitMutex(m_writeMutex, block))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (mode == ReadLock) {
|
if (mode == ReadLock)
|
||||||
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (; idx < MAX_READERS; idx++) {
|
for (; idx < MAX_READERS; ++idx)
|
||||||
rmutex = getMutexHandle(idx, false);
|
{
|
||||||
if (!rmutex || waitMutex(rmutex, false))
|
m_readMutex = getMutexHandle(idx, false);
|
||||||
|
if (!m_readMutex || waitMutex(m_readMutex, false))
|
||||||
break;
|
break;
|
||||||
CloseHandle(rmutex);
|
::CloseHandle(m_readMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (idx >= MAX_READERS) {
|
if (idx >= MAX_READERS)
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::lock(): too many readers");
|
qWarning("QtLockedFile::lock(): too many readers");
|
||||||
rmutex = 0;
|
m_readMutex = nullptr;
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
else if (!rmutex) {
|
else if (!m_readMutex)
|
||||||
rmutex = getMutexHandle(idx, true);
|
{
|
||||||
if (!rmutex || !waitMutex(rmutex, false))
|
m_readMutex = getMutexHandle(idx, true);
|
||||||
|
if (!m_readMutex || !waitMutex(m_readMutex, false))
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
if (!ok && rmutex) {
|
|
||||||
CloseHandle(rmutex);
|
if (!ok && m_readMutex)
|
||||||
rmutex = 0;
|
{
|
||||||
|
::CloseHandle(m_readMutex);
|
||||||
|
m_readMutex = nullptr;
|
||||||
}
|
}
|
||||||
ReleaseMutex(wmutex);
|
|
||||||
|
::ReleaseMutex(m_writeMutex);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
Q_ASSERT(rmutexes.isEmpty());
|
{
|
||||||
for (int i = 0; i < MAX_READERS; i++) {
|
Q_ASSERT(m_readMutexes.isEmpty());
|
||||||
Qt::HANDLE mutex = getMutexHandle(i, false);
|
for (int i = 0; i < MAX_READERS; ++i)
|
||||||
|
{
|
||||||
|
const Qt::HANDLE mutex = getMutexHandle(i, false);
|
||||||
if (mutex)
|
if (mutex)
|
||||||
rmutexes.append(mutex);
|
m_readMutexes.append(mutex);
|
||||||
}
|
}
|
||||||
if (rmutexes.size()) {
|
if (m_readMutexes.size())
|
||||||
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
|
{
|
||||||
TRUE, block ? INFINITE : 0);
|
const DWORD res = ::WaitForMultipleObjects(m_readMutexes.size(), m_readMutexes.constData(),
|
||||||
if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
|
TRUE, (block ? INFINITE : 0));
|
||||||
|
if ((res != WAIT_OBJECT_0) && (res != WAIT_ABANDONED))
|
||||||
|
{
|
||||||
if (res != WAIT_TIMEOUT)
|
if (res != WAIT_TIMEOUT)
|
||||||
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
|
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
|
||||||
m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
|
m_lockMode = WriteLock; // trick unlock() to clean up - semiyucky
|
||||||
unlock();
|
unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lock_mode = mode;
|
m_lockMode = mode;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtLockedFile::unlock()
|
bool QtLockedFile::unlock()
|
||||||
{
|
{
|
||||||
if (!isOpen()) {
|
if (!isOpen())
|
||||||
|
{
|
||||||
qWarning("QtLockedFile::unlock(): file is not opened");
|
qWarning("QtLockedFile::unlock(): file is not opened");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -208,21 +230,24 @@ bool QtLockedFile::unlock()
|
|||||||
if (!isLocked())
|
if (!isLocked())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (m_lock_mode == ReadLock) {
|
if (m_lockMode == ReadLock)
|
||||||
ReleaseMutex(rmutex);
|
{
|
||||||
CloseHandle(rmutex);
|
::ReleaseMutex(m_readMutex);
|
||||||
rmutex = 0;
|
::CloseHandle(m_readMutex);
|
||||||
|
m_readMutex = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
foreach(Qt::HANDLE mutex, rmutexes) {
|
{
|
||||||
ReleaseMutex(mutex);
|
for (const Qt::HANDLE &mutex : asConst(m_readMutexes))
|
||||||
CloseHandle(mutex);
|
{
|
||||||
|
::ReleaseMutex(mutex);
|
||||||
|
::CloseHandle(mutex);
|
||||||
}
|
}
|
||||||
rmutexes.clear();
|
m_readMutexes.clear();
|
||||||
ReleaseMutex(wmutex);
|
::ReleaseMutex(m_writeMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lock_mode = QtLockedFile::NoLock;
|
m_lockMode = QtLockedFile::NoLock;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +255,6 @@ QtLockedFile::~QtLockedFile()
|
|||||||
{
|
{
|
||||||
if (isOpen())
|
if (isOpen())
|
||||||
unlock();
|
unlock();
|
||||||
if (wmutex)
|
if (m_writeMutex)
|
||||||
CloseHandle(wmutex);
|
::CloseHandle(m_writeMutex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,19 +28,24 @@
|
|||||||
|
|
||||||
#include "upgrade.h"
|
#include "upgrade.h"
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
#include "base/bittorrent/torrentcontentlayout.h"
|
#include "base/bittorrent/torrentcontentlayout.h"
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
|
#include "base/net/proxyconfigurationmanager.h"
|
||||||
|
#include "base/preferences.h"
|
||||||
#include "base/profile.h"
|
#include "base/profile.h"
|
||||||
#include "base/settingsstorage.h"
|
#include "base/settingsstorage.h"
|
||||||
|
#include "base/settingvalue.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
|
#include "base/utils/io.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const int MIGRATION_VERSION = 3;
|
||||||
|
const char MIGRATION_VERSION_KEY[] = "Meta/MigrationVersion";
|
||||||
|
|
||||||
void exportWebUIHttpsFiles()
|
void exportWebUIHttpsFiles()
|
||||||
{
|
{
|
||||||
const auto migrate = [](const QString &oldKey, const QString &newKey, const QString &savePath)
|
const auto migrate = [](const QString &oldKey, const QString &newKey, const QString &savePath)
|
||||||
@@ -53,17 +58,10 @@ namespace
|
|||||||
if (!newData.isEmpty() || oldData.isEmpty())
|
if (!newData.isEmpty() || oldData.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QFile file(savePath);
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(savePath, oldData);
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
if (!result)
|
||||||
{
|
{
|
||||||
LogMsg(errorMsgFormat.arg(savePath, file.errorString()) , Log::WARNING);
|
LogMsg(errorMsgFormat.arg(savePath, result.error()) , Log::WARNING);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (file.write(oldData) != oldData.size())
|
|
||||||
{
|
|
||||||
file.close();
|
|
||||||
Utils::Fs::forceRemove(savePath);
|
|
||||||
LogMsg(errorMsgFormat.arg(savePath, QLatin1String("Write incomplete.")) , Log::WARNING);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,10 +75,10 @@ namespace
|
|||||||
const QString configPath {specialFolderLocation(SpecialFolder::Config)};
|
const QString configPath {specialFolderLocation(SpecialFolder::Config)};
|
||||||
migrate(QLatin1String("Preferences/WebUI/HTTPS/Certificate")
|
migrate(QLatin1String("Preferences/WebUI/HTTPS/Certificate")
|
||||||
, QLatin1String("Preferences/WebUI/HTTPS/CertificatePath")
|
, QLatin1String("Preferences/WebUI/HTTPS/CertificatePath")
|
||||||
, Utils::Fs::toNativePath(configPath + QLatin1String("WebUICertificate.crt")));
|
, Utils::Fs::toNativePath(configPath + QLatin1String("/WebUICertificate.crt")));
|
||||||
migrate(QLatin1String("Preferences/WebUI/HTTPS/Key")
|
migrate(QLatin1String("Preferences/WebUI/HTTPS/Key")
|
||||||
, QLatin1String("Preferences/WebUI/HTTPS/KeyPath")
|
, QLatin1String("Preferences/WebUI/HTTPS/KeyPath")
|
||||||
, Utils::Fs::toNativePath(configPath + QLatin1String("WebUIPrivateKey.pem")));
|
, Utils::Fs::toNativePath(configPath + QLatin1String("/WebUIPrivateKey.pem")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void upgradeTorrentContentLayout()
|
void upgradeTorrentContentLayout()
|
||||||
@@ -117,16 +115,293 @@ namespace
|
|||||||
settingsStorage->removeValue(oldKey);
|
settingsStorage->removeValue(oldKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void upgradeSchedulerDaysSettings()
|
||||||
|
{
|
||||||
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
|
const auto key = QString::fromLatin1("Preferences/Scheduler/days");
|
||||||
|
const auto value = settingsStorage->loadValue<QString>(key);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const auto number = value.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
switch (number)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::EveryDay);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Weekday);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Weekend);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Monday);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Tuesday);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Wednesday);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Thursday);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Friday);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Saturday);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
settingsStorage->storeValue(key, Scheduler::Days::Sunday);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogMsg(QObject::tr("Invalid value found in configuration file, reverting it to default. Key: \"%1\". Invalid value: \"%2\".")
|
||||||
|
.arg(key, QString::number(number)), Log::WARNING);
|
||||||
|
settingsStorage->removeValue(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void upgradeDNSServiceSettings()
|
||||||
|
{
|
||||||
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
|
const auto key = QString::fromLatin1("Preferences/DynDNS/Service");
|
||||||
|
const auto value = settingsStorage->loadValue<QString>(key);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const auto number = value.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
switch (number)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
settingsStorage->storeValue(key, DNS::Service::None);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
settingsStorage->storeValue(key, DNS::Service::DynDNS);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
settingsStorage->storeValue(key, DNS::Service::NoIP);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogMsg(QObject::tr("Invalid value found in configuration file, reverting it to default. Key: \"%1\". Invalid value: \"%2\".")
|
||||||
|
.arg(key, QString::number(number)), Log::WARNING);
|
||||||
|
settingsStorage->removeValue(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void upgradeTrayIconStyleSettings()
|
||||||
|
{
|
||||||
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
|
const auto key = QString::fromLatin1("Preferences/Advanced/TrayIconStyle");
|
||||||
|
const auto value = settingsStorage->loadValue<QString>(key);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const auto number = value.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
switch (number)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
settingsStorage->storeValue(key, TrayIcon::Style::Normal);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
settingsStorage->storeValue(key, TrayIcon::Style::MonoDark);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
settingsStorage->storeValue(key, TrayIcon::Style::MonoLight);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogMsg(QObject::tr("Invalid value found in configuration file, reverting it to default. Key: \"%1\". Invalid value: \"%2\".")
|
||||||
|
.arg(key, QString::number(number)), Log::WARNING);
|
||||||
|
settingsStorage->removeValue(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void migrateSettingKeys()
|
||||||
|
{
|
||||||
|
struct KeyMapping
|
||||||
|
{
|
||||||
|
QString newKey;
|
||||||
|
QString oldKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
const KeyMapping mappings[] =
|
||||||
|
{
|
||||||
|
{"AddNewTorrentDialog/Enabled", "Preferences/Downloads/NewAdditionDialog"},
|
||||||
|
{"AddNewTorrentDialog/Expanded", "AddNewTorrentDialog/expanded"},
|
||||||
|
{"AddNewTorrentDialog/Position", "AddNewTorrentDialog/y"},
|
||||||
|
{"AddNewTorrentDialog/SavePathHistory", "TorrentAdditionDlg/save_path_history"},
|
||||||
|
{"AddNewTorrentDialog/TopLevel", "Preferences/Downloads/NewAdditionDialogFront"},
|
||||||
|
{"AddNewTorrentDialog/TreeHeaderState", "AddNewTorrentDialog/qt5/treeHeaderState"},
|
||||||
|
{"AddNewTorrentDialog/Width", "AddNewTorrentDialog/width"},
|
||||||
|
{"BitTorrent/Session/AddExtensionToIncompleteFiles", "Preferences/Downloads/UseIncompleteExtension"},
|
||||||
|
{"BitTorrent/Session/AdditionalTrackers", "Preferences/Bittorrent/TrackersList"},
|
||||||
|
{"BitTorrent/Session/AddTorrentPaused", "Preferences/Downloads/StartInPause"},
|
||||||
|
{"BitTorrent/Session/AddTrackersEnabled", "Preferences/Bittorrent/AddTrackers"},
|
||||||
|
{"BitTorrent/Session/AlternativeGlobalDLSpeedLimit", "Preferences/Connection/GlobalDLLimitAlt"},
|
||||||
|
{"BitTorrent/Session/AlternativeGlobalUPSpeedLimit", "Preferences/Connection/GlobalUPLimitAlt"},
|
||||||
|
{"BitTorrent/Session/AnnounceIP", "Preferences/Connection/InetAddress"},
|
||||||
|
{"BitTorrent/Session/AnnounceToAllTrackers", "Preferences/Advanced/AnnounceToAllTrackers"},
|
||||||
|
{"BitTorrent/Session/AnonymousModeEnabled", "Preferences/Advanced/AnonymousMode"},
|
||||||
|
{"BitTorrent/Session/BandwidthSchedulerEnabled", "Preferences/Scheduler/Enabled"},
|
||||||
|
{"BitTorrent/Session/DefaultSavePath", "Preferences/Downloads/SavePath"},
|
||||||
|
{"BitTorrent/Session/DHTEnabled", "Preferences/Bittorrent/DHT"},
|
||||||
|
{"BitTorrent/Session/DiskCacheSize", "Preferences/Downloads/DiskWriteCacheSize"},
|
||||||
|
{"BitTorrent/Session/DiskCacheTTL", "Preferences/Downloads/DiskWriteCacheTTL"},
|
||||||
|
{"BitTorrent/Session/Encryption", "Preferences/Bittorrent/Encryption"},
|
||||||
|
{"BitTorrent/Session/FinishedTorrentExportDirectory", "Preferences/Downloads/FinishedTorrentExportDir"},
|
||||||
|
{"BitTorrent/Session/ForceProxy", "Preferences/Connection/ProxyForce"},
|
||||||
|
{"BitTorrent/Session/GlobalDLSpeedLimit", "Preferences/Connection/GlobalDLLimit"},
|
||||||
|
{"BitTorrent/Session/GlobalMaxRatio", "Preferences/Bittorrent/MaxRatio"},
|
||||||
|
{"BitTorrent/Session/GlobalUPSpeedLimit", "Preferences/Connection/GlobalUPLimit"},
|
||||||
|
{"BitTorrent/Session/IgnoreLimitsOnLAN", "Preferences/Advanced/IgnoreLimitsLAN"},
|
||||||
|
{"BitTorrent/Session/IgnoreSlowTorrentsForQueueing", "Preferences/Queueing/IgnoreSlowTorrents"},
|
||||||
|
{"BitTorrent/Session/IncludeOverheadInLimits", "Preferences/Advanced/IncludeOverhead"},
|
||||||
|
{"BitTorrent/Session/Interface", "Preferences/Connection/Interface"},
|
||||||
|
{"BitTorrent/Session/InterfaceAddress", "Preferences/Connection/InterfaceAddress"},
|
||||||
|
{"BitTorrent/Session/InterfaceName", "Preferences/Connection/InterfaceName"},
|
||||||
|
{"BitTorrent/Session/IPFilter", "Preferences/IPFilter/File"},
|
||||||
|
{"BitTorrent/Session/IPFilteringEnabled", "Preferences/IPFilter/Enabled"},
|
||||||
|
{"BitTorrent/Session/LSDEnabled", "Preferences/Bittorrent/LSD"},
|
||||||
|
{"BitTorrent/Session/MaxActiveDownloads", "Preferences/Queueing/MaxActiveDownloads"},
|
||||||
|
{"BitTorrent/Session/MaxActiveTorrents", "Preferences/Queueing/MaxActiveTorrents"},
|
||||||
|
{"BitTorrent/Session/MaxActiveUploads", "Preferences/Queueing/MaxActiveUploads"},
|
||||||
|
{"BitTorrent/Session/MaxConnections", "Preferences/Bittorrent/MaxConnecs"},
|
||||||
|
{"BitTorrent/Session/MaxConnectionsPerTorrent", "Preferences/Bittorrent/MaxConnecsPerTorrent"},
|
||||||
|
{"BitTorrent/Session/MaxHalfOpenConnections", "Preferences/Connection/MaxHalfOpenConnec"},
|
||||||
|
{"BitTorrent/Session/MaxRatioAction", "Preferences/Bittorrent/MaxRatioAction"},
|
||||||
|
{"BitTorrent/Session/MaxUploads", "Preferences/Bittorrent/MaxUploads"},
|
||||||
|
{"BitTorrent/Session/MaxUploadsPerTorrent", "Preferences/Bittorrent/MaxUploadsPerTorrent"},
|
||||||
|
{"BitTorrent/Session/OutgoingPortsMax", "Preferences/Advanced/OutgoingPortsMax"},
|
||||||
|
{"BitTorrent/Session/OutgoingPortsMin", "Preferences/Advanced/OutgoingPortsMin"},
|
||||||
|
{"BitTorrent/Session/PeXEnabled", "Preferences/Bittorrent/PeX"},
|
||||||
|
{"BitTorrent/Session/Port", "Preferences/Connection/PortRangeMin"},
|
||||||
|
{"BitTorrent/Session/Preallocation", "Preferences/Downloads/PreAllocation"},
|
||||||
|
{"BitTorrent/Session/ProxyPeerConnections", "Preferences/Connection/ProxyPeerConnections"},
|
||||||
|
{"BitTorrent/Session/QueueingSystemEnabled", "Preferences/Queueing/QueueingEnabled"},
|
||||||
|
{"BitTorrent/Session/RefreshInterval", "Preferences/General/RefreshInterval"},
|
||||||
|
{"BitTorrent/Session/SaveResumeDataInterval", "Preferences/Downloads/SaveResumeDataInterval"},
|
||||||
|
{"BitTorrent/Session/SuperSeedingEnabled", "Preferences/Advanced/SuperSeeding"},
|
||||||
|
{"BitTorrent/Session/TempPath", "Preferences/Downloads/TempPath"},
|
||||||
|
{"BitTorrent/Session/TempPathEnabled", "Preferences/Downloads/TempPathEnabled"},
|
||||||
|
{"BitTorrent/Session/TorrentExportDirectory", "Preferences/Downloads/TorrentExportDir"},
|
||||||
|
{"BitTorrent/Session/TrackerFilteringEnabled", "Preferences/IPFilter/FilterTracker"},
|
||||||
|
{"BitTorrent/Session/UseAlternativeGlobalSpeedLimit", "Preferences/Connection/alt_speeds_on"},
|
||||||
|
{"BitTorrent/Session/UseOSCache", "Preferences/Advanced/osCache"},
|
||||||
|
{"BitTorrent/Session/UseRandomPort", "Preferences/General/UseRandomPort"},
|
||||||
|
{"BitTorrent/Session/uTPEnabled", "Preferences/Bittorrent/uTP"},
|
||||||
|
{"BitTorrent/Session/uTPRateLimited", "Preferences/Bittorrent/uTP_rate_limited"},
|
||||||
|
{"BitTorrent/TrackerEnabled", "Preferences/Advanced/trackerEnabled"},
|
||||||
|
{"Network/PortForwardingEnabled", "Preferences/Connection/UPnP"},
|
||||||
|
{"Network/Proxy/Authentication", "Preferences/Connection/Proxy/Authentication"},
|
||||||
|
{"Network/Proxy/IP", "Preferences/Connection/Proxy/IP"},
|
||||||
|
{"Network/Proxy/OnlyForTorrents", "Preferences/Connection/ProxyOnlyForTorrents"},
|
||||||
|
{"Network/Proxy/Password", "Preferences/Connection/Proxy/Password"},
|
||||||
|
{"Network/Proxy/Port", "Preferences/Connection/Proxy/Port"},
|
||||||
|
{"Network/Proxy/Type", "Preferences/Connection/ProxyType"},
|
||||||
|
{"Network/Proxy/Username", "Preferences/Connection/Proxy/Username"},
|
||||||
|
{"State/BannedIPs", "Preferences/IPFilter/BannedIPs"}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
|
for (const KeyMapping &mapping : mappings)
|
||||||
|
{
|
||||||
|
if (settingsStorage->hasKey(mapping.oldKey))
|
||||||
|
{
|
||||||
|
const auto value = settingsStorage->loadValue<QVariant>(mapping.oldKey);
|
||||||
|
settingsStorage->storeValue(mapping.newKey, value);
|
||||||
|
// TODO: Remove oldKey after ~v4.4.3 and bump migration version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void migrateProxySettingsEnum()
|
||||||
|
{
|
||||||
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
|
const auto key = QString::fromLatin1("Network/Proxy/Type");
|
||||||
|
const auto value = settingsStorage->loadValue<QString>(key);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const auto number = value.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
switch (number)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
settingsStorage->storeValue(key, Net::ProxyType::None);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
settingsStorage->storeValue(key, Net::ProxyType::HTTP);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
settingsStorage->storeValue(key, Net::ProxyType::SOCKS5);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
settingsStorage->storeValue(key, Net::ProxyType::HTTP_PW);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
settingsStorage->storeValue(key, Net::ProxyType::SOCKS5_PW);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
settingsStorage->storeValue(key, Net::ProxyType::SOCKS4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogMsg(QObject::tr("Invalid value found in configuration file, reverting it to default. Key: \"%1\". Invalid value: \"%2\".")
|
||||||
|
.arg(key, QString::number(number)), Log::WARNING);
|
||||||
|
settingsStorage->removeValue(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool upgrade(const bool /*ask*/)
|
bool upgrade(const bool /*ask*/)
|
||||||
{
|
{
|
||||||
exportWebUIHttpsFiles();
|
CachedSettingValue<int> version {MIGRATION_VERSION_KEY, 0};
|
||||||
upgradeTorrentContentLayout();
|
|
||||||
upgradeListenPortSettings();
|
if (version != MIGRATION_VERSION)
|
||||||
|
{
|
||||||
|
if (version < 1)
|
||||||
|
{
|
||||||
|
exportWebUIHttpsFiles();
|
||||||
|
upgradeTorrentContentLayout();
|
||||||
|
upgradeListenPortSettings();
|
||||||
|
upgradeSchedulerDaysSettings();
|
||||||
|
upgradeDNSServiceSettings();
|
||||||
|
upgradeTrayIconStyleSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version < 2)
|
||||||
|
migrateSettingKeys();
|
||||||
|
|
||||||
|
if (version < 3)
|
||||||
|
migrateProxySettingsEnum();
|
||||||
|
|
||||||
|
version = MIGRATION_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCurrentMigrationVersion()
|
||||||
|
{
|
||||||
|
SettingsStorage::instance()->storeValue(QLatin1String(MIGRATION_VERSION_KEY), MIGRATION_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
void handleChangedDefaults(const DefaultPreferencesMode mode)
|
void handleChangedDefaults(const DefaultPreferencesMode mode)
|
||||||
{
|
{
|
||||||
struct DefaultValue
|
struct DefaultValue
|
||||||
@@ -136,15 +411,18 @@ void handleChangedDefaults(const DefaultPreferencesMode mode)
|
|||||||
QVariant current;
|
QVariant current;
|
||||||
};
|
};
|
||||||
|
|
||||||
const QVector<DefaultValue> changedDefaults
|
const DefaultValue changedDefaults[] =
|
||||||
{
|
{
|
||||||
{QLatin1String {"BitTorrent/Session/QueueingSystemEnabled"}, true, false}
|
{QLatin1String {"BitTorrent/Session/QueueingSystemEnabled"}, true, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
SettingsStorage *settingsStorage {SettingsStorage::instance()};
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
for (auto it = changedDefaults.cbegin(); it != changedDefaults.cend(); ++it)
|
for (const DefaultValue &value : changedDefaults)
|
||||||
{
|
{
|
||||||
if (settingsStorage->loadValue<QVariant>(it->name).isNull())
|
if (!settingsStorage->hasKey(value.name))
|
||||||
settingsStorage->storeValue(it->name, (mode == DefaultPreferencesMode::Legacy ? it->legacy : it->current));
|
{
|
||||||
|
settingsStorage->storeValue(value.name
|
||||||
|
, (mode == DefaultPreferencesMode::Legacy ? value.legacy : value.current));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,3 +36,4 @@ enum class DefaultPreferencesMode
|
|||||||
|
|
||||||
void handleChangedDefaults(DefaultPreferencesMode mode);
|
void handleChangedDefaults(DefaultPreferencesMode mode);
|
||||||
bool upgrade(bool ask = true);
|
bool upgrade(bool ask = true);
|
||||||
|
void setCurrentMigrationVersion();
|
||||||
|
|||||||
2517
src/base/3rdparty/expected.hpp
vendored
Normal file
@@ -1,5 +1,6 @@
|
|||||||
add_library(qbt_base STATIC
|
add_library(qbt_base STATIC
|
||||||
# headers
|
# headers
|
||||||
|
3rdparty/expected.hpp
|
||||||
algorithm.h
|
algorithm.h
|
||||||
asyncfilestorage.h
|
asyncfilestorage.h
|
||||||
bittorrent/abstractfilestorage.h
|
bittorrent/abstractfilestorage.h
|
||||||
@@ -7,6 +8,7 @@ add_library(qbt_base STATIC
|
|||||||
bittorrent/bandwidthscheduler.h
|
bittorrent/bandwidthscheduler.h
|
||||||
bittorrent/bencoderesumedatastorage.h
|
bittorrent/bencoderesumedatastorage.h
|
||||||
bittorrent/cachestatus.h
|
bittorrent/cachestatus.h
|
||||||
|
bittorrent/categoryoptions.h
|
||||||
bittorrent/common.h
|
bittorrent/common.h
|
||||||
bittorrent/customstorage.h
|
bittorrent/customstorage.h
|
||||||
bittorrent/dbresumedatastorage.h
|
bittorrent/dbresumedatastorage.h
|
||||||
@@ -16,7 +18,7 @@ add_library(qbt_base STATIC
|
|||||||
bittorrent/infohash.h
|
bittorrent/infohash.h
|
||||||
bittorrent/loadtorrentparams.h
|
bittorrent/loadtorrentparams.h
|
||||||
bittorrent/ltqhash.h
|
bittorrent/ltqhash.h
|
||||||
bittorrent/ltunderlyingtype.h
|
bittorrent/lttypecast.h
|
||||||
bittorrent/magneturi.h
|
bittorrent/magneturi.h
|
||||||
bittorrent/nativesessionextension.h
|
bittorrent/nativesessionextension.h
|
||||||
bittorrent/nativetorrentextension.h
|
bittorrent/nativetorrentextension.h
|
||||||
@@ -99,6 +101,7 @@ add_library(qbt_base STATIC
|
|||||||
bittorrent/abstractfilestorage.cpp
|
bittorrent/abstractfilestorage.cpp
|
||||||
bittorrent/bandwidthscheduler.cpp
|
bittorrent/bandwidthscheduler.cpp
|
||||||
bittorrent/bencoderesumedatastorage.cpp
|
bittorrent/bencoderesumedatastorage.cpp
|
||||||
|
bittorrent/categoryoptions.cpp
|
||||||
bittorrent/customstorage.cpp
|
bittorrent/customstorage.cpp
|
||||||
bittorrent/dbresumedatastorage.cpp
|
bittorrent/dbresumedatastorage.cpp
|
||||||
bittorrent/downloadpriority.cpp
|
bittorrent/downloadpriority.cpp
|
||||||
@@ -115,6 +118,7 @@ add_library(qbt_base STATIC
|
|||||||
bittorrent/speedmonitor.cpp
|
bittorrent/speedmonitor.cpp
|
||||||
bittorrent/statistics.cpp
|
bittorrent/statistics.cpp
|
||||||
bittorrent/torrent.cpp
|
bittorrent/torrent.cpp
|
||||||
|
bittorrent/torrentcontentlayout.cpp
|
||||||
bittorrent/torrentcreatorthread.cpp
|
bittorrent/torrentcreatorthread.cpp
|
||||||
bittorrent/torrentimpl.cpp
|
bittorrent/torrentimpl.cpp
|
||||||
bittorrent/torrentinfo.cpp
|
bittorrent/torrentinfo.cpp
|
||||||
@@ -176,7 +180,7 @@ target_link_libraries(qbt_base
|
|||||||
ZLIB::ZLIB
|
ZLIB::ZLIB
|
||||||
PUBLIC
|
PUBLIC
|
||||||
LibtorrentRasterbar::torrent-rasterbar
|
LibtorrentRasterbar::torrent-rasterbar
|
||||||
Qt5::Core Qt5::Network Qt5::Sql Qt5::Xml
|
Qt::Core Qt::Network Qt::Sql Qt::Xml
|
||||||
qbt_common_cfg
|
qbt_common_cfg
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -203,5 +207,5 @@ if (NOT WEBUI)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (DBUS)
|
if (DBUS)
|
||||||
target_link_libraries(qbt_base PUBLIC Qt5::DBus)
|
target_link_libraries(qbt_base PUBLIC Qt::DBus)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
#include <QSaveFile>
|
|
||||||
|
#include "base/utils/io.h"
|
||||||
|
|
||||||
AsyncFileStorage::AsyncFileStorage(const QString &storageFolderPath, QObject *parent)
|
AsyncFileStorage::AsyncFileStorage(const QString &storageFolderPath, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@@ -67,15 +68,12 @@ QDir AsyncFileStorage::storageDir() const
|
|||||||
void AsyncFileStorage::store_impl(const QString &fileName, const QByteArray &data)
|
void AsyncFileStorage::store_impl(const QString &fileName, const QByteArray &data)
|
||||||
{
|
{
|
||||||
const QString filePath = m_storageDir.absoluteFilePath(fileName);
|
const QString filePath = m_storageDir.absoluteFilePath(fileName);
|
||||||
QSaveFile file(filePath);
|
|
||||||
qDebug() << "AsyncFileStorage: Saving data to" << filePath;
|
qDebug() << "AsyncFileStorage: Saving data to" << filePath;
|
||||||
if (file.open(QIODevice::WriteOnly))
|
|
||||||
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(filePath, data);
|
||||||
|
if (!result)
|
||||||
{
|
{
|
||||||
file.write(data);
|
qDebug() << "AsyncFileStorage: Failed to save data";
|
||||||
if (!file.commit())
|
emit failed(filePath, result.error());
|
||||||
{
|
|
||||||
qDebug() << "AsyncFileStorage: Failed to save data";
|
|
||||||
emit failed(filePath, file.errorString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
$$PWD/3rdparty/expected.hpp \
|
||||||
$$PWD/algorithm.h \
|
$$PWD/algorithm.h \
|
||||||
$$PWD/asyncfilestorage.h \
|
$$PWD/asyncfilestorage.h \
|
||||||
$$PWD/bittorrent/abstractfilestorage.h \
|
$$PWD/bittorrent/abstractfilestorage.h \
|
||||||
@@ -6,6 +7,7 @@ HEADERS += \
|
|||||||
$$PWD/bittorrent/bandwidthscheduler.h \
|
$$PWD/bittorrent/bandwidthscheduler.h \
|
||||||
$$PWD/bittorrent/bencoderesumedatastorage.h \
|
$$PWD/bittorrent/bencoderesumedatastorage.h \
|
||||||
$$PWD/bittorrent/cachestatus.h \
|
$$PWD/bittorrent/cachestatus.h \
|
||||||
|
$$PWD/bittorrent/categoryoptions.h \
|
||||||
$$PWD/bittorrent/common.h \
|
$$PWD/bittorrent/common.h \
|
||||||
$$PWD/bittorrent/customstorage.h \
|
$$PWD/bittorrent/customstorage.h \
|
||||||
$$PWD/bittorrent/downloadpriority.h \
|
$$PWD/bittorrent/downloadpriority.h \
|
||||||
@@ -15,7 +17,7 @@ HEADERS += \
|
|||||||
$$PWD/bittorrent/infohash.h \
|
$$PWD/bittorrent/infohash.h \
|
||||||
$$PWD/bittorrent/loadtorrentparams.h \
|
$$PWD/bittorrent/loadtorrentparams.h \
|
||||||
$$PWD/bittorrent/ltqhash.h \
|
$$PWD/bittorrent/ltqhash.h \
|
||||||
$$PWD/bittorrent/ltunderlyingtype.h \
|
$$PWD/bittorrent/lttypecast.h \
|
||||||
$$PWD/bittorrent/magneturi.h \
|
$$PWD/bittorrent/magneturi.h \
|
||||||
$$PWD/bittorrent/nativesessionextension.h \
|
$$PWD/bittorrent/nativesessionextension.h \
|
||||||
$$PWD/bittorrent/nativetorrentextension.h \
|
$$PWD/bittorrent/nativetorrentextension.h \
|
||||||
@@ -99,6 +101,7 @@ SOURCES += \
|
|||||||
$$PWD/bittorrent/abstractfilestorage.cpp \
|
$$PWD/bittorrent/abstractfilestorage.cpp \
|
||||||
$$PWD/bittorrent/bandwidthscheduler.cpp \
|
$$PWD/bittorrent/bandwidthscheduler.cpp \
|
||||||
$$PWD/bittorrent/bencoderesumedatastorage.cpp \
|
$$PWD/bittorrent/bencoderesumedatastorage.cpp \
|
||||||
|
$$PWD/bittorrent/categoryoptions.cpp \
|
||||||
$$PWD/bittorrent/customstorage.cpp \
|
$$PWD/bittorrent/customstorage.cpp \
|
||||||
$$PWD/bittorrent/dbresumedatastorage.cpp \
|
$$PWD/bittorrent/dbresumedatastorage.cpp \
|
||||||
$$PWD/bittorrent/downloadpriority.cpp \
|
$$PWD/bittorrent/downloadpriority.cpp \
|
||||||
@@ -115,6 +118,7 @@ SOURCES += \
|
|||||||
$$PWD/bittorrent/speedmonitor.cpp \
|
$$PWD/bittorrent/speedmonitor.cpp \
|
||||||
$$PWD/bittorrent/statistics.cpp \
|
$$PWD/bittorrent/statistics.cpp \
|
||||||
$$PWD/bittorrent/torrent.cpp \
|
$$PWD/bittorrent/torrent.cpp \
|
||||||
|
$$PWD/bittorrent/torrentcontentlayout.cpp \
|
||||||
$$PWD/bittorrent/torrentcreatorthread.cpp \
|
$$PWD/bittorrent/torrentcreatorthread.cpp \
|
||||||
$$PWD/bittorrent/torrentimpl.cpp \
|
$$PWD/bittorrent/torrentimpl.cpp \
|
||||||
$$PWD/bittorrent/torrentinfo.cpp \
|
$$PWD/bittorrent/torrentinfo.cpp \
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace BitTorrent
|
|||||||
|
|
||||||
virtual int filesCount() const = 0;
|
virtual int filesCount() const = 0;
|
||||||
virtual QString filePath(int index) const = 0;
|
virtual QString filePath(int index) const = 0;
|
||||||
virtual QString fileName(int index) const = 0;
|
|
||||||
virtual qlonglong fileSize(int index) const = 0;
|
virtual qlonglong fileSize(int index) const = 0;
|
||||||
|
|
||||||
virtual void renameFile(int index, const QString &name) = 0;
|
virtual void renameFile(int index, const QString &name) = 0;
|
||||||
|
|||||||
@@ -48,11 +48,13 @@ namespace BitTorrent
|
|||||||
QString category;
|
QString category;
|
||||||
TagSet tags;
|
TagSet tags;
|
||||||
QString savePath;
|
QString savePath;
|
||||||
bool disableTempPath = false; // e.g. for imported torrents
|
std::optional<bool> useDownloadPath;
|
||||||
|
QString downloadPath;
|
||||||
bool sequential = false;
|
bool sequential = false;
|
||||||
bool firstLastPiecePriority = false;
|
bool firstLastPiecePriority = false;
|
||||||
bool addForced = false;
|
bool addForced = false;
|
||||||
std::optional<bool> addPaused;
|
std::optional<bool> addPaused;
|
||||||
|
QStringList filePaths; // used if TorrentInfo is set
|
||||||
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
|
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
|
||||||
bool skipChecking = false;
|
bool skipChecking = false;
|
||||||
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
|
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ bool BandwidthScheduler::isTimeForAlternative() const
|
|||||||
QTime start = pref->getSchedulerStartTime();
|
QTime start = pref->getSchedulerStartTime();
|
||||||
QTime end = pref->getSchedulerEndTime();
|
QTime end = pref->getSchedulerEndTime();
|
||||||
const QTime now = QTime::currentTime();
|
const QTime now = QTime::currentTime();
|
||||||
const int schedulerDays = pref->getSchedulerDays();
|
const Scheduler::Days schedulerDays = pref->getSchedulerDays();
|
||||||
const int day = QDate::currentDate().dayOfWeek();
|
const int day = QDate::currentDate().dayOfWeek();
|
||||||
bool alternative = false;
|
bool alternative = false;
|
||||||
|
|
||||||
@@ -75,20 +75,34 @@ bool BandwidthScheduler::isTimeForAlternative() const
|
|||||||
{
|
{
|
||||||
switch (schedulerDays)
|
switch (schedulerDays)
|
||||||
{
|
{
|
||||||
case EVERY_DAY:
|
case Scheduler::Days::EveryDay:
|
||||||
alternative = !alternative;
|
alternative = !alternative;
|
||||||
break;
|
break;
|
||||||
case WEEK_ENDS:
|
case Scheduler::Days::Monday:
|
||||||
|
case Scheduler::Days::Tuesday:
|
||||||
|
case Scheduler::Days::Wednesday:
|
||||||
|
case Scheduler::Days::Thursday:
|
||||||
|
case Scheduler::Days::Friday:
|
||||||
|
case Scheduler::Days::Saturday:
|
||||||
|
case Scheduler::Days::Sunday:
|
||||||
|
{
|
||||||
|
const int offset = static_cast<int>(Scheduler::Days::Monday) - 1;
|
||||||
|
const int dayOfWeek = static_cast<int>(schedulerDays) - offset;
|
||||||
|
if (day == dayOfWeek)
|
||||||
|
alternative = !alternative;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Scheduler::Days::Weekday:
|
||||||
|
if ((day >= 1) && (day <= 5))
|
||||||
|
alternative = !alternative;
|
||||||
|
break;
|
||||||
|
case Scheduler::Days::Weekend:
|
||||||
if ((day == 6) || (day == 7))
|
if ((day == 6) || (day == 7))
|
||||||
alternative = !alternative;
|
alternative = !alternative;
|
||||||
break;
|
break;
|
||||||
case WEEK_DAYS:
|
|
||||||
if ((day != 6) && (day != 7))
|
|
||||||
alternative = !alternative;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
if (day == (schedulerDays - 2))
|
Q_ASSERT(false);
|
||||||
alternative = !alternative;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,15 +29,14 @@
|
|||||||
#include "bencoderesumedatastorage.h"
|
#include "bencoderesumedatastorage.h"
|
||||||
|
|
||||||
#include <libtorrent/bdecode.hpp>
|
#include <libtorrent/bdecode.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
|
||||||
#include <libtorrent/entry.hpp>
|
#include <libtorrent/entry.hpp>
|
||||||
#include <libtorrent/read_resume_data.hpp>
|
#include <libtorrent/read_resume_data.hpp>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
#include <libtorrent/write_resume_data.hpp>
|
#include <libtorrent/write_resume_data.hpp>
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QDebug>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QSaveFile>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include "base/algorithm.h"
|
#include "base/algorithm.h"
|
||||||
@@ -88,17 +87,6 @@ namespace
|
|||||||
entryList.emplace_back(setValue.toStdString());
|
entryList.emplace_back(setValue.toStdString());
|
||||||
return entryList;
|
return entryList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeEntryToFile(const QString &filepath, const lt::entry &data)
|
|
||||||
{
|
|
||||||
QSaveFile file {filepath};
|
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
|
||||||
throw RuntimeError(file.errorString());
|
|
||||||
|
|
||||||
lt::bencode(Utils::IO::FileDeviceOutputIterator {file}, data);
|
|
||||||
if (file.error() != QFileDevice::NoError || !file.commit())
|
|
||||||
throw RuntimeError(file.errorString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitTorrent::BencodeResumeDataStorage::BencodeResumeDataStorage(const QString &path, QObject *parent)
|
BitTorrent::BencodeResumeDataStorage::BencodeResumeDataStorage(const QString &path, QObject *parent)
|
||||||
@@ -126,7 +114,7 @@ BitTorrent::BencodeResumeDataStorage::BencodeResumeDataStorage(const QString &pa
|
|||||||
|
|
||||||
loadQueue(m_resumeDataDir.absoluteFilePath(QLatin1String("queue")));
|
loadQueue(m_resumeDataDir.absoluteFilePath(QLatin1String("queue")));
|
||||||
|
|
||||||
qDebug("Registered torrents count: %d", m_registeredTorrents.size());
|
qDebug() << "Registered torrents count: " << m_registeredTorrents.size();
|
||||||
|
|
||||||
m_asyncWorker->moveToThread(m_ioThread);
|
m_asyncWorker->moveToThread(m_ioThread);
|
||||||
connect(m_ioThread, &QThread::finished, m_asyncWorker, &QObject::deleteLater);
|
connect(m_ioThread, &QThread::finished, m_asyncWorker, &QObject::deleteLater);
|
||||||
@@ -185,12 +173,19 @@ std::optional<BitTorrent::LoadTorrentParams> BitTorrent::BencodeResumeDataStorag
|
|||||||
torrentParams.restored = true;
|
torrentParams.restored = true;
|
||||||
torrentParams.category = fromLTString(root.dict_find_string_value("qBt-category"));
|
torrentParams.category = fromLTString(root.dict_find_string_value("qBt-category"));
|
||||||
torrentParams.name = fromLTString(root.dict_find_string_value("qBt-name"));
|
torrentParams.name = fromLTString(root.dict_find_string_value("qBt-name"));
|
||||||
torrentParams.savePath = Profile::instance()->fromPortablePath(
|
|
||||||
Utils::Fs::toUniformPath(fromLTString(root.dict_find_string_value("qBt-savePath"))));
|
|
||||||
torrentParams.hasSeedStatus = root.dict_find_int_value("qBt-seedStatus");
|
torrentParams.hasSeedStatus = root.dict_find_int_value("qBt-seedStatus");
|
||||||
torrentParams.firstLastPiecePriority = root.dict_find_int_value("qBt-firstLastPiecePriority");
|
torrentParams.firstLastPiecePriority = root.dict_find_int_value("qBt-firstLastPiecePriority");
|
||||||
torrentParams.seedingTimeLimit = root.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
|
torrentParams.seedingTimeLimit = root.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
|
||||||
|
|
||||||
|
torrentParams.savePath = Profile::instance()->fromPortablePath(
|
||||||
|
Utils::Fs::toUniformPath(fromLTString(root.dict_find_string_value("qBt-savePath"))));
|
||||||
|
torrentParams.useAutoTMM = torrentParams.savePath.isEmpty();
|
||||||
|
if (!torrentParams.useAutoTMM)
|
||||||
|
{
|
||||||
|
torrentParams.downloadPath = Profile::instance()->fromPortablePath(
|
||||||
|
Utils::Fs::toUniformPath(fromLTString(root.dict_find_string_value("qBt-downloadPath"))));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
|
// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
|
||||||
// === BEGIN DEPRECATED CODE === //
|
// === BEGIN DEPRECATED CODE === //
|
||||||
const lt::bdecode_node contentLayoutNode = root.dict_find("qBt-contentLayout");
|
const lt::bdecode_node contentLayoutNode = root.dict_find("qBt-contentLayout");
|
||||||
@@ -355,19 +350,15 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
|
|||||||
metadataDict.insert(dataDict.extract("comment"));
|
metadataDict.insert(dataDict.extract("comment"));
|
||||||
|
|
||||||
const QString torrentFilepath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.torrent").arg(id.toString()));
|
const QString torrentFilepath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.torrent").arg(id.toString()));
|
||||||
try
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(torrentFilepath, metadata);
|
||||||
{
|
if (!result)
|
||||||
writeEntryToFile(torrentFilepath, metadata);
|
|
||||||
}
|
|
||||||
catch (const RuntimeError &err)
|
|
||||||
{
|
{
|
||||||
LogMsg(tr("Couldn't save torrent metadata to '%1'. Error: %2.")
|
LogMsg(tr("Couldn't save torrent metadata to '%1'. Error: %2.")
|
||||||
.arg(torrentFilepath, err.message()), Log::CRITICAL);
|
.arg(torrentFilepath, result.error()), Log::CRITICAL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data["qBt-savePath"] = Profile::instance()->toPortablePath(resumeData.savePath).toStdString();
|
|
||||||
data["qBt-ratioLimit"] = static_cast<int>(resumeData.ratioLimit * 1000);
|
data["qBt-ratioLimit"] = static_cast<int>(resumeData.ratioLimit * 1000);
|
||||||
data["qBt-seedingTimeLimit"] = resumeData.seedingTimeLimit;
|
data["qBt-seedingTimeLimit"] = resumeData.seedingTimeLimit;
|
||||||
data["qBt-category"] = resumeData.category.toStdString();
|
data["qBt-category"] = resumeData.category.toStdString();
|
||||||
@@ -377,15 +368,18 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
|
|||||||
data["qBt-contentLayout"] = Utils::String::fromEnum(resumeData.contentLayout).toStdString();
|
data["qBt-contentLayout"] = Utils::String::fromEnum(resumeData.contentLayout).toStdString();
|
||||||
data["qBt-firstLastPiecePriority"] = resumeData.firstLastPiecePriority;
|
data["qBt-firstLastPiecePriority"] = resumeData.firstLastPiecePriority;
|
||||||
|
|
||||||
const QString resumeFilepath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.fastresume").arg(id.toString()));
|
if (!resumeData.useAutoTMM)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
writeEntryToFile(resumeFilepath, data);
|
data["qBt-savePath"] = Profile::instance()->toPortablePath(resumeData.savePath).toStdString();
|
||||||
|
data["qBt-downloadPath"] = Profile::instance()->toPortablePath(resumeData.downloadPath).toStdString();
|
||||||
}
|
}
|
||||||
catch (const RuntimeError &err)
|
|
||||||
|
const QString resumeFilepath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.fastresume").arg(id.toString()));
|
||||||
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(resumeFilepath, data);
|
||||||
|
if (!result)
|
||||||
{
|
{
|
||||||
LogMsg(tr("Couldn't save torrent resume data to '%1'. Error: %2.")
|
LogMsg(tr("Couldn't save torrent resume data to '%1'. Error: %2.")
|
||||||
.arg(resumeFilepath, err.message()), Log::CRITICAL);
|
.arg(resumeFilepath, result.error()), Log::CRITICAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,10 +400,10 @@ void BitTorrent::BencodeResumeDataStorage::Worker::storeQueue(const QVector<Torr
|
|||||||
data += (torrentID.toString().toLatin1() + '\n');
|
data += (torrentID.toString().toLatin1() + '\n');
|
||||||
|
|
||||||
const QString filepath = m_resumeDataDir.absoluteFilePath(QLatin1String("queue"));
|
const QString filepath = m_resumeDataDir.absoluteFilePath(QLatin1String("queue"));
|
||||||
QSaveFile file {filepath};
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(filepath, data);
|
||||||
if (!file.open(QIODevice::WriteOnly) || (file.write(data) != data.size()) || !file.commit())
|
if (!result)
|
||||||
{
|
{
|
||||||
LogMsg(tr("Couldn't save data to '%1'. Error: %2")
|
LogMsg(tr("Couldn't save data to '%1'. Error: %2")
|
||||||
.arg(filepath, file.errorString()), Log::CRITICAL);
|
.arg(filepath, result.error()), Log::CRITICAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
78
src/base/bittorrent/categoryoptions.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2021 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "categoryoptions.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
|
||||||
|
const QString OPTION_SAVEPATH {QStringLiteral("save_path")};
|
||||||
|
const QString OPTION_DOWNLOADPATH {QStringLiteral("download_path")};
|
||||||
|
|
||||||
|
BitTorrent::CategoryOptions BitTorrent::CategoryOptions::fromJSON(const QJsonObject &jsonObj)
|
||||||
|
{
|
||||||
|
CategoryOptions options;
|
||||||
|
options.savePath = jsonObj.value(OPTION_SAVEPATH).toString();
|
||||||
|
|
||||||
|
const QJsonValue downloadPathValue = jsonObj.value(OPTION_DOWNLOADPATH);
|
||||||
|
if (downloadPathValue.isBool())
|
||||||
|
options.downloadPath = {downloadPathValue.toBool(), {}};
|
||||||
|
else if (downloadPathValue.isString())
|
||||||
|
options.downloadPath = {true, downloadPathValue.toString()};
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject BitTorrent::CategoryOptions::toJSON() const
|
||||||
|
{
|
||||||
|
QJsonValue downloadPathValue = QJsonValue::Undefined;
|
||||||
|
if (downloadPath)
|
||||||
|
{
|
||||||
|
if (downloadPath->enabled)
|
||||||
|
downloadPathValue = downloadPath->path;
|
||||||
|
else
|
||||||
|
downloadPathValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
{OPTION_SAVEPATH, savePath},
|
||||||
|
{OPTION_DOWNLOADPATH, downloadPathValue}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BitTorrent::operator==(const BitTorrent::CategoryOptions::DownloadPathOption &left, const BitTorrent::CategoryOptions::DownloadPathOption &right)
|
||||||
|
{
|
||||||
|
return ((left.enabled == right.enabled)
|
||||||
|
&& (left.path == right.path));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BitTorrent::operator==(const BitTorrent::CategoryOptions &left, const BitTorrent::CategoryOptions &right)
|
||||||
|
{
|
||||||
|
return ((left.savePath == right.savePath)
|
||||||
|
&& (left.downloadPath == right.downloadPath));
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2021 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
|
||||||
@@ -28,8 +28,29 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
template <typename T>
|
#include <optional>
|
||||||
typename T::underlying_type toLTUnderlyingType(const T &t)
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class QJsonObject;
|
||||||
|
|
||||||
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
return static_cast<typename T::underlying_type>(t);
|
struct CategoryOptions
|
||||||
|
{
|
||||||
|
struct DownloadPathOption
|
||||||
|
{
|
||||||
|
bool enabled;
|
||||||
|
QString path;
|
||||||
|
};
|
||||||
|
|
||||||
|
QString savePath;
|
||||||
|
std::optional<DownloadPathOption> downloadPath;
|
||||||
|
|
||||||
|
static CategoryOptions fromJSON(const QJsonObject &jsonObj);
|
||||||
|
QJsonObject toJSON() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const CategoryOptions::DownloadPathOption &left, const CategoryOptions::DownloadPathOption &right);
|
||||||
|
bool operator==(const CategoryOptions &left, const CategoryOptions &right);
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include "dbresumedatastorage.h"
|
#include "dbresumedatastorage.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <libtorrent/bdecode.hpp>
|
#include <libtorrent/bdecode.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
#include <libtorrent/entry.hpp>
|
#include <libtorrent/entry.hpp>
|
||||||
@@ -57,11 +59,13 @@ namespace
|
|||||||
{
|
{
|
||||||
const char DB_CONNECTION_NAME[] = "ResumeDataStorage";
|
const char DB_CONNECTION_NAME[] = "ResumeDataStorage";
|
||||||
|
|
||||||
const int DB_VERSION = 1;
|
const int DB_VERSION = 2;
|
||||||
|
|
||||||
const char DB_TABLE_META[] = "meta";
|
const char DB_TABLE_META[] = "meta";
|
||||||
const char DB_TABLE_TORRENTS[] = "torrents";
|
const char DB_TABLE_TORRENTS[] = "torrents";
|
||||||
|
|
||||||
|
const char META_VERSION[] = "version";
|
||||||
|
|
||||||
struct Column
|
struct Column
|
||||||
{
|
{
|
||||||
QString name;
|
QString name;
|
||||||
@@ -80,6 +84,7 @@ namespace
|
|||||||
const Column DB_COLUMN_CATEGORY = makeColumn("category");
|
const Column DB_COLUMN_CATEGORY = makeColumn("category");
|
||||||
const Column DB_COLUMN_TAGS = makeColumn("tags");
|
const Column DB_COLUMN_TAGS = makeColumn("tags");
|
||||||
const Column DB_COLUMN_TARGET_SAVE_PATH = makeColumn("target_save_path");
|
const Column DB_COLUMN_TARGET_SAVE_PATH = makeColumn("target_save_path");
|
||||||
|
const Column DB_COLUMN_DOWNLOAD_PATH = makeColumn("download_path");
|
||||||
const Column DB_COLUMN_CONTENT_LAYOUT = makeColumn("content_layout");
|
const Column DB_COLUMN_CONTENT_LAYOUT = makeColumn("content_layout");
|
||||||
const Column DB_COLUMN_RATIO_LIMIT = makeColumn("ratio_limit");
|
const Column DB_COLUMN_RATIO_LIMIT = makeColumn("ratio_limit");
|
||||||
const Column DB_COLUMN_SEEDING_TIME_LIMIT = makeColumn("seeding_time_limit");
|
const Column DB_COLUMN_SEEDING_TIME_LIMIT = makeColumn("seeding_time_limit");
|
||||||
@@ -109,42 +114,50 @@ namespace
|
|||||||
return QString::fromLatin1("CREATE TABLE %1 (%2)").arg(quoted(tableName), items.join(QLatin1Char(',')));
|
return QString::fromLatin1("CREATE TABLE %1 (%2)").arg(quoted(tableName), items.join(QLatin1Char(',')));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString makeInsertStatement(const QString &tableName, const QVector<Column> &columns)
|
std::pair<QString, QString> joinColumns(const QVector<Column> &columns)
|
||||||
{
|
{
|
||||||
QStringList names;
|
int namesSize = columns.size();
|
||||||
names.reserve(columns.size());
|
int valuesSize = columns.size();
|
||||||
QStringList values;
|
|
||||||
values.reserve(columns.size());
|
|
||||||
for (const Column &column : columns)
|
for (const Column &column : columns)
|
||||||
{
|
{
|
||||||
names.append(quoted(column.name));
|
namesSize += column.name.size() + 2;
|
||||||
values.append(column.placeholder);
|
valuesSize += column.placeholder.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString jointNames = names.join(QLatin1Char(','));
|
QString names;
|
||||||
const QString jointValues = values.join(QLatin1Char(','));
|
names.reserve(namesSize);
|
||||||
|
QString values;
|
||||||
|
values.reserve(valuesSize);
|
||||||
|
for (const Column &column : columns)
|
||||||
|
{
|
||||||
|
names.append(quoted(column.name) + QLatin1Char(','));
|
||||||
|
values.append(column.placeholder + QLatin1Char(','));
|
||||||
|
}
|
||||||
|
names.chop(1);
|
||||||
|
values.chop(1);
|
||||||
|
|
||||||
|
return std::make_pair(names, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString makeInsertStatement(const QString &tableName, const QVector<Column> &columns)
|
||||||
|
{
|
||||||
|
const auto [names, values] = joinColumns(columns);
|
||||||
return QString::fromLatin1("INSERT INTO %1 (%2) VALUES (%3)")
|
return QString::fromLatin1("INSERT INTO %1 (%2) VALUES (%3)")
|
||||||
.arg(quoted(tableName), jointNames, jointValues);
|
.arg(quoted(tableName), names, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString makeUpdateStatement(const QString &tableName, const QVector<Column> &columns)
|
||||||
|
{
|
||||||
|
const auto [names, values] = joinColumns(columns);
|
||||||
|
return QString::fromLatin1("UPDATE %1 SET (%2) = (%3)")
|
||||||
|
.arg(quoted(tableName), names, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString makeOnConflictUpdateStatement(const Column &constraint, const QVector<Column> &columns)
|
QString makeOnConflictUpdateStatement(const Column &constraint, const QVector<Column> &columns)
|
||||||
{
|
{
|
||||||
QStringList names;
|
const auto [names, values] = joinColumns(columns);
|
||||||
names.reserve(columns.size());
|
|
||||||
QStringList values;
|
|
||||||
values.reserve(columns.size());
|
|
||||||
for (const Column &column : columns)
|
|
||||||
{
|
|
||||||
names.append(quoted(column.name));
|
|
||||||
values.append(column.placeholder);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString jointNames = names.join(QLatin1Char(','));
|
|
||||||
const QString jointValues = values.join(QLatin1Char(','));
|
|
||||||
|
|
||||||
return QString::fromLatin1(" ON CONFLICT (%1) DO UPDATE SET (%2) = (%3)")
|
return QString::fromLatin1(" ON CONFLICT (%1) DO UPDATE SET (%2) = (%3)")
|
||||||
.arg(quoted(constraint.name), jointNames, jointValues);
|
.arg(quoted(constraint.name), names, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString makeColumnDefinition(const Column &column, const char *definition)
|
QString makeColumnDefinition(const Column &column, const char *definition)
|
||||||
@@ -187,7 +200,15 @@ BitTorrent::DBResumeDataStorage::DBResumeDataStorage(const QString &dbPath, QObj
|
|||||||
throw RuntimeError(db.lastError().text());
|
throw RuntimeError(db.lastError().text());
|
||||||
|
|
||||||
if (needCreateDB)
|
if (needCreateDB)
|
||||||
|
{
|
||||||
createDB();
|
createDB();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int dbVersion = currentDBVersion();
|
||||||
|
if (dbVersion == 1)
|
||||||
|
updateDBFromVersion1();
|
||||||
|
}
|
||||||
|
|
||||||
m_asyncWorker = new Worker(dbPath, QLatin1String("ResumeDataStorageWorker"));
|
m_asyncWorker = new Worker(dbPath, QLatin1String("ResumeDataStorageWorker"));
|
||||||
m_asyncWorker->moveToThread(m_ioThread);
|
m_asyncWorker->moveToThread(m_ioThread);
|
||||||
@@ -276,8 +297,6 @@ std::optional<BitTorrent::LoadTorrentParams> BitTorrent::DBResumeDataStorage::lo
|
|||||||
const QStringList tagList = tagsData.split(QLatin1Char(','));
|
const QStringList tagList = tagsData.split(QLatin1Char(','));
|
||||||
resumeData.tags.insert(tagList.cbegin(), tagList.cend());
|
resumeData.tags.insert(tagList.cbegin(), tagList.cend());
|
||||||
}
|
}
|
||||||
resumeData.savePath = Profile::instance()->fromPortablePath(
|
|
||||||
Utils::Fs::toUniformPath(query.value(DB_COLUMN_TARGET_SAVE_PATH.name).toString()));
|
|
||||||
resumeData.hasSeedStatus = query.value(DB_COLUMN_HAS_SEED_STATUS.name).toBool();
|
resumeData.hasSeedStatus = query.value(DB_COLUMN_HAS_SEED_STATUS.name).toBool();
|
||||||
resumeData.firstLastPiecePriority = query.value(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY.name).toBool();
|
resumeData.firstLastPiecePriority = query.value(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY.name).toBool();
|
||||||
resumeData.ratioLimit = query.value(DB_COLUMN_RATIO_LIMIT.name).toInt() / 1000.0;
|
resumeData.ratioLimit = query.value(DB_COLUMN_RATIO_LIMIT.name).toInt() / 1000.0;
|
||||||
@@ -288,6 +307,15 @@ std::optional<BitTorrent::LoadTorrentParams> BitTorrent::DBResumeDataStorage::lo
|
|||||||
query.value(DB_COLUMN_OPERATING_MODE.name).toString(), TorrentOperatingMode::AutoManaged);
|
query.value(DB_COLUMN_OPERATING_MODE.name).toString(), TorrentOperatingMode::AutoManaged);
|
||||||
resumeData.stopped = query.value(DB_COLUMN_STOPPED.name).toBool();
|
resumeData.stopped = query.value(DB_COLUMN_STOPPED.name).toBool();
|
||||||
|
|
||||||
|
resumeData.savePath = Profile::instance()->fromPortablePath(
|
||||||
|
Utils::Fs::toUniformPath(query.value(DB_COLUMN_TARGET_SAVE_PATH.name).toString()));
|
||||||
|
resumeData.useAutoTMM = resumeData.savePath.isEmpty();
|
||||||
|
if (!resumeData.useAutoTMM)
|
||||||
|
{
|
||||||
|
resumeData.downloadPath = Profile::instance()->fromPortablePath(
|
||||||
|
Utils::Fs::toUniformPath(query.value(DB_COLUMN_DOWNLOAD_PATH.name).toString()));
|
||||||
|
}
|
||||||
|
|
||||||
const QByteArray bencodedResumeData = query.value(DB_COLUMN_RESUMEDATA.name).toByteArray();
|
const QByteArray bencodedResumeData = query.value(DB_COLUMN_RESUMEDATA.name).toByteArray();
|
||||||
const QByteArray bencodedMetadata = query.value(DB_COLUMN_METADATA.name).toByteArray();
|
const QByteArray bencodedMetadata = query.value(DB_COLUMN_METADATA.name).toByteArray();
|
||||||
const QByteArray allData = ((bencodedMetadata.isEmpty() || bencodedResumeData.isEmpty())
|
const QByteArray allData = ((bencodedMetadata.isEmpty() || bencodedResumeData.isEmpty())
|
||||||
@@ -329,6 +357,33 @@ void BitTorrent::DBResumeDataStorage::storeQueue(const QVector<TorrentID> &queue
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BitTorrent::DBResumeDataStorage::currentDBVersion() const
|
||||||
|
{
|
||||||
|
const auto selectDBVersionStatement = QString::fromLatin1("SELECT %1 FROM %2 WHERE %3 = %4;")
|
||||||
|
.arg(quoted(DB_COLUMN_VALUE.name), quoted(DB_TABLE_META), quoted(DB_COLUMN_NAME.name), DB_COLUMN_NAME.placeholder);
|
||||||
|
|
||||||
|
auto db = QSqlDatabase::database(DB_CONNECTION_NAME);
|
||||||
|
QSqlQuery query {db};
|
||||||
|
|
||||||
|
if (!query.prepare(selectDBVersionStatement))
|
||||||
|
throw RuntimeError(query.lastError().text());
|
||||||
|
|
||||||
|
query.bindValue(DB_COLUMN_NAME.placeholder, QString::fromLatin1(META_VERSION));
|
||||||
|
|
||||||
|
if (!query.exec())
|
||||||
|
throw RuntimeError(query.lastError().text());
|
||||||
|
|
||||||
|
if (!query.next())
|
||||||
|
throw RuntimeError(tr("Database is corrupted."));
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
const int dbVersion = query.value(0).toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
throw RuntimeError(tr("Database is corrupted."));
|
||||||
|
|
||||||
|
return dbVersion;
|
||||||
|
}
|
||||||
|
|
||||||
void BitTorrent::DBResumeDataStorage::createDB() const
|
void BitTorrent::DBResumeDataStorage::createDB() const
|
||||||
{
|
{
|
||||||
auto db = QSqlDatabase::database(DB_CONNECTION_NAME);
|
auto db = QSqlDatabase::database(DB_CONNECTION_NAME);
|
||||||
@@ -353,7 +408,7 @@ void BitTorrent::DBResumeDataStorage::createDB() const
|
|||||||
if (!query.prepare(insertMetaVersionQuery))
|
if (!query.prepare(insertMetaVersionQuery))
|
||||||
throw RuntimeError(query.lastError().text());
|
throw RuntimeError(query.lastError().text());
|
||||||
|
|
||||||
query.bindValue(DB_COLUMN_NAME.placeholder, QString::fromLatin1("version"));
|
query.bindValue(DB_COLUMN_NAME.placeholder, QString::fromLatin1(META_VERSION));
|
||||||
query.bindValue(DB_COLUMN_VALUE.placeholder, DB_VERSION);
|
query.bindValue(DB_COLUMN_VALUE.placeholder, DB_VERSION);
|
||||||
|
|
||||||
if (!query.exec())
|
if (!query.exec())
|
||||||
@@ -391,6 +446,42 @@ void BitTorrent::DBResumeDataStorage::createDB() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitTorrent::DBResumeDataStorage::updateDBFromVersion1() const
|
||||||
|
{
|
||||||
|
auto db = QSqlDatabase::database(DB_CONNECTION_NAME);
|
||||||
|
|
||||||
|
if (!db.transaction())
|
||||||
|
throw RuntimeError(db.lastError().text());
|
||||||
|
|
||||||
|
QSqlQuery query {db};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const auto alterTableTorrentsQuery = QString::fromLatin1("ALTER TABLE %1 ADD %2")
|
||||||
|
.arg(quoted(DB_TABLE_TORRENTS), makeColumnDefinition(DB_COLUMN_DOWNLOAD_PATH, "TEXT"));
|
||||||
|
if (!query.exec(alterTableTorrentsQuery))
|
||||||
|
throw RuntimeError(query.lastError().text());
|
||||||
|
|
||||||
|
const QString updateMetaVersionQuery = makeUpdateStatement(DB_TABLE_META, {DB_COLUMN_NAME, DB_COLUMN_VALUE});
|
||||||
|
if (!query.prepare(updateMetaVersionQuery))
|
||||||
|
throw RuntimeError(query.lastError().text());
|
||||||
|
|
||||||
|
query.bindValue(DB_COLUMN_NAME.placeholder, QString::fromLatin1(META_VERSION));
|
||||||
|
query.bindValue(DB_COLUMN_VALUE.placeholder, DB_VERSION);
|
||||||
|
|
||||||
|
if (!query.exec())
|
||||||
|
throw RuntimeError(query.lastError().text());
|
||||||
|
|
||||||
|
if (!db.commit())
|
||||||
|
throw RuntimeError(db.lastError().text());
|
||||||
|
}
|
||||||
|
catch (const RuntimeError &)
|
||||||
|
{
|
||||||
|
db.rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BitTorrent::DBResumeDataStorage::Worker::Worker(const QString &dbPath, const QString &dbConnectionName)
|
BitTorrent::DBResumeDataStorage::Worker::Worker(const QString &dbPath, const QString &dbConnectionName)
|
||||||
: m_path {dbPath}
|
: m_path {dbPath}
|
||||||
, m_connectionName {dbConnectionName}
|
, m_connectionName {dbConnectionName}
|
||||||
@@ -499,7 +590,6 @@ void BitTorrent::DBResumeDataStorage::Worker::store(const TorrentID &id, const L
|
|||||||
query.bindValue(DB_COLUMN_CATEGORY.placeholder, resumeData.category);
|
query.bindValue(DB_COLUMN_CATEGORY.placeholder, resumeData.category);
|
||||||
query.bindValue(DB_COLUMN_TAGS.placeholder, (resumeData.tags.isEmpty()
|
query.bindValue(DB_COLUMN_TAGS.placeholder, (resumeData.tags.isEmpty()
|
||||||
? QVariant(QVariant::String) : resumeData.tags.join(QLatin1String(","))));
|
? QVariant(QVariant::String) : resumeData.tags.join(QLatin1String(","))));
|
||||||
query.bindValue(DB_COLUMN_TARGET_SAVE_PATH.placeholder, Profile::instance()->toPortablePath(resumeData.savePath));
|
|
||||||
query.bindValue(DB_COLUMN_CONTENT_LAYOUT.placeholder, Utils::String::fromEnum(resumeData.contentLayout));
|
query.bindValue(DB_COLUMN_CONTENT_LAYOUT.placeholder, Utils::String::fromEnum(resumeData.contentLayout));
|
||||||
query.bindValue(DB_COLUMN_RATIO_LIMIT.placeholder, static_cast<int>(resumeData.ratioLimit * 1000));
|
query.bindValue(DB_COLUMN_RATIO_LIMIT.placeholder, static_cast<int>(resumeData.ratioLimit * 1000));
|
||||||
query.bindValue(DB_COLUMN_SEEDING_TIME_LIMIT.placeholder, resumeData.seedingTimeLimit);
|
query.bindValue(DB_COLUMN_SEEDING_TIME_LIMIT.placeholder, resumeData.seedingTimeLimit);
|
||||||
@@ -507,6 +597,13 @@ void BitTorrent::DBResumeDataStorage::Worker::store(const TorrentID &id, const L
|
|||||||
query.bindValue(DB_COLUMN_HAS_SEED_STATUS.placeholder, resumeData.hasSeedStatus);
|
query.bindValue(DB_COLUMN_HAS_SEED_STATUS.placeholder, resumeData.hasSeedStatus);
|
||||||
query.bindValue(DB_COLUMN_OPERATING_MODE.placeholder, Utils::String::fromEnum(resumeData.operatingMode));
|
query.bindValue(DB_COLUMN_OPERATING_MODE.placeholder, Utils::String::fromEnum(resumeData.operatingMode));
|
||||||
query.bindValue(DB_COLUMN_STOPPED.placeholder, resumeData.stopped);
|
query.bindValue(DB_COLUMN_STOPPED.placeholder, resumeData.stopped);
|
||||||
|
|
||||||
|
if (!resumeData.useAutoTMM)
|
||||||
|
{
|
||||||
|
query.bindValue(DB_COLUMN_TARGET_SAVE_PATH.placeholder, Profile::instance()->toPortablePath(resumeData.savePath));
|
||||||
|
query.bindValue(DB_COLUMN_DOWNLOAD_PATH.placeholder, Profile::instance()->toPortablePath(resumeData.downloadPath));
|
||||||
|
}
|
||||||
|
|
||||||
query.bindValue(DB_COLUMN_RESUMEDATA.placeholder, bencodedResumeData);
|
query.bindValue(DB_COLUMN_RESUMEDATA.placeholder, bencodedResumeData);
|
||||||
if (!bencodedMetadata.isEmpty())
|
if (!bencodedMetadata.isEmpty())
|
||||||
query.bindValue(DB_COLUMN_METADATA.placeholder, bencodedMetadata);
|
query.bindValue(DB_COLUMN_METADATA.placeholder, bencodedMetadata);
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ namespace BitTorrent
|
|||||||
void storeQueue(const QVector<TorrentID> &queue) const override;
|
void storeQueue(const QVector<TorrentID> &queue) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int currentDBVersion() const;
|
||||||
void createDB() const;
|
void createDB() const;
|
||||||
|
void updateDBFromVersion1() const;
|
||||||
|
|
||||||
QThread *m_ioThread = nullptr;
|
QThread *m_ioThread = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include "base/bittorrent/infohash.h"
|
#include "base/bittorrent/infohash.h"
|
||||||
|
|
||||||
void FileSearcher::search(const BitTorrent::TorrentID &id, const QStringList &originalFileNames
|
void FileSearcher::search(const BitTorrent::TorrentID &id, const QStringList &originalFileNames
|
||||||
, const QString &completeSavePath, const QString &incompleteSavePath)
|
, const QString &savePath, const QString &downloadPath)
|
||||||
{
|
{
|
||||||
const auto findInDir = [](const QString &dirPath, QStringList &fileNames) -> bool
|
const auto findInDir = [](const QString &dirPath, QStringList &fileNames) -> bool
|
||||||
{
|
{
|
||||||
@@ -56,14 +56,14 @@ void FileSearcher::search(const BitTorrent::TorrentID &id, const QStringList &or
|
|||||||
return found;
|
return found;
|
||||||
};
|
};
|
||||||
|
|
||||||
QString savePath = completeSavePath;
|
QString usedPath = savePath;
|
||||||
QStringList adjustedFileNames = originalFileNames;
|
QStringList adjustedFileNames = originalFileNames;
|
||||||
const bool found = findInDir(savePath, adjustedFileNames);
|
const bool found = findInDir(usedPath, adjustedFileNames);
|
||||||
if (!found && !incompleteSavePath.isEmpty())
|
if (!found && !downloadPath.isEmpty())
|
||||||
{
|
{
|
||||||
savePath = incompleteSavePath;
|
usedPath = downloadPath;
|
||||||
findInDir(savePath, adjustedFileNames);
|
findInDir(usedPath, adjustedFileNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit searchFinished(id, savePath, adjustedFileNames);
|
emit searchFinished(id, usedPath, adjustedFileNames);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void search(const BitTorrent::TorrentID &id, const QStringList &originalFileNames
|
void search(const BitTorrent::TorrentID &id, const QStringList &originalFileNames
|
||||||
, const QString &completeSavePath, const QString &incompleteSavePath);
|
, const QString &savePath, const QString &downloadPath);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void searchFinished(const BitTorrent::TorrentID &id, const QString &savePath, const QStringList &fileNames);
|
void searchFinished(const BitTorrent::TorrentID &id, const QString &savePath, const QStringList &fileNames);
|
||||||
|
|||||||
@@ -36,6 +36,13 @@ BitTorrent::InfoHash::InfoHash(const WrappedType &nativeHash)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
BitTorrent::InfoHash::InfoHash(const SHA1Hash &v1, const SHA256Hash &v2)
|
||||||
|
: InfoHash {WrappedType(v1, v2)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool BitTorrent::InfoHash::isValid() const
|
bool BitTorrent::InfoHash::isValid() const
|
||||||
{
|
{
|
||||||
return m_valid;
|
return m_valid;
|
||||||
|
|||||||
@@ -64,8 +64,10 @@ namespace BitTorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
InfoHash() = default;
|
InfoHash() = default;
|
||||||
InfoHash(const InfoHash &other) = default;
|
|
||||||
InfoHash(const WrappedType &nativeHash);
|
InfoHash(const WrappedType &nativeHash);
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
InfoHash(const SHA1Hash &v1, const SHA256Hash &v2);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
SHA1Hash v1() const;
|
SHA1Hash v1() const;
|
||||||
@@ -86,3 +88,6 @@ namespace BitTorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(BitTorrent::TorrentID)
|
Q_DECLARE_METATYPE(BitTorrent::TorrentID)
|
||||||
|
// We can declare it as Q_MOVABLE_TYPE to improve performance
|
||||||
|
// since base type uses QSharedDataPointer as the only member
|
||||||
|
Q_DECLARE_TYPEINFO(BitTorrent::TorrentID, Q_MOVABLE_TYPE);
|
||||||
|
|||||||
@@ -46,8 +46,10 @@ namespace BitTorrent
|
|||||||
QString category;
|
QString category;
|
||||||
TagSet tags;
|
TagSet tags;
|
||||||
QString savePath;
|
QString savePath;
|
||||||
|
QString downloadPath;
|
||||||
TorrentContentLayout contentLayout = TorrentContentLayout::Original;
|
TorrentContentLayout contentLayout = TorrentContentLayout::Original;
|
||||||
TorrentOperatingMode operatingMode = TorrentOperatingMode::AutoManaged;
|
TorrentOperatingMode operatingMode = TorrentOperatingMode::AutoManaged;
|
||||||
|
bool useAutoTMM = false;
|
||||||
bool firstLastPiecePriority = false;
|
bool firstLastPiecePriority = false;
|
||||||
bool hasSeedStatus = false;
|
bool hasSeedStatus = false;
|
||||||
bool stopped = false;
|
bool stopped = false;
|
||||||
|
|||||||
@@ -34,6 +34,9 @@
|
|||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
|
||||||
|
// From https://doc.qt.io/qt-6/qhash.html#the-hashing-function:
|
||||||
|
// A hashing function for a key type K may be provided in two different ways.
|
||||||
|
// The first way is by having an overload of qHash() in K's namespace.
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
namespace aux
|
namespace aux
|
||||||
|
|||||||
52
src/base/bittorrent/lttypecast.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2019, 2021 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libtorrent/download_priority.hpp>
|
||||||
|
|
||||||
|
#include "downloadpriority.h"
|
||||||
|
|
||||||
|
namespace BitTorrent::LT
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
constexpr typename T::underlying_type toUnderlyingType(const T &t) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<typename T::underlying_type>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr lt::download_priority_t toNative(const DownloadPriority priority) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<lt::download_priority_t>(static_cast<lt::download_priority_t::underlying_type>(priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr DownloadPriority fromNative(const lt::download_priority_t priority) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<DownloadPriority>(toUnderlyingType(priority));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@ namespace
|
|||||||
NativeTorrentExtension::NativeTorrentExtension(const lt::torrent_handle &torrentHandle)
|
NativeTorrentExtension::NativeTorrentExtension(const lt::torrent_handle &torrentHandle)
|
||||||
: m_torrentHandle {torrentHandle}
|
: m_torrentHandle {torrentHandle}
|
||||||
{
|
{
|
||||||
|
on_state(m_torrentHandle.status({}).state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeTorrentExtension::on_pause()
|
bool NativeTorrentExtension::on_pause()
|
||||||
@@ -56,7 +57,10 @@ bool NativeTorrentExtension::on_pause()
|
|||||||
void NativeTorrentExtension::on_state(const lt::torrent_status::state_t state)
|
void NativeTorrentExtension::on_state(const lt::torrent_status::state_t state)
|
||||||
{
|
{
|
||||||
if (m_state == lt::torrent_status::downloading_metadata)
|
if (m_state == lt::torrent_status::downloading_metadata)
|
||||||
m_torrentHandle.set_flags(lt::torrent_flags::stop_when_ready);
|
{
|
||||||
|
m_torrentHandle.unset_flags(lt::torrent_flags::auto_managed);
|
||||||
|
m_torrentHandle.pause();
|
||||||
|
}
|
||||||
|
|
||||||
m_state = state;
|
m_state = state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,16 +33,13 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/settingsstorage.h"
|
|
||||||
|
|
||||||
const QString KEY_ENABLED = QStringLiteral("Network/PortForwardingEnabled");
|
|
||||||
|
|
||||||
PortForwarderImpl::PortForwarderImpl(lt::session *provider, QObject *parent)
|
PortForwarderImpl::PortForwarderImpl(lt::session *provider, QObject *parent)
|
||||||
: Net::PortForwarder {parent}
|
: Net::PortForwarder {parent}
|
||||||
, m_active {SettingsStorage::instance()->loadValue(KEY_ENABLED, true)}
|
, m_storeActive {"Network/PortForwardingEnabled", true}
|
||||||
, m_provider {provider}
|
, m_provider {provider}
|
||||||
{
|
{
|
||||||
if (m_active)
|
if (isEnabled())
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,20 +50,19 @@ PortForwarderImpl::~PortForwarderImpl()
|
|||||||
|
|
||||||
bool PortForwarderImpl::isEnabled() const
|
bool PortForwarderImpl::isEnabled() const
|
||||||
{
|
{
|
||||||
return m_active;
|
return m_storeActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortForwarderImpl::setEnabled(const bool enabled)
|
void PortForwarderImpl::setEnabled(const bool enabled)
|
||||||
{
|
{
|
||||||
if (m_active != enabled)
|
if (m_storeActive != enabled)
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (enabled)
|
||||||
start();
|
start();
|
||||||
else
|
else
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
m_active = enabled;
|
m_storeActive = enabled;
|
||||||
SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
|
||||||
#include "base/net/portforwarder.h"
|
#include "base/net/portforwarder.h"
|
||||||
|
#include "base/settingvalue.h"
|
||||||
|
|
||||||
class PortForwarderImpl final : public Net::PortForwarder
|
class PortForwarderImpl final : public Net::PortForwarder
|
||||||
{
|
{
|
||||||
@@ -56,7 +57,7 @@ private:
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
bool m_active;
|
CachedSettingValue<bool> m_storeActive;
|
||||||
lt::session *m_provider;
|
lt::session *m_provider;
|
||||||
QHash<quint16, std::vector<lt::port_mapping_t>> m_mappedPorts;
|
QHash<quint16, std::vector<lt::port_mapping_t>> m_mappedPorts;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "base/types.h"
|
#include "base/types.h"
|
||||||
#include "addtorrentparams.h"
|
#include "addtorrentparams.h"
|
||||||
#include "cachestatus.h"
|
#include "cachestatus.h"
|
||||||
|
#include "categoryoptions.h"
|
||||||
#include "sessionstatus.h"
|
#include "sessionstatus.h"
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
#include "trackerentry.h"
|
#include "trackerentry.h"
|
||||||
@@ -211,22 +212,23 @@ namespace BitTorrent
|
|||||||
static void freeInstance();
|
static void freeInstance();
|
||||||
static Session *instance();
|
static Session *instance();
|
||||||
|
|
||||||
QString defaultSavePath() const;
|
QString savePath() const;
|
||||||
void setDefaultSavePath(QString path);
|
void setSavePath(const QString &path);
|
||||||
QString tempPath() const;
|
QString downloadPath() const;
|
||||||
void setTempPath(QString path);
|
void setDownloadPath(const QString &path);
|
||||||
bool isTempPathEnabled() const;
|
bool isDownloadPathEnabled() const;
|
||||||
void setTempPathEnabled(bool enabled);
|
void setDownloadPathEnabled(bool enabled);
|
||||||
QString torrentTempPath(const TorrentInfo &torrentInfo) const;
|
|
||||||
|
|
||||||
static bool isValidCategoryName(const QString &name);
|
static bool isValidCategoryName(const QString &name);
|
||||||
// returns category itself and all top level categories
|
// returns category itself and all top level categories
|
||||||
static QStringList expandCategory(const QString &category);
|
static QStringList expandCategory(const QString &category);
|
||||||
|
|
||||||
QStringMap categories() const;
|
QStringList categories() const;
|
||||||
|
CategoryOptions categoryOptions(const QString &categoryName) const;
|
||||||
QString categorySavePath(const QString &categoryName) const;
|
QString categorySavePath(const QString &categoryName) const;
|
||||||
bool addCategory(const QString &name, const QString &savePath = "");
|
QString categoryDownloadPath(const QString &categoryName) const;
|
||||||
bool editCategory(const QString &name, const QString &savePath);
|
bool addCategory(const QString &name, const CategoryOptions &options = {});
|
||||||
|
bool editCategory(const QString &name, const CategoryOptions &options);
|
||||||
bool removeCategory(const QString &name);
|
bool removeCategory(const QString &name);
|
||||||
bool isSubcategoriesEnabled() const;
|
bool isSubcategoriesEnabled() const;
|
||||||
void setSubcategoriesEnabled(bool value);
|
void setSubcategoriesEnabled(bool value);
|
||||||
@@ -499,7 +501,8 @@ namespace BitTorrent
|
|||||||
|
|
||||||
bool addMoveTorrentStorageJob(TorrentImpl *torrent, const QString &newPath, MoveStorageMode mode);
|
bool addMoveTorrentStorageJob(TorrentImpl *torrent, const QString &newPath, MoveStorageMode mode);
|
||||||
|
|
||||||
void findIncompleteFiles(const TorrentInfo &torrentInfo, const QString &savePath) const;
|
void findIncompleteFiles(const TorrentInfo &torrentInfo, const QString &savePath
|
||||||
|
, const QString &downloadPath, const QStringList &filePaths = {}) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void allTorrentsFinished();
|
void allTorrentsFinished();
|
||||||
@@ -642,6 +645,10 @@ namespace BitTorrent
|
|||||||
void moveTorrentStorage(const MoveStorageJob &job) const;
|
void moveTorrentStorage(const MoveStorageJob &job) const;
|
||||||
void handleMoveTorrentStorageJobFinished();
|
void handleMoveTorrentStorageJobFinished();
|
||||||
|
|
||||||
|
void loadCategories();
|
||||||
|
void storeCategories() const;
|
||||||
|
void upgradeCategories();
|
||||||
|
|
||||||
// BitTorrent
|
// BitTorrent
|
||||||
lt::session *m_nativeSession = nullptr;
|
lt::session *m_nativeSession = nullptr;
|
||||||
|
|
||||||
@@ -729,13 +736,12 @@ namespace BitTorrent
|
|||||||
CachedSettingValue<bool> m_isProxyPeerConnectionsEnabled;
|
CachedSettingValue<bool> m_isProxyPeerConnectionsEnabled;
|
||||||
CachedSettingValue<ChokingAlgorithm> m_chokingAlgorithm;
|
CachedSettingValue<ChokingAlgorithm> m_chokingAlgorithm;
|
||||||
CachedSettingValue<SeedChokingAlgorithm> m_seedChokingAlgorithm;
|
CachedSettingValue<SeedChokingAlgorithm> m_seedChokingAlgorithm;
|
||||||
CachedSettingValue<QVariantMap> m_storedCategories;
|
|
||||||
CachedSettingValue<QStringList> m_storedTags;
|
CachedSettingValue<QStringList> m_storedTags;
|
||||||
CachedSettingValue<int> m_maxRatioAction;
|
CachedSettingValue<int> m_maxRatioAction;
|
||||||
CachedSettingValue<QString> m_defaultSavePath;
|
CachedSettingValue<QString> m_savePath;
|
||||||
CachedSettingValue<QString> m_tempPath;
|
CachedSettingValue<QString> m_downloadPath;
|
||||||
CachedSettingValue<bool> m_isSubcategoriesEnabled;
|
CachedSettingValue<bool> m_isSubcategoriesEnabled;
|
||||||
CachedSettingValue<bool> m_isTempPathEnabled;
|
CachedSettingValue<bool> m_isDownloadPathEnabled;
|
||||||
CachedSettingValue<bool> m_isAutoTMMDisabledByDefault;
|
CachedSettingValue<bool> m_isAutoTMMDisabledByDefault;
|
||||||
CachedSettingValue<bool> m_isDisableAutoTMMWhenCategoryChanged;
|
CachedSettingValue<bool> m_isDisableAutoTMMWhenCategoryChanged;
|
||||||
CachedSettingValue<bool> m_isDisableAutoTMMWhenDefaultSavePathChanged;
|
CachedSettingValue<bool> m_isDisableAutoTMMWhenDefaultSavePathChanged;
|
||||||
@@ -780,7 +786,7 @@ namespace BitTorrent
|
|||||||
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
||||||
QHash<TorrentID, RemovingTorrentData> m_removingTorrents;
|
QHash<TorrentID, RemovingTorrentData> m_removingTorrents;
|
||||||
QSet<TorrentID> m_needSaveResumeDataTorrents;
|
QSet<TorrentID> m_needSaveResumeDataTorrents;
|
||||||
QStringMap m_categories;
|
QMap<QString, CategoryOptions> m_categories;
|
||||||
QSet<QString> m_tags;
|
QSet<QString> m_tags;
|
||||||
|
|
||||||
// I/O errored torrents
|
// I/O errored torrents
|
||||||
@@ -800,6 +806,8 @@ namespace BitTorrent
|
|||||||
|
|
||||||
QString m_lastExternalIP;
|
QString m_lastExternalIP;
|
||||||
|
|
||||||
|
bool m_needUpgradeDownloadPath = false;
|
||||||
|
|
||||||
static Session *m_instance;
|
static Session *m_instance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||