mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-06 15:42:32 -06:00
Compare commits
221 Commits
release-4.
...
release-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
2b501904cf | ||
|
|
ea986a1f1b | ||
|
|
b924357ea9 | ||
|
|
b823d74ac3 | ||
|
|
d1e2019cd7 | ||
|
|
70573eba2c | ||
|
|
cf46653333 | ||
|
|
8d3fcbd897 | ||
|
|
1900538315 | ||
|
|
a9feae6110 | ||
|
|
8d822f2cb4 | ||
|
|
c12e486f59 | ||
|
|
d0d0bed333 | ||
|
|
8799321312 | ||
|
|
00d2997971 | ||
|
|
69f7f233fd | ||
|
|
793e8643bf | ||
|
|
521ef8e28f | ||
|
|
7433d85418 | ||
|
|
ba1cf12817 | ||
|
|
7dc7b95bfd | ||
|
|
59352e4ca7 | ||
|
|
011d026d76 | ||
|
|
89a8184ad2 | ||
|
|
a23e10dff5 | ||
|
|
535603fac4 | ||
|
|
fb6282da57 | ||
|
|
23766cd01d | ||
|
|
44b2afb218 | ||
|
|
9e82e59fc8 | ||
|
|
e006538514 | ||
|
|
fad5dfa4f4 | ||
|
|
b737ee0240 | ||
|
|
9d9f774dad | ||
|
|
526ee9c9db | ||
|
|
671eff324d | ||
|
|
a93cf04aca | ||
|
|
e93a67e644 | ||
|
|
b29a52dfa8 | ||
|
|
4ed99ba851 | ||
|
|
3e92e716b2 | ||
|
|
c6c8f6563d | ||
|
|
138c911ef4 | ||
|
|
e5fe6401a0 | ||
|
|
bed643e627 | ||
|
|
4ac25a50ed | ||
|
|
d9cf189ef6 | ||
|
|
6e19878973 | ||
|
|
9f9c4d6ed0 | ||
|
|
567848e94f | ||
|
|
221cbcc1ac | ||
|
|
dc2086dab4 | ||
|
|
7be2a03c86 | ||
|
|
e87f8f5b93 | ||
|
|
11a063ea66 | ||
|
|
1d26f4c5f7 | ||
|
|
8a09558ed8 | ||
|
|
60b1e692b9 | ||
|
|
0a1865d0dd | ||
|
|
3d94c70c48 | ||
|
|
7d7f967d5e | ||
|
|
ce554e6c77 | ||
|
|
5d151cca9d | ||
|
|
e47d90b5a6 | ||
|
|
e4730191db | ||
|
|
49aab492e0 | ||
|
|
2d4d246268 | ||
|
|
09e558ae0b | ||
|
|
a3fd6633c4 | ||
|
|
1eb246c98b | ||
|
|
96e0c0df20 | ||
|
|
aa8f420681 | ||
|
|
7974b5a95c | ||
|
|
ed4570cb4d | ||
|
|
01d851440b | ||
|
|
e5943b64c1 | ||
|
|
933e56494c | ||
|
|
140e73be4e | ||
|
|
960b9b855f | ||
|
|
1e1d55b26d | ||
|
|
925bf7715c | ||
|
|
399d3ad85a | ||
|
|
d923c03d52 | ||
|
|
699b91ab8d | ||
|
|
abd6eb2ff3 | ||
|
|
32f29e72c6 | ||
|
|
e76bac4131 | ||
|
|
8b94642ab1 | ||
|
|
d3497148c5 | ||
|
|
27baa55443 | ||
|
|
fd3d4d479a | ||
|
|
4b0a2d050a | ||
|
|
d85c14864b | ||
|
|
ee696e6f36 | ||
|
|
6ccbd8472c | ||
|
|
8ec26e9ea9 | ||
|
|
45e31a153c | ||
|
|
7c23d800e6 | ||
|
|
4dbf6af733 | ||
|
|
bdc03b1c75 | ||
|
|
9bfc74a1bc | ||
|
|
5d03917877 | ||
|
|
d2f975a0f3 | ||
|
|
eedd47860a | ||
|
|
6e59248ea6 | ||
|
|
365554d064 | ||
|
|
70d1cb86fd | ||
|
|
ccb7c0d579 | ||
|
|
fd9941e2d8 | ||
|
|
2f89563fca | ||
|
|
261f601bd5 | ||
|
|
5157e4965a |
@@ -43,7 +43,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 (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||||
- SET PATH=%PATH%;c:\qbt\qt5_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%"
|
||||||
# workarounds
|
# workarounds
|
||||||
|
|||||||
89
.github/ISSUE_TEMPLATE/bug_report.md
vendored
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
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
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
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
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
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
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
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())
|
||||||
254
.github/workflows/ci.yaml
vendored
254
.github/workflows/ci.yaml
vendored
@@ -1,254 +0,0 @@
|
|||||||
name: GitHub Actions CI
|
|
||||||
|
|
||||||
# Cache is used for all Windows and macOS dependencies (size approx. 1230 * 2 + 1850 = 4310 MiB)
|
|
||||||
# Cache is not used for Ubuntu builds, because it already has all dependencies except
|
|
||||||
# the appropriate libtorrent version, which only takes 3-5 minutes to build from source anyway
|
|
||||||
|
|
||||||
on: [pull_request, push]
|
|
||||||
|
|
||||||
env:
|
|
||||||
VCPKG_COMMIT: 8f03e2264da6b95fa5b01dd89cdd5b499458d428
|
|
||||||
VCPKG_DEST_MACOS: /Users/runner/qbt_tools/vcpkg
|
|
||||||
VCPKG_DEST_WIN: C:\qbt_tools\vcpkg
|
|
||||||
LIBTORRENT_VERSION_TAG: v1.2.13
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
ci_ubuntu:
|
|
||||||
name: Ubuntu
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-20.04]
|
|
||||||
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
|
||||||
fail-fast: false
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: install all build dependencies except libtorrent from Ubuntu repos
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install \
|
|
||||||
build-essential cmake git ninja-build pkg-config \
|
|
||||||
libssl-dev libgeoip-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...
|
|
||||||
|
|
||||||
# this will be installed under /opt/qt514. CMake will still find it automatically without additional hints
|
|
||||||
# to speed up the process, only the required components are installed rather than the full qt514-meta-full metapackage
|
|
||||||
- name: install Qt 5.14.2 from an external PPA
|
|
||||||
run: |
|
|
||||||
sudo add-apt-repository ppa:beineri/opt-qt-5.14.2-focal
|
|
||||||
sudo apt install qt514base qt514svg qt514tools
|
|
||||||
|
|
||||||
- name: install libtorrent from source
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/arvidn/libtorrent && cd libtorrent
|
|
||||||
git checkout ${{ env.LIBTORRENT_VERSION_TAG }}
|
|
||||||
cmake -B cmake-build-dir -G "Ninja" \
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-Ddeprecated-functions=OFF \
|
|
||||||
--graphviz=cmake-build-dir/target_graph.dot
|
|
||||||
cmake --build cmake-build-dir
|
|
||||||
sudo cmake --install cmake-build-dir --prefix /usr/local
|
|
||||||
|
|
||||||
- name: build qBittorrent
|
|
||||||
run: |
|
|
||||||
cmake -B build -G "Ninja" \
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-D${{ matrix.qbt_gui }} \
|
|
||||||
-DVERBOSE_CONFIGURE=ON \
|
|
||||||
--graphviz=build/target_graph.dot
|
|
||||||
cmake --build build
|
|
||||||
|
|
||||||
- name: install qBittorrent
|
|
||||||
run: sudo cmake --install build --prefix /usr/local
|
|
||||||
|
|
||||||
- name: upload artifact as zip
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: qBittorrent-CI_${{ matrix.os }}-x64_${{ matrix.qbt_gui }}
|
|
||||||
path: |
|
|
||||||
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
|
|
||||||
|
|
||||||
ci_windows:
|
|
||||||
name: Windows + vcpkg
|
|
||||||
|
|
||||||
runs-on: windows-2019
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: pwsh
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# - ninja is needed for building qBittorrent (because it's preferable, not a hard requirement)
|
|
||||||
- name: install additional required packages with chocolatey
|
|
||||||
run: |
|
|
||||||
choco install ninja
|
|
||||||
|
|
||||||
- name: setup vcpkg (cached, if possible)
|
|
||||||
uses: lukka/run-vcpkg@v7
|
|
||||||
with:
|
|
||||||
vcpkgDirectory: ${{ env.VCPKG_DEST_WIN }}
|
|
||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT }}
|
|
||||||
setupOnly: true
|
|
||||||
|
|
||||||
# Tell vcpkg to only build Release variants of the dependencies
|
|
||||||
- name: configure vcpkg triplet overlay for release builds only
|
|
||||||
run: |
|
|
||||||
New-Item -Path ${{ github.workspace }} -Name "triplets_overlay" -ItemType Directory
|
|
||||||
Copy-Item ${{ env.RUNVCPKG_VCPKG_ROOT }}/triplets/x64-windows-static.cmake `
|
|
||||||
${{ github.workspace }}/triplets_overlay/x64-windows-static-release.cmake
|
|
||||||
Add-Content ${{ github.workspace }}/triplets_overlay/x64-windows-static-release.cmake `
|
|
||||||
-Value "set(VCPKG_BUILD_TYPE release)"
|
|
||||||
|
|
||||||
# clear buildtrees after each package installation to reduce disk space requirements
|
|
||||||
- name: install dependencies via vcpkg
|
|
||||||
run: |
|
|
||||||
$packages = `
|
|
||||||
"boost-circular-buffer:x64-windows-static-release",
|
|
||||||
"libtorrent: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 `
|
|
||||||
--overlay-triplets=${{ github.workspace }}/triplets_overlay `
|
|
||||||
--no-dry-run
|
|
||||||
foreach($package in $packages)
|
|
||||||
{
|
|
||||||
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg.exe install $package `
|
|
||||||
--overlay-triplets=${{ github.workspace }}/triplets_overlay `
|
|
||||||
--clean-after-build
|
|
||||||
}
|
|
||||||
|
|
||||||
# NOTE: this is necessary to correctly find and use cl.exe with the Ninja generator for now
|
|
||||||
- name: setup devcmd
|
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
|
||||||
|
|
||||||
- name: build qBittorrent
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
cmake -B build -G "Ninja" ^
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo ^
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_DEST_WIN }}\scripts\buildsystems\vcpkg.cmake ^
|
|
||||||
-DVCPKG_TARGET_TRIPLET=x64-windows-static-release ^
|
|
||||||
-DVERBOSE_CONFIGURE=ON ^
|
|
||||||
-DMSVC_RUNTIME_DYNAMIC=OFF ^
|
|
||||||
--graphviz=build\target_graph.dot
|
|
||||||
cmake --build build
|
|
||||||
|
|
||||||
- name: upload artifact as zip
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: qBittorrent-CI_Windows-x64
|
|
||||||
path: |
|
|
||||||
build/compile_commands.json
|
|
||||||
build/target_graph.dot
|
|
||||||
build/qbittorrent.exe
|
|
||||||
build/qbittorrent.pdb
|
|
||||||
dist/windows/qt.conf
|
|
||||||
|
|
||||||
ci_macos:
|
|
||||||
name: macOS + vcpkg
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
|
||||||
fail-fast: false
|
|
||||||
|
|
||||||
runs-on: macos-10.15
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: pwsh
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# - ninja is needed for building qBittorrent (because it's preferable, not a hard requirement)
|
|
||||||
# - automake is needed for the installation the vcpkg installation of fontconfig, a dependency of qt5-base
|
|
||||||
- name: install additional required packages with homebrew
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
brew install automake ninja
|
|
||||||
|
|
||||||
- name: setup vcpkg (cached, if possible)
|
|
||||||
uses: lukka/run-vcpkg@v7
|
|
||||||
with:
|
|
||||||
vcpkgDirectory: ${{ env.VCPKG_DEST_MACOS }}
|
|
||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT }}
|
|
||||||
setupOnly: true
|
|
||||||
|
|
||||||
- name: configure vcpkg triplet overlay for release builds only
|
|
||||||
run: |
|
|
||||||
New-Item -Path ${{ github.workspace }} -Name "triplets_overlay" -ItemType Directory
|
|
||||||
Copy-Item ${{ env.RUNVCPKG_VCPKG_ROOT }}/triplets/x64-osx.cmake `
|
|
||||||
${{ github.workspace }}/triplets_overlay/x64-osx-release.cmake
|
|
||||||
Add-Content ${{ github.workspace }}/triplets_overlay/x64-osx-release.cmake `
|
|
||||||
-Value "set(VCPKG_BUILD_TYPE release)","set(VCPKG_OSX_DEPLOYMENT_TARGET 10.15)"
|
|
||||||
|
|
||||||
# NOTE: Avoids a libtorrent ABI issue. See https://github.com/arvidn/libtorrent/issues/4965
|
|
||||||
- name: force AppleClang to compile libtorrent with the same C++ standard as qBittorrent
|
|
||||||
run: |
|
|
||||||
(Get-Content -path ${{ env.RUNVCPKG_VCPKG_ROOT }}/ports/libtorrent/portfile.cmake).Replace( `
|
|
||||||
'${FEATURE_OPTIONS}', '${FEATURE_OPTIONS} -DCMAKE_CXX_STANDARD=17') `
|
|
||||||
| Set-Content -Path ${{ env.RUNVCPKG_VCPKG_ROOT }}/ports/libtorrent/portfile.cmake
|
|
||||||
|
|
||||||
- name: install dependencies via vcpkg
|
|
||||||
run: |
|
|
||||||
$packages = `
|
|
||||||
"boost-circular-buffer:x64-osx-release",
|
|
||||||
"libtorrent:x64-osx-release",
|
|
||||||
"qt5-base:x64-osx-release",
|
|
||||||
"qt5-svg:x64-osx-release",
|
|
||||||
"qt5-tools:x64-osx-release",
|
|
||||||
"qt5-macextras:x64-osx-release"
|
|
||||||
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg upgrade `
|
|
||||||
--overlay-triplets=${{ github.workspace }}/triplets_overlay `
|
|
||||||
--no-dry-run
|
|
||||||
foreach($package in $packages)
|
|
||||||
{
|
|
||||||
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg install $package `
|
|
||||||
--overlay-triplets=${{ github.workspace }}/triplets_overlay `
|
|
||||||
--clean-after-build
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: build qBittorrent
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cmake -B build -G "Ninja" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_DEST_MACOS }}/scripts/buildsystems/vcpkg.cmake \
|
|
||||||
-DVCPKG_TARGET_TRIPLET=x64-osx-release \
|
|
||||||
-D${{ matrix.qbt_gui }} \
|
|
||||||
-DVERBOSE_CONFIGURE=ON \
|
|
||||||
--graphviz=build/target_graph.dot
|
|
||||||
cmake --build build
|
|
||||||
|
|
||||||
- name: upload artifact as zip
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: qBittorrent-CI_macOS_${{ matrix.qbt_gui }}
|
|
||||||
path: |
|
|
||||||
build/compile_commands.json
|
|
||||||
build/target_graph.dot
|
|
||||||
build/qbittorrent.app
|
|
||||||
build/qbittorrent-nox.app
|
|
||||||
17
.github/workflows/ci_file_health.yaml
vendored
Normal file
17
.github/workflows/ci_file_health.yaml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: CI - File health
|
||||||
|
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install tools
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
|
||||||
|
- name: Check files
|
||||||
|
uses: pre-commit/action@v2.0.3
|
||||||
91
.github/workflows/ci_macos.yaml
vendored
Normal file
91
.github/workflows/ci_macos.yaml
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
name: CI - macOS
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: Build
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
libt_version: ["2.0.4", "1.2.14"]
|
||||||
|
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
||||||
|
qt_version: ["5.15.2", "6.2.0"]
|
||||||
|
exclude:
|
||||||
|
- libt_version: "1.2.14"
|
||||||
|
qt_version: "6.2.0"
|
||||||
|
|
||||||
|
env:
|
||||||
|
openssl_root: /usr/local/opt/openssl@1.1
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
brew update > /dev/null
|
||||||
|
brew install \
|
||||||
|
cmake ninja \
|
||||||
|
boost openssl@1.1 zlib
|
||||||
|
|
||||||
|
- name: Setup ccache
|
||||||
|
uses: Chocobo1/setup-ccache-action@v1
|
||||||
|
with:
|
||||||
|
update_packager_index: false
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v2
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.qt_version }}
|
||||||
|
|
||||||
|
- name: Install libtorrent
|
||||||
|
run: |
|
||||||
|
git clone --branch v${{ matrix.libt_version }} --depth 1 https://github.com/arvidn/libtorrent.git
|
||||||
|
cd libtorrent
|
||||||
|
git submodule update --init --recursive
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_CXX_STANDARD=17 \
|
||||||
|
-Ddeprecated-functions=OFF \
|
||||||
|
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}"
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
|
||||||
|
- name: Build qBittorrent (Qt5)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 5) }}
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}" \
|
||||||
|
-DQt5_DIR="$Qt5_DIR" \
|
||||||
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
|
-D${{ matrix.qbt_gui }}
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Build qBittorrent (Qt6)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 6) }}
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DOPENSSL_ROOT_DIR="${{ env.openssl_root }}" \
|
||||||
|
-DQT6=ON \
|
||||||
|
-DQt6_DIR="$Qt6_DIR" \
|
||||||
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
|
-D${{ matrix.qbt_gui }}
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: qBittorrent-CI_macOS_${{ matrix.qbt_gui }}_libtorrent-${{ matrix.libt_version }}_Qt-${{ matrix.qt_version }}
|
||||||
|
path: |
|
||||||
|
build/qbittorrent.app
|
||||||
|
build/qbittorrent-nox.app
|
||||||
99
.github/workflows/ci_ubuntu.yaml
vendored
Normal file
99
.github/workflows/ci_ubuntu.yaml
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
name: CI - Ubuntu
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
libt_version: ["2.0.4", "1.2.14"]
|
||||||
|
qbt_gui: ["GUI=ON", "GUI=OFF"]
|
||||||
|
qt_version: ["5.15.2", "6.2.0"]
|
||||||
|
exclude:
|
||||||
|
- libt_version: "1.2.14"
|
||||||
|
qt_version: "6.2.0"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install \
|
||||||
|
build-essential cmake ninja-build pkg-config \
|
||||||
|
libboost-dev libssl-dev zlib1g-dev
|
||||||
|
|
||||||
|
- name: Setup ccache
|
||||||
|
uses: Chocobo1/setup-ccache-action@v1
|
||||||
|
with:
|
||||||
|
update_packager_index: false
|
||||||
|
ccache_options: |
|
||||||
|
max_size=2G
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v2
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.qt_version }}
|
||||||
|
|
||||||
|
- name: Install libtorrent
|
||||||
|
run: |
|
||||||
|
git clone --branch v${{ matrix.libt_version }} --depth 1 https://github.com/arvidn/libtorrent.git
|
||||||
|
cd libtorrent
|
||||||
|
git submodule update --init --recursive
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-Ddeprecated-functions=OFF \
|
||||||
|
--graphviz=cmake-build-dir/target_graph.dot
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
|
||||||
|
- name: Build qBittorrent (Qt5)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 5) }}
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DQt5_DIR="$Qt5_DIR" \
|
||||||
|
-D${{ matrix.qbt_gui }} \
|
||||||
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
|
--graphviz=build/target_graph.dot
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
|
||||||
|
- name: Build qBittorrent (Qt6)
|
||||||
|
if: ${{ startsWith(matrix.qt_version, 6) }}
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DQt6_DIR="$Qt6_DIR" \
|
||||||
|
-DQT6=ON \
|
||||||
|
-D${{ matrix.qbt_gui }} \
|
||||||
|
-DVERBOSE_CONFIGURE=ON \
|
||||||
|
--graphviz=build/target_graph.dot
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: qBittorrent-CI_ubuntu-20.04-x64_${{ matrix.qbt_gui }}_libtorrent-${{ matrix.libt_version }}_Qt-${{ matrix.qt_version }}
|
||||||
|
path: |
|
||||||
|
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
|
||||||
32
.github/workflows/ci_webui.yaml
vendored
Normal file
32
.github/workflows/ci_webui.yaml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: CI - WebUI
|
||||||
|
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: src/webui/www
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup nodejs
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: 'lts/*'
|
||||||
|
|
||||||
|
- name: Install tools
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Lint code
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Format code
|
||||||
|
run: |
|
||||||
|
npm run format
|
||||||
|
git diff --exit-code
|
||||||
128
.github/workflows/ci_windows.yaml
vendored
Normal file
128
.github/workflows/ci_windows.yaml
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
name: CI - Windows
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: Build
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
libt_version: ["v2.0.4", "v1.2.14"]
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
boost_path: "${{ github.workspace }}/boost"
|
||||||
|
libtorrent_path: "${{ github.workspace }}/libtorrent"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup devcmd
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
|
||||||
|
- name: Install build tools
|
||||||
|
run: |
|
||||||
|
choco install ninja
|
||||||
|
|
||||||
|
# use the preinstalled vcpkg from image
|
||||||
|
# https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#package-management
|
||||||
|
- name: Setup vcpkg
|
||||||
|
uses: lukka/run-vcpkg@v7
|
||||||
|
with:
|
||||||
|
vcpkgDirectory: C:/vcpkg
|
||||||
|
doNotUpdateVcpkg: true # the preinstalled vcpkg is updated regularly
|
||||||
|
setupOnly: true
|
||||||
|
|
||||||
|
# tell vcpkg to only build Release variants of the dependencies
|
||||||
|
- name: Configure vcpkg triplet overlay
|
||||||
|
run: |
|
||||||
|
New-Item `
|
||||||
|
-Path "${{ github.workspace }}" `
|
||||||
|
-Name "triplets_overlay" `
|
||||||
|
-ItemType Directory
|
||||||
|
Copy-Item `
|
||||||
|
"${{ env.RUNVCPKG_VCPKG_ROOT }}/triplets/x64-windows-static.cmake" `
|
||||||
|
"${{ github.workspace }}/triplets_overlay/x64-windows-static-release.cmake"
|
||||||
|
Add-Content `
|
||||||
|
"${{ github.workspace }}/triplets_overlay/x64-windows-static-release.cmake" `
|
||||||
|
-Value "set(VCPKG_BUILD_TYPE release)"
|
||||||
|
|
||||||
|
# clear buildtrees after each package installation to reduce disk space requirements
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
$packages = `
|
||||||
|
"openssl: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",
|
||||||
|
"zlib:x64-windows-static-release"
|
||||||
|
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg.exe upgrade `
|
||||||
|
--overlay-triplets="${{ github.workspace }}/triplets_overlay" `
|
||||||
|
--no-dry-run
|
||||||
|
${{ env.RUNVCPKG_VCPKG_ROOT }}/vcpkg.exe install `
|
||||||
|
--overlay-triplets="${{ github.workspace }}/triplets_overlay" `
|
||||||
|
--clean-after-build `
|
||||||
|
$packages
|
||||||
|
|
||||||
|
- name: Install boost
|
||||||
|
run: |
|
||||||
|
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 libtorrent
|
||||||
|
run: |
|
||||||
|
git clone --branch ${{ matrix.libt_version }} --depth 1 https://github.com/arvidn/libtorrent.git
|
||||||
|
cd libtorrent
|
||||||
|
git submodule update --init --recursive
|
||||||
|
cmake `
|
||||||
|
-B build `
|
||||||
|
-G "Ninja" `
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
||||||
|
-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
|
||||||
|
run: |
|
||||||
|
cmake `
|
||||||
|
-B build `
|
||||||
|
-G "Ninja" `
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON `
|
||||||
|
-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 `
|
||||||
|
-DVCPKG_TARGET_TRIPLET=x64-windows-static-release `
|
||||||
|
-DVERBOSE_CONFIGURE=ON `
|
||||||
|
--graphviz=build/target_graph.dot
|
||||||
|
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
|
||||||
|
mkdir upload/cmake
|
||||||
|
copy build/compile_commands.json upload/cmake
|
||||||
|
copy build/target_graph.dot upload/cmake
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: qBittorrent-CI_Windows-x64_libtorrent-${{ matrix.libt_version }}
|
||||||
|
path: upload
|
||||||
67
.github/workflows/coverity-scan.yml
vendored
Normal file
67
.github/workflows/coverity-scan.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
name: Coverity Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 1 * *' # Monthly (1st day of month at midnight)
|
||||||
|
workflow_dispatch: # Mainly for testing. Don't forget the Coverity usage limits.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverity_scan:
|
||||||
|
name: Scan
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-focal
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install \
|
||||||
|
build-essential cmake ninja-build pkg-config \
|
||||||
|
libboost-dev libssl-dev qt515base qt515svg qt515tools zlib1g-dev
|
||||||
|
|
||||||
|
- name: Install libtorrent
|
||||||
|
run: |
|
||||||
|
git clone --branch v2.0.4 --depth 1 https://github.com/arvidn/libtorrent.git
|
||||||
|
cd libtorrent
|
||||||
|
git submodule update --init --recursive
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-Ddeprecated-functions=OFF
|
||||||
|
cmake --build build
|
||||||
|
sudo cmake --install build
|
||||||
|
|
||||||
|
- name: Download Coverity Build Tool
|
||||||
|
run: |
|
||||||
|
wget \
|
||||||
|
-q \
|
||||||
|
https://scan.coverity.com/download/linux64 \
|
||||||
|
--post-data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=qbittorrent%2FqBittorrent" \
|
||||||
|
-O coverity_tool.tgz
|
||||||
|
mkdir coverity_tool
|
||||||
|
tar xzf coverity_tool.tgz --strip 1 -C coverity_tool
|
||||||
|
|
||||||
|
- name: Build qBittorrent
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
-B build \
|
||||||
|
-G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DGUI=ON \
|
||||||
|
-DVERBOSE_CONFIGURE=ON
|
||||||
|
export PATH="$(pwd)/coverity_tool/bin:$PATH"
|
||||||
|
cov-build --dir cov-int cmake --build build
|
||||||
|
|
||||||
|
- name: Submit the result to Coverity Scan
|
||||||
|
run: |
|
||||||
|
tar caf qbittorrent.xz cov-int
|
||||||
|
curl \
|
||||||
|
--form token="${{ secrets.COVERITY_SCAN_TOKEN }}" \
|
||||||
|
--form email=sledgehammer999@qbittorrent.org \
|
||||||
|
--form file=@qbittorrent.xz \
|
||||||
|
--form version="$(git rev-parse --short HEAD)" \
|
||||||
|
--form description="master" \
|
||||||
|
https://scan.coverity.com/builds?project=qbittorrent%2FqBittorrent
|
||||||
85
.github/workflows/file_health.sh
vendored
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/mootools-1.2-more.js'
|
|
||||||
exclusions_trailing_newline='configure'
|
|
||||||
exclusions_no_lf='(*.ts)|(.*svg)|compile_commands.json|src/webui/www/private/scripts/lib/mootools-1.2-(core-yc.js|more.js)'
|
|
||||||
|
|
||||||
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;
|
|
||||||
22
.github/workflows/file_health.yaml
vendored
22
.github/workflows/file_health.yaml
vendored
@@ -1,22 +0,0 @@
|
|||||||
name: GitHub Actions file health check
|
|
||||||
|
|
||||||
on: [pull_request, push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check_file_health:
|
|
||||||
name: Check file health
|
|
||||||
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: install zsh
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install zsh
|
|
||||||
|
|
||||||
- name: run check file health script
|
|
||||||
run: |
|
|
||||||
./.github/workflows/file_health.sh
|
|
||||||
22
.github/workflows/stale_bot.yaml
vendored
Normal file
22
.github/workflows/stale_bot.yaml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Stale bot
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Mark and close stale PRs
|
||||||
|
uses: actions/stale@v4
|
||||||
|
with:
|
||||||
|
stale-pr-message: "This PR is stale because it has been 60 days with no activity. This PR will be automatically closed within 7 days if there is no further activity."
|
||||||
|
close-pr-message: "This PR was closed because it has been stalled for some time with no activity."
|
||||||
|
days-before-stale: -1 # avoid marking issues
|
||||||
|
days-before-pr-stale: 60
|
||||||
|
days-before-close: -1 # avoid closing issues
|
||||||
|
days-before-pr-close: 7
|
||||||
|
exempt-all-pr-assignees: true # avoid stale for all PR with assignees
|
||||||
|
exempt-all-pr-milestones: true # avoid stale for all PR with milestones
|
||||||
|
operations-per-run: 200
|
||||||
31
.github/workflows/webui_ci.yaml
vendored
31
.github/workflows/webui_ci.yaml
vendored
@@ -1,31 +0,0 @@
|
|||||||
name: WebUI CI
|
|
||||||
|
|
||||||
on: [pull_request, push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check_webui:
|
|
||||||
name: Check WebUI
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: src/webui/www
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: setup nodejs
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: '14'
|
|
||||||
|
|
||||||
- name: install tools
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: lint code
|
|
||||||
run: npm run lint
|
|
||||||
|
|
||||||
- name: format code
|
|
||||||
run: |
|
|
||||||
npm run format
|
|
||||||
git diff --exit-code
|
|
||||||
55
.pre-commit-config.yaml
Normal file
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
|
||||||
194
.travis.yml
194
.travis.yml
@@ -1,194 +0,0 @@
|
|||||||
language: cpp
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
dist: focal
|
|
||||||
osx_image: xcode12.2
|
|
||||||
|
|
||||||
env:
|
|
||||||
matrix:
|
|
||||||
- libt_branch=RC_1_2 gui=true build_system=qmake
|
|
||||||
- libt_branch=RC_1_2 gui=false build_system=qmake
|
|
||||||
- libt_branch=RC_1_2 gui=true build_system=cmake
|
|
||||||
- libt_branch=RC_1_2 gui=false build_system=cmake
|
|
||||||
global:
|
|
||||||
- secure: "OI9CUjj4lTb0HwwIZU5PbECU3hLlAL6KC8KsbwohG8/O3j5fLcnmDsK4Ad9us5cC39sS11Jcd1kDP2qRcCuST/glVNhLkcjKkiQerOfd5nQ/qL4JYfz/1mfP5mdpz9jHKzpLUIG+TXkbSTjP6VVmsb5KPT+3pKEdRFZB+Pu9+J8="
|
|
||||||
- coverity_branch: coverity_scan
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- env: libt_branch=RC_2_0 gui=true build_system=qmake
|
|
||||||
os: linux
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
on_success: change
|
|
||||||
on_failure: change
|
|
||||||
|
|
||||||
cache:
|
|
||||||
ccache: true
|
|
||||||
directories:
|
|
||||||
- $HOME/travis/deb
|
|
||||||
- $HOME/travis/brew
|
|
||||||
|
|
||||||
addons:
|
|
||||||
coverity_scan:
|
|
||||||
project:
|
|
||||||
name: "qbittorrent/qBittorrent"
|
|
||||||
description: "Build submitted via Travis CI"
|
|
||||||
build_command_prepend: "./bootstrap.sh && ./configure $qmake_conf"
|
|
||||||
build_command: "make -j2"
|
|
||||||
branch_pattern: $coverity_branch
|
|
||||||
notification_email: sledgehammer999@qbittorrent.org
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
# sources list: https://github.com/travis-ci/apt-source-safelist/blob/master/ubuntu.json
|
|
||||||
- sourceline: 'deb https://apt.kitware.com/ubuntu/ focal main'
|
|
||||||
key_url: 'https://apt.kitware.com/keys/kitware-archive-latest.asc'
|
|
||||||
- sourceline: 'ppa:beineri/opt-qt-5.14.2-focal'
|
|
||||||
packages:
|
|
||||||
# packages list: https://github.com/travis-ci/apt-package-safelist/blob/master/ubuntu-trusty
|
|
||||||
- [autoconf, automake, cmake, colormake]
|
|
||||||
- [libboost-dev, libboost-system-dev]
|
|
||||||
- libssl-dev
|
|
||||||
- [qt514base, qt514svg, qt514tools]
|
|
||||||
- zlib1g-dev
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# only allow specific build for coverity scan, others will stop
|
|
||||||
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$libt_branch" = "RC_1_2" -a "$gui" = "true" -a "$build_system" = "qmake" ]; then exit ; fi
|
|
||||||
|
|
||||||
- shopt -s expand_aliases
|
|
||||||
- alias make="colormake -j2" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
|
||||||
- qbt_path="$HOME/qbt_install"
|
|
||||||
- qmake_conf="$qmake_conf --prefix=$qbt_path"
|
|
||||||
- cmake_conf="$cmake_conf -DCMAKE_INSTALL_PREFIX=$qbt_path"
|
|
||||||
|
|
||||||
# options for specific branches
|
|
||||||
- |
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
|
||||||
# setup virtual display for after_success target
|
|
||||||
if [ "$gui" = "true" ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi ;
|
|
||||||
# CMake from Kitware is installed in /usr/bin
|
|
||||||
# TravisCI installs its own cmake to another location which ovverides other installations
|
|
||||||
# if they don't call the new binary directly
|
|
||||||
alias cmake="/usr/bin/cmake"
|
|
||||||
|
|
||||||
# Qt 5.14.2
|
|
||||||
PATH="/opt/qt514/bin:$PATH"
|
|
||||||
qmake_conf="$qmake_conf PKG_CONFIG_PATH=/opt/qt514/lib/pkgconfig:$PKG_CONFIG_PATH"
|
|
||||||
cmake_conf="$cmake_conf PKG_CONFIG_PATH=/opt/qt514/lib/pkgconfig:$PKG_CONFIG_PATH"
|
|
||||||
|
|
||||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
|
|
||||||
fi
|
|
||||||
- |
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
|
||||||
CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedefs"
|
|
||||||
|
|
||||||
openssl_root_path="/usr/local/opt/openssl"
|
|
||||||
qmake_conf="$qmake_conf PKG_CONFIG_PATH=$openssl_root_path/lib/pkgconfig:$PKG_CONFIG_PATH"
|
|
||||||
cmake_conf="$cmake_conf -DOPENSSL_ROOT_DIR=$openssl_root_path"
|
|
||||||
fi
|
|
||||||
- |
|
|
||||||
if [ "$gui" = "false" ]; then
|
|
||||||
qmake_conf="$qmake_conf --disable-gui"
|
|
||||||
cmake_conf="$cmake_conf -DGUI=OFF"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# print settings
|
|
||||||
- echo $libt_branch
|
|
||||||
- echo $gui
|
|
||||||
- echo $build_system
|
|
||||||
- echo $qmake_conf
|
|
||||||
- echo $cmake_conf
|
|
||||||
|
|
||||||
install:
|
|
||||||
- |
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
|
||||||
# dependencies
|
|
||||||
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
|
||||||
|
|
||||||
brew update > /dev/null
|
|
||||||
brew upgrade cmake
|
|
||||||
brew install ccache colormake boost openssl qt@5 zlib
|
|
||||||
brew link --force qt@5 zlib
|
|
||||||
|
|
||||||
if [ "$build_system" = "cmake" ]; then
|
|
||||||
sudo ln -s /usr/local/opt/qt/mkspecs /usr/local/mkspecs
|
|
||||||
sudo ln -s /usr/local/opt/qt/plugins /usr/local/plugins
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
- |
|
|
||||||
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
|
|
||||||
export use_ccache=true
|
|
||||||
ccache -M 512M
|
|
||||||
ccache -V && ccache --show-stats && ccache --zero-stats
|
|
||||||
fi
|
|
||||||
- |
|
|
||||||
if [ "$libt_branch" = "RC_1_2" ]; then
|
|
||||||
pushd "$HOME"
|
|
||||||
git clone --single-branch --branch RC_1_2 https://github.com/arvidn/libtorrent.git
|
|
||||||
cd libtorrent
|
|
||||||
git checkout tags/v1.2.13
|
|
||||||
|
|
||||||
cmake \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
-Ddeprecated-functions=OFF \
|
|
||||||
-DOPENSSL_ROOT_DIR="$openssl_root_path" \
|
|
||||||
./
|
|
||||||
make
|
|
||||||
sudo make install
|
|
||||||
popd
|
|
||||||
elif [ "$libt_branch" = "RC_2_0" ]; then
|
|
||||||
pushd "$HOME"
|
|
||||||
git clone --single-branch --branch RC_2_0 https://github.com/arvidn/libtorrent.git
|
|
||||||
cd libtorrent
|
|
||||||
git checkout tags/v2.0.3
|
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
cmake \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
-Ddeprecated-functions=OFF \
|
|
||||||
-DOPENSSL_ROOT_DIR="$openssl_root_path" \
|
|
||||||
./
|
|
||||||
make
|
|
||||||
sudo make install
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ]; then exit ; fi # skip usual build when running coverity scan
|
|
||||||
- |
|
|
||||||
cd "$TRAVIS_BUILD_DIR"
|
|
||||||
if [ "$build_system" = "qmake" ]; then
|
|
||||||
# scan only as lupdate is prone to hang
|
|
||||||
lupdate -extensions c,cpp,h,hpp,ui ./
|
|
||||||
./bootstrap.sh
|
|
||||||
./configure $qmake_conf CXXFLAGS="$CXXFLAGS"
|
|
||||||
else
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake $cmake_conf ../
|
|
||||||
fi
|
|
||||||
- make
|
|
||||||
- make install
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- if [ "$gui" = "true" ]; then qbt_exe="qbittorrent" ; else qbt_exe="qbittorrent-nox" ; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd "$qbt_path/bin" ; fi
|
|
||||||
- |
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
|
||||||
if [ "$build_system" = "qmake" ]; then
|
|
||||||
macdeployqt "$TRAVIS_BUILD_DIR/src/$qbt_exe.app"
|
|
||||||
cd "$TRAVIS_BUILD_DIR/src/$qbt_exe.app/Contents/MacOS"
|
|
||||||
else
|
|
||||||
cd "$qbt_path/$qbt_exe.app/Contents/MacOS"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
- ./$qbt_exe --version
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- if [ "$use_ccache" = true ]; then ccache --show-stats ; fi
|
|
||||||
@@ -10,17 +10,20 @@ project(qBittorrent
|
|||||||
|
|
||||||
# use CONFIG mode first in find_package
|
# use CONFIG mode first in find_package
|
||||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
||||||
# version requirements - older vesions 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.14)
|
set(minQt5Version 5.15.2)
|
||||||
|
set(minQt6Version 6.2)
|
||||||
set(minOpenSSLVersion 1.1.1)
|
set(minOpenSSLVersion 1.1.1)
|
||||||
set(minLibtorrentVersion 1.2.13)
|
set(minLibtorrent1Version 1.2.14)
|
||||||
|
set(minLibtorrentVersion 2.0.4)
|
||||||
set(minZlibVersion 1.2.11)
|
set(minZlibVersion 1.2.11)
|
||||||
|
|
||||||
# features (some are platform-specific)
|
# features (some are platform-specific)
|
||||||
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/
|
|
||||||
|
|||||||
65
COPYING
65
COPYING
@@ -18,8 +18,8 @@ See also the AUTHORS file
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ software--to make sure the software is free for all its users. This
|
|||||||
General Public License applies to most of the Free Software
|
General Public License applies to most of the Free Software
|
||||||
Foundation's software and to any other program whose authors commit to
|
Foundation's software and to any other program whose authors commit to
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
your programs, too.
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
@@ -295,3 +295,62 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|||||||
POSSIBILITY OF SUCH DAMAGES.
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
|
|||||||
14
INSTALL
14
INSTALL
@@ -5,20 +5,22 @@ qBittorrent - A BitTorrent client in C++ / Qt
|
|||||||
|
|
||||||
- Boost >= 1.65
|
- Boost >= 1.65
|
||||||
|
|
||||||
- libtorrent-rasterbar >= 1.2.13 (by Arvid Norberg)
|
- libtorrent-rasterbar 1.2.14 - 1.2.x || 2.0.4 - 2.0.x
|
||||||
* https://www.libtorrent.org/
|
* By Arvid Norberg, https://www.libtorrent.org/
|
||||||
* Be careful: another library (the one used by rTorrent) uses a similar name
|
* Be careful: another library (the one used by rTorrent) uses a similar name
|
||||||
|
|
||||||
- OpenSSL >= 1.1.1
|
- OpenSSL >= 1.1.1
|
||||||
|
|
||||||
- Qt >= 5.14
|
- Qt 5.15.2 - 5.x
|
||||||
|
|
||||||
- zlib >= 1.2.11
|
- zlib >= 1.2.11
|
||||||
|
|
||||||
- pkg-config (compile-time only on *nix systems)
|
- pkg-config *
|
||||||
|
* Compile-time only on *nix systems
|
||||||
|
|
||||||
- Python >= 3.5.0 (optional, runtime only)
|
- Python >= 3.5.0
|
||||||
* Required by the internal search engine
|
* Optional, run-time only
|
||||||
|
* Used by the bundled search engine
|
||||||
|
|
||||||
Dependency version numbers are bumped every once in a while to keep the range of properly tested configurations manageable, even if not strictly required to build.
|
Dependency version numbers are bumped every once in a while to keep the range of properly tested configurations manageable, even if not strictly required to build.
|
||||||
You may be able to build with older versions of (some of) the dependencies other than the minimum versions specified in the build scripts, but support for such builds is not provided - you are on your own.
|
You may be able to build with older versions of (some of) the dependencies other than the minimum versions specified in the build scripts, but support for such builds is not provided - you are on your own.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
qBittorrent - A BitTorrent client in Qt
|
qBittorrent - A BitTorrent client in Qt
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
[](https://travis-ci.org/qbittorrent/qBittorrent)
|
|
||||||
[](https://ci.appveyor.com/project/qbittorrent/qBittorrent)
|
[](https://ci.appveyor.com/project/qbittorrent/qBittorrent)
|
||||||
[](https://github.com/qbittorrent/qBittorrent/actions)
|
[](https://github.com/qbittorrent/qBittorrent/actions)
|
||||||
[](https://scan.coverity.com/projects/5494)
|
[](https://scan.coverity.com/projects/5494)
|
||||||
@@ -46,8 +45,8 @@ http://forum.qbittorrent.org
|
|||||||
Please report any bug (or feature request) to:
|
Please report any bug (or feature request) to:
|
||||||
http://bugs.qbittorrent.org
|
http://bugs.qbittorrent.org
|
||||||
|
|
||||||
You can also meet me (sledgehammer_999) on IRC:
|
Official IRC channel:
|
||||||
`#qbittorrent on irc.freenode.net`
|
`#qbittorrent on irc.libera.chat`
|
||||||
|
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
sledgehammer999 <sledgehammer999@qbittorrent.org>
|
sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ macro(qbt_common_config)
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(qbt_common_cfg INTERFACE
|
target_compile_definitions(qbt_common_cfg INTERFACE
|
||||||
QT_DISABLE_DEPRECATED_BEFORE=0x050e00
|
QT_DISABLE_DEPRECATED_BEFORE=0x050f02
|
||||||
QT_NO_CAST_TO_ASCII
|
QT_NO_CAST_TO_ASCII
|
||||||
QT_NO_CAST_FROM_BYTEARRAY
|
QT_NO_CAST_FROM_BYTEARRAY
|
||||||
QT_USE_QSTRINGBUILDER
|
QT_USE_QSTRINGBUILDER
|
||||||
@@ -90,4 +90,7 @@ macro(qbt_common_config)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (LibtorrentRasterbar_VERSION VERSION_GREATER_EQUAL ${minLibtorrentVersion})
|
||||||
|
target_compile_definitions(qbt_common_cfg INTERFACE QBT_USES_LIBTORRENT2)
|
||||||
|
endif()
|
||||||
endmacro(qbt_common_config)
|
endmacro(qbt_common_config)
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ DEFINES += BOOST_SYSTEM_STATIC_LINK
|
|||||||
# Enable if linking dynamically against libtorrent
|
# Enable if linking dynamically against libtorrent
|
||||||
#DEFINES += TORRENT_LINKING_SHARED
|
#DEFINES += TORRENT_LINKING_SHARED
|
||||||
|
|
||||||
|
# Enable this if compiling with libtorrent 2.x
|
||||||
|
#DEFINES += QBT_USES_LIBTORRENT2
|
||||||
|
|
||||||
# Enable stack trace support
|
# Enable stack trace support
|
||||||
CONFIG += stacktrace
|
CONFIG += stacktrace
|
||||||
|
|
||||||
|
|||||||
302
configure
vendored
302
configure
vendored
@@ -1450,7 +1450,7 @@ Some influential environment variables:
|
|||||||
directories to add to pkg-config's search path
|
directories to add to pkg-config's search path
|
||||||
PKG_CONFIG_LIBDIR
|
PKG_CONFIG_LIBDIR
|
||||||
path overriding pkg-config's built-in search path
|
path overriding pkg-config's built-in search path
|
||||||
QT_QMAKE value of host_bins for Qt5Core >= 5.14, overriding pkg-config
|
QT_QMAKE value of host_bins for Qt5Core >= 5.15.2, overriding pkg-config
|
||||||
Qt5Svg_CFLAGS
|
Qt5Svg_CFLAGS
|
||||||
C compiler flags for Qt5Svg, overriding pkg-config
|
C compiler flags for Qt5Svg, overriding pkg-config
|
||||||
Qt5Svg_LIBS linker flags for Qt5Svg, overriding pkg-config
|
Qt5Svg_LIBS linker flags for Qt5Svg, overriding pkg-config
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -5456,8 +5465,8 @@ printf "%s\n" "$enable_webui" >&6; }
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.14\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.15.2\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.14") 2>&5
|
($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.15.2") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
@@ -5466,12 +5475,12 @@ if test -n "$QT_QMAKE"; then
|
|||||||
pkg_cv_QT_QMAKE="$QT_QMAKE"
|
pkg_cv_QT_QMAKE="$QT_QMAKE"
|
||||||
elif test -n "$PKG_CONFIG"; then
|
elif test -n "$PKG_CONFIG"; then
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.14\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.15.2\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.14") 2>&5
|
($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.15.2") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
pkg_cv_QT_QMAKE=`$PKG_CONFIG --variable="host_bins" "Qt5Core >= 5.14" 2>/dev/null`
|
pkg_cv_QT_QMAKE=`$PKG_CONFIG --variable="host_bins" "Qt5Core >= 5.15.2" 2>/dev/null`
|
||||||
test "x$?" != "x0" && pkg_failed=yes
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
else
|
else
|
||||||
pkg_failed=yes
|
pkg_failed=yes
|
||||||
@@ -5501,8 +5510,8 @@ fi
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Qt5 qmake >= 5.14" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Qt5 qmake >= 5.15.2" >&5
|
||||||
printf %s "checking for Qt5 qmake >= 5.14... " >&6; }
|
printf %s "checking for Qt5 qmake >= 5.15.2... " >&6; }
|
||||||
if test "x$QT_QMAKE" != "x"
|
if test "x$QT_QMAKE" != "x"
|
||||||
then :
|
then :
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $QT_QMAKE" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $QT_QMAKE" >&5
|
||||||
@@ -5522,19 +5531,19 @@ if test "x$enable_gui" = "xyes"
|
|||||||
then :
|
then :
|
||||||
|
|
||||||
pkg_failed=no
|
pkg_failed=no
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Qt5Svg" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Qt5Svg >= 5.15.2" >&5
|
||||||
printf %s "checking for Qt5Svg... " >&6; }
|
printf %s "checking for Qt5Svg >= 5.15.2... " >&6; }
|
||||||
|
|
||||||
if test -n "$Qt5Svg_CFLAGS"; then
|
if test -n "$Qt5Svg_CFLAGS"; then
|
||||||
pkg_cv_Qt5Svg_CFLAGS="$Qt5Svg_CFLAGS"
|
pkg_cv_Qt5Svg_CFLAGS="$Qt5Svg_CFLAGS"
|
||||||
elif test -n "$PKG_CONFIG"; then
|
elif test -n "$PKG_CONFIG"; then
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Svg >= 5.14\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Svg >= 5.15.2\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "Qt5Svg >= 5.14") 2>&5
|
($PKG_CONFIG --exists --print-errors "Qt5Svg >= 5.15.2") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
pkg_cv_Qt5Svg_CFLAGS=`$PKG_CONFIG --cflags "Qt5Svg >= 5.14" 2>/dev/null`
|
pkg_cv_Qt5Svg_CFLAGS=`$PKG_CONFIG --cflags "Qt5Svg >= 5.15.2" 2>/dev/null`
|
||||||
test "x$?" != "x0" && pkg_failed=yes
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
else
|
else
|
||||||
pkg_failed=yes
|
pkg_failed=yes
|
||||||
@@ -5546,12 +5555,12 @@ if test -n "$Qt5Svg_LIBS"; then
|
|||||||
pkg_cv_Qt5Svg_LIBS="$Qt5Svg_LIBS"
|
pkg_cv_Qt5Svg_LIBS="$Qt5Svg_LIBS"
|
||||||
elif test -n "$PKG_CONFIG"; then
|
elif test -n "$PKG_CONFIG"; then
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Svg >= 5.14\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Svg >= 5.15.2\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "Qt5Svg >= 5.14") 2>&5
|
($PKG_CONFIG --exists --print-errors "Qt5Svg >= 5.15.2") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
pkg_cv_Qt5Svg_LIBS=`$PKG_CONFIG --libs "Qt5Svg >= 5.14" 2>/dev/null`
|
pkg_cv_Qt5Svg_LIBS=`$PKG_CONFIG --libs "Qt5Svg >= 5.15.2" 2>/dev/null`
|
||||||
test "x$?" != "x0" && pkg_failed=yes
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
else
|
else
|
||||||
pkg_failed=yes
|
pkg_failed=yes
|
||||||
@@ -5563,7 +5572,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
if test $pkg_failed = yes; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
@@ -5572,14 +5581,14 @@ else
|
|||||||
_pkg_short_errors_supported=no
|
_pkg_short_errors_supported=no
|
||||||
fi
|
fi
|
||||||
if test $_pkg_short_errors_supported = yes; then
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
Qt5Svg_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "Qt5Svg >= 5.14" 2>&1`
|
Qt5Svg_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "Qt5Svg >= 5.15.2" 2>&1`
|
||||||
else
|
else
|
||||||
Qt5Svg_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "Qt5Svg >= 5.14" 2>&1`
|
Qt5Svg_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "Qt5Svg >= 5.15.2" 2>&1`
|
||||||
fi
|
fi
|
||||||
# Put the nasty error message in config.log where it belongs
|
# Put the nasty error message in config.log where it belongs
|
||||||
echo "$Qt5Svg_PKG_ERRORS" >&5
|
echo "$Qt5Svg_PKG_ERRORS" >&5
|
||||||
|
|
||||||
as_fn_error $? "Package requirements (Qt5Svg >= 5.14) were not met:
|
as_fn_error $? "Package requirements (Qt5Svg >= 5.15.2) were not met:
|
||||||
|
|
||||||
$Qt5Svg_PKG_ERRORS
|
$Qt5Svg_PKG_ERRORS
|
||||||
|
|
||||||
@@ -5590,7 +5599,7 @@ Alternatively, you may set the environment variables Qt5Svg_CFLAGS
|
|||||||
and Qt5Svg_LIBS to avoid the need to call pkg-config.
|
and Qt5Svg_LIBS to avoid the need to call pkg-config.
|
||||||
See the pkg-config man page for more details." "$LINENO" 5
|
See the pkg-config man page for more details." "$LINENO" 5
|
||||||
elif test $pkg_failed = untried; then
|
elif test $pkg_failed = untried; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
@@ -5619,11 +5628,11 @@ case "x$enable_qt_dbus" in #(
|
|||||||
"xyes") :
|
"xyes") :
|
||||||
{ 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; }
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Qt5DBus >= 5.14" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Qt5DBus >= 5.15.2" >&5
|
||||||
printf %s "checking for Qt5DBus >= 5.14... " >&6; }
|
printf %s "checking for Qt5DBus >= 5.15.2... " >&6; }
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5DBus >= 5.14\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5DBus >= 5.15.2\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "Qt5DBus >= 5.14") 2>&5
|
($PKG_CONFIG --exists --print-errors "Qt5DBus >= 5.15.2") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
@@ -6032,19 +6041,19 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
|||||||
|
|
||||||
|
|
||||||
pkg_failed=no
|
pkg_failed=no
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent-rasterbar >= 2.0.4" >&5
|
||||||
printf %s "checking for libtorrent... " >&6; }
|
printf %s "checking for libtorrent-rasterbar >= 2.0.4... " >&6; }
|
||||||
|
|
||||||
if test -n "$libtorrent_CFLAGS"; then
|
if test -n "$libtorrent_CFLAGS"; then
|
||||||
pkg_cv_libtorrent_CFLAGS="$libtorrent_CFLAGS"
|
pkg_cv_libtorrent_CFLAGS="$libtorrent_CFLAGS"
|
||||||
elif test -n "$PKG_CONFIG"; then
|
elif test -n "$PKG_CONFIG"; then
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.2.13\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 2.0.4\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.2.13") 2>&5
|
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 2.0.4") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
pkg_cv_libtorrent_CFLAGS=`$PKG_CONFIG --cflags "libtorrent-rasterbar >= 1.2.13" 2>/dev/null`
|
pkg_cv_libtorrent_CFLAGS=`$PKG_CONFIG --cflags "libtorrent-rasterbar >= 2.0.4" 2>/dev/null`
|
||||||
test "x$?" != "x0" && pkg_failed=yes
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
else
|
else
|
||||||
pkg_failed=yes
|
pkg_failed=yes
|
||||||
@@ -6056,12 +6065,12 @@ if test -n "$libtorrent_LIBS"; then
|
|||||||
pkg_cv_libtorrent_LIBS="$libtorrent_LIBS"
|
pkg_cv_libtorrent_LIBS="$libtorrent_LIBS"
|
||||||
elif test -n "$PKG_CONFIG"; then
|
elif test -n "$PKG_CONFIG"; then
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.2.13\""; } >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 2.0.4\""; } >&5
|
||||||
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.2.13") 2>&5
|
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 2.0.4") 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
test $ac_status = 0; }; then
|
test $ac_status = 0; }; then
|
||||||
pkg_cv_libtorrent_LIBS=`$PKG_CONFIG --libs "libtorrent-rasterbar >= 1.2.13" 2>/dev/null`
|
pkg_cv_libtorrent_LIBS=`$PKG_CONFIG --libs "libtorrent-rasterbar >= 2.0.4" 2>/dev/null`
|
||||||
test "x$?" != "x0" && pkg_failed=yes
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
else
|
else
|
||||||
pkg_failed=yes
|
pkg_failed=yes
|
||||||
@@ -6073,7 +6082,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
if test $pkg_failed = yes; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
@@ -6082,14 +6091,73 @@ else
|
|||||||
_pkg_short_errors_supported=no
|
_pkg_short_errors_supported=no
|
||||||
fi
|
fi
|
||||||
if test $_pkg_short_errors_supported = yes; then
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
libtorrent_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libtorrent-rasterbar >= 1.2.13" 2>&1`
|
libtorrent_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libtorrent-rasterbar >= 2.0.4" 2>&1`
|
||||||
else
|
else
|
||||||
libtorrent_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libtorrent-rasterbar >= 1.2.13" 2>&1`
|
libtorrent_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libtorrent-rasterbar >= 2.0.4" 2>&1`
|
||||||
fi
|
fi
|
||||||
# Put the nasty error message in config.log where it belongs
|
# Put the nasty error message in config.log where it belongs
|
||||||
echo "$libtorrent_PKG_ERRORS" >&5
|
echo "$libtorrent_PKG_ERRORS" >&5
|
||||||
|
|
||||||
as_fn_error $? "Package requirements (libtorrent-rasterbar >= 1.2.13) were not met:
|
|
||||||
|
pkg_failed=no
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" >&5
|
||||||
|
printf %s "checking for libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2... " >&6; }
|
||||||
|
|
||||||
|
if test -n "$libtorrent_CFLAGS"; then
|
||||||
|
pkg_cv_libtorrent_CFLAGS="$libtorrent_CFLAGS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_libtorrent_CFLAGS=`$PKG_CONFIG --cflags "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
if test -n "$libtorrent_LIBS"; then
|
||||||
|
pkg_cv_libtorrent_LIBS="$libtorrent_LIBS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_libtorrent_LIBS=`$PKG_CONFIG --libs "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
libtorrent_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>&1`
|
||||||
|
else
|
||||||
|
libtorrent_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>&1`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$libtorrent_PKG_ERRORS" >&5
|
||||||
|
|
||||||
|
as_fn_error $? "Package requirements (libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2) were not met:
|
||||||
|
|
||||||
$libtorrent_PKG_ERRORS
|
$libtorrent_PKG_ERRORS
|
||||||
|
|
||||||
@@ -6100,7 +6168,7 @@ Alternatively, you may set the environment variables libtorrent_CFLAGS
|
|||||||
and libtorrent_LIBS to avoid the need to call pkg-config.
|
and libtorrent_LIBS to avoid the need to call pkg-config.
|
||||||
See the pkg-config man page for more details." "$LINENO" 5
|
See the pkg-config man page for more details." "$LINENO" 5
|
||||||
elif test $pkg_failed = untried; then
|
elif test $pkg_failed = untried; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
@@ -6119,14 +6187,114 @@ else
|
|||||||
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
||||||
{ 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; }
|
||||||
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
|
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS" LIBS="$libtorrent_LIBS $LIBS"
|
||||||
LIBS="$libtorrent_LIBS $LIBS"
|
fi
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" >&5
|
||||||
|
printf %s "checking for libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2... " >&6; }
|
||||||
|
|
||||||
|
if test -n "$libtorrent_CFLAGS"; then
|
||||||
|
pkg_cv_libtorrent_CFLAGS="$libtorrent_CFLAGS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_libtorrent_CFLAGS=`$PKG_CONFIG --cflags "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
if test -n "$libtorrent_LIBS"; then
|
||||||
|
pkg_cv_libtorrent_LIBS="$libtorrent_LIBS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_libtorrent_LIBS=`$PKG_CONFIG --libs "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
libtorrent_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>&1`
|
||||||
|
else
|
||||||
|
libtorrent_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2" 2>&1`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$libtorrent_PKG_ERRORS" >&5
|
||||||
|
|
||||||
|
as_fn_error $? "Package requirements (libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2) were not met:
|
||||||
|
|
||||||
|
$libtorrent_PKG_ERRORS
|
||||||
|
|
||||||
|
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||||
|
installed software in a non-standard prefix.
|
||||||
|
|
||||||
|
Alternatively, you may set the environment variables libtorrent_CFLAGS
|
||||||
|
and libtorrent_LIBS to avoid the need to call pkg-config.
|
||||||
|
See the pkg-config man page for more details." "$LINENO" 5
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
|
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
|
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
|
||||||
|
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||||
|
path to pkg-config.
|
||||||
|
|
||||||
|
Alternatively, you may set the environment variables libtorrent_CFLAGS
|
||||||
|
and libtorrent_LIBS to avoid the need to call pkg-config.
|
||||||
|
See the pkg-config man page for more details.
|
||||||
|
|
||||||
|
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
|
||||||
|
See \`config.log' for more details" "$LINENO" 5; }
|
||||||
|
else
|
||||||
|
libtorrent_CFLAGS=$pkg_cv_libtorrent_CFLAGS
|
||||||
|
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
printf "%s\n" "yes" >&6; }
|
||||||
|
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS" LIBS="$libtorrent_LIBS $LIBS"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
libtorrent_CFLAGS=$pkg_cv_libtorrent_CFLAGS
|
||||||
|
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
printf "%s\n" "yes" >&6; }
|
||||||
|
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS" LIBS="$libtorrent_LIBS $LIBS" QBT_ADD_DEFINES="$QBT_ADD_DEFINES QBT_USES_LIBTORRENT2"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
pkg_failed=no
|
pkg_failed=no
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openssl" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openssl >= 1.1.1" >&5
|
||||||
printf %s "checking for openssl... " >&6; }
|
printf %s "checking for openssl >= 1.1.1... " >&6; }
|
||||||
|
|
||||||
if test -n "$openssl_CFLAGS"; then
|
if test -n "$openssl_CFLAGS"; then
|
||||||
pkg_cv_openssl_CFLAGS="$openssl_CFLAGS"
|
pkg_cv_openssl_CFLAGS="$openssl_CFLAGS"
|
||||||
@@ -6166,7 +6334,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
if test $pkg_failed = yes; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
@@ -6193,7 +6361,7 @@ Alternatively, you may set the environment variables openssl_CFLAGS
|
|||||||
and openssl_LIBS to avoid the need to call pkg-config.
|
and openssl_LIBS to avoid the need to call pkg-config.
|
||||||
See the pkg-config man page for more details." "$LINENO" 5
|
See the pkg-config man page for more details." "$LINENO" 5
|
||||||
elif test $pkg_failed = untried; then
|
elif test $pkg_failed = untried; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
@@ -6218,8 +6386,8 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
pkg_failed=no
|
pkg_failed=no
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib >= 1.2.11" >&5
|
||||||
printf %s "checking for zlib... " >&6; }
|
printf %s "checking for zlib >= 1.2.11... " >&6; }
|
||||||
|
|
||||||
if test -n "$zlib_CFLAGS"; then
|
if test -n "$zlib_CFLAGS"; then
|
||||||
pkg_cv_zlib_CFLAGS="$zlib_CFLAGS"
|
pkg_cv_zlib_CFLAGS="$zlib_CFLAGS"
|
||||||
@@ -6259,7 +6427,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
if test $pkg_failed = yes; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
@@ -6286,7 +6454,7 @@ Alternatively, you may set the environment variables zlib_CFLAGS
|
|||||||
and zlib_LIBS to avoid the need to call pkg-config.
|
and zlib_LIBS to avoid the need to call pkg-config.
|
||||||
See the pkg-config man page for more details." "$LINENO" 5
|
See the pkg-config man page for more details." "$LINENO" 5
|
||||||
elif test $pkg_failed = untried; then
|
elif test $pkg_failed = untried; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
printf "%s\n" "no" >&6; }
|
printf "%s\n" "no" >&6; }
|
||||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||||
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||||
|
|||||||
46
configure.ac
46
configure.ac
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
AC_INIT([qbittorrent], [v4.4.0alpha], [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])
|
||||||
@@ -53,17 +54,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])
|
||||||
@@ -141,7 +157,7 @@ AS_IF([test "x$QT_QMAKE" = "x"],
|
|||||||
[AC_MSG_ERROR([Could not find qmake])
|
[AC_MSG_ERROR([Could not find qmake])
|
||||||
])
|
])
|
||||||
AS_IF([test "x$enable_gui" = "xyes"],
|
AS_IF([test "x$enable_gui" = "xyes"],
|
||||||
[PKG_CHECK_MODULES(Qt5Svg, [Qt5Svg >= 5.14])
|
[PKG_CHECK_MODULES(Qt5Svg, [Qt5Svg >= 5.15.2])
|
||||||
])
|
])
|
||||||
AC_MSG_CHECKING([whether QtDBus should be enabled])
|
AC_MSG_CHECKING([whether QtDBus should be enabled])
|
||||||
AS_CASE(["x$enable_qt_dbus"],
|
AS_CASE(["x$enable_qt_dbus"],
|
||||||
@@ -176,9 +192,11 @@ AC_COMPILE_IFELSE([DETECT_BOOST_VERSION_PROGRAM(106000)], [],
|
|||||||
[QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"])
|
[QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"])
|
||||||
|
|
||||||
PKG_CHECK_MODULES(libtorrent,
|
PKG_CHECK_MODULES(libtorrent,
|
||||||
[libtorrent-rasterbar >= 1.2.13],
|
[libtorrent-rasterbar >= 2.0.4],
|
||||||
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
|
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS" LIBS="$libtorrent_LIBS $LIBS" QBT_ADD_DEFINES="$QBT_ADD_DEFINES QBT_USES_LIBTORRENT2"],
|
||||||
LIBS="$libtorrent_LIBS $LIBS"])
|
[PKG_CHECK_MODULES(libtorrent,
|
||||||
|
[libtorrent-rasterbar >= 1.2.14 libtorrent-rasterbar < 2],
|
||||||
|
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS" LIBS="$libtorrent_LIBS $LIBS"])])
|
||||||
|
|
||||||
PKG_CHECK_MODULES(openssl,
|
PKG_CHECK_MODULES(openssl,
|
||||||
[openssl >= 1.1.1],
|
[openssl >= 1.1.1],
|
||||||
|
|||||||
22
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
22
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
@@ -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
|
||||||
@@ -70,7 +70,7 @@ Name[fa]=کیو بیت تورنت
|
|||||||
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]=Letölteni és megosztani a dokumentumokat Bittorrenttel
|
||||||
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
|
||||||
@@ -106,8 +106,8 @@ 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 下载和分享文件
|
Comment[zh]=通过 BitTorrent 下载和分享文件
|
||||||
GenericName[zh]=BitTorrent 客户端
|
GenericName[zh]=BitTorrent 客户端
|
||||||
@@ -153,6 +153,7 @@ GenericName[sl]=BitTorrent odjemalec
|
|||||||
Name[sl]=qBittorrent
|
Name[sl]=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
|
||||||
@@ -177,8 +178,8 @@ Name[ur]=قیو بٹ ٹورنٹ
|
|||||||
Comment[uk]=Завантажуйте та поширюйте файли через BitTorrent
|
Comment[uk]=Завантажуйте та поширюйте файли через BitTorrent
|
||||||
GenericName[uk]=BitTorrent-клієнт
|
GenericName[uk]=BitTorrent-клієнт
|
||||||
Name[uk]=qBittorrent
|
Name[uk]=qBittorrent
|
||||||
Comment[vi]=Tải xuống và chia sẻ tệp qua BitTorrent
|
Comment[vi]=Tải về và chia sẻ tệp qua BitTorrent
|
||||||
GenericName[vi]=Client BitTorrent
|
GenericName[vi]=Máy khách BitTorrent
|
||||||
Name[vi]=qBittorrent
|
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
|
||||||
@@ -192,6 +193,9 @@ 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[kk]=BitTorrent арқылы файл жүктеу және бөлісу
|
||||||
|
GenericName[kk]=BitTorrent клиенті
|
||||||
|
Name[kk]=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
|
||||||
@@ -213,6 +217,6 @@ 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]=ดาวน์โหลดและแชร์ไฟล์ด้วยบิททอเร้น
|
Comment[th]=ดาวน์โหลดและแชร์ไฟล์ผ่าน BitTorrent
|
||||||
GenericName[th]=โปรแกรมบิททอเร้น
|
GenericName[th]=ไคลเอนต์ BitTorrent
|
||||||
Name[th]=qBittorrent
|
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
|
||||||
|
|||||||
10
dist/windows/installer-translations/danish.nsi
vendored
10
dist/windows/installer-translations/danish.nsi
vendored
@@ -7,7 +7,7 @@ LangString inst_dekstop ${LANG_DANISH} "Opret skrivebordsgenvej"
|
|||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_DANISH} "Opret genvej i menuen Start"
|
LangString inst_startmenu ${LANG_DANISH} "Opret genvej i menuen Start"
|
||||||
;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_DANISH} "Start qBittorrent i Windows opstart"
|
LangString inst_startup ${LANG_DANISH} "Start qBittorrent når Windows starter"
|
||||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||||
LangString inst_torrent ${LANG_DANISH} "Åbn .torrent-filer med qBittorrent"
|
LangString inst_torrent ${LANG_DANISH} "Åbn .torrent-filer med 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_DANISH} "Åbn magnet-links med qBittorrent"
|
|||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_DANISH} "Tilføj Windows Firewall-regel"
|
LangString inst_firewall ${LANG_DANISH} "Tilføj Windows Firewall-regel"
|
||||||
;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_DANISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_DANISH} "Deaktivér grænse for for lang Windows-stien kan være (MAX_PATH-begrænsning på 260 tegn, kræver Windows 10 1607 eller senere)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_DANISH} "Tilføjer Windows Firewall-regel"
|
LangString inst_firewallinfo ${LANG_DANISH} "Tilføjer Windows Firewall-regel"
|
||||||
;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."
|
||||||
@@ -27,11 +27,11 @@ LangString inst_unist ${LANG_DANISH} "Afinstallerer tidligere version."
|
|||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_DANISH} "Start qBittorrent."
|
LangString launch_qbt ${LANG_DANISH} "Start 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_DANISH} "Dette installationsprogram virker kun i 64-bit Windows versioner."
|
LangString inst_requires_64bit ${LANG_DANISH} "Installationsprogrammet virker kun i Windows-versioner som er 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_DANISH} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_DANISH} "qBittorrent-versionen kræver mindst 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_DANISH} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_DANISH} "Afinstaller qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
|
|||||||
@@ -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
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} "자석 연결을 제거하지 않습니다. 관련 항목:"
|
||||||
|
|||||||
54
dist/windows/installer-translations/polish.nsi
vendored
54
dist/windows/installer-translations/polish.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_POLISH} "qBittorrent (required)"
|
LangString inst_qbt_req ${LANG_POLISH} "qBittorrent (wymagany)"
|
||||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||||
LangString inst_dekstop ${LANG_POLISH} "Create Desktop Shortcut"
|
LangString inst_dekstop ${LANG_POLISH} "Utwórz skrót na pulpicie"
|
||||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||||
LangString inst_startmenu ${LANG_POLISH} "Create Start Menu Shortcut"
|
LangString inst_startmenu ${LANG_POLISH} "Utwórz skrót w menu Start"
|
||||||
;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_POLISH} "Start qBittorrent on Windows start up"
|
LangString inst_startup ${LANG_POLISH} "Uruchamiaj qBittorrent wraz z systemem 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_POLISH} "Open .torrent files with qBittorrent"
|
LangString inst_torrent ${LANG_POLISH} "Otwieraj pliki .torrent za pomocą 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_POLISH} "Open magnet links with qBittorrent"
|
LangString inst_magnet ${LANG_POLISH} "Otwieraj odnośniki magnet za pomocą qBittorrent"
|
||||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||||
LangString inst_firewall ${LANG_POLISH} "Add Windows Firewall rule"
|
LangString inst_firewall ${LANG_POLISH} "Dodaj regułę Zapory systemu 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_POLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
|
LangString inst_pathlimit ${LANG_POLISH} "Wyłącz ograniczenie długości ścieżki systemu Windows (ograniczenie MAX_PATH do 260 znaków, wymaga systemu Windows 10 1607 lub nowszego)"
|
||||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||||
LangString inst_firewallinfo ${LANG_POLISH} "Adding Windows Firewall rule"
|
LangString inst_firewallinfo ${LANG_POLISH} "Dodawanie reguły Zapory systemu 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_POLISH} "qBittorrent is running. Please close the application before installing."
|
LangString inst_warning ${LANG_POLISH} "qBittorrent jest uruchomiony. Proszę zamknąć aplikację przed instalacją."
|
||||||
;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_POLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
|
LangString inst_uninstall_question ${LANG_POLISH} "Obecna wersja zostanie odinstalowana. Ustawienia użytkownika i torrenty pozostaną nienaruszone."
|
||||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||||
LangString inst_unist ${LANG_POLISH} "Uninstalling previous version."
|
LangString inst_unist ${LANG_POLISH} "Odinstalowywanie poprzedniej wersji."
|
||||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||||
LangString launch_qbt ${LANG_POLISH} "Launch qBittorrent."
|
LangString launch_qbt ${LANG_POLISH} "Uruchom 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_POLISH} "This installer works only in 64-bit Windows versions."
|
LangString inst_requires_64bit ${LANG_POLISH} "Ten instalator działa tylko w 64-bitowych wersjach systemu 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_POLISH} "This qBittorrent version requires at least Windows 7."
|
LangString inst_requires_win7 ${LANG_POLISH} "Ta wersja qBittorrent wymaga co najmniej systemu 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_POLISH} "Uninstall qBittorrent"
|
LangString inst_uninstall_link_description ${LANG_POLISH} "Odinstaluj qBittorrent"
|
||||||
|
|
||||||
;------------------------------------
|
;------------------------------------
|
||||||
;Uninstaller strings
|
;Uninstaller strings
|
||||||
|
|
||||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||||
LangString remove_files ${LANG_POLISH} "Remove files"
|
LangString remove_files ${LANG_POLISH} "Usuń pliki"
|
||||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||||
LangString remove_shortcuts ${LANG_POLISH} "Remove shortcuts"
|
LangString remove_shortcuts ${LANG_POLISH} "Usuń skróty"
|
||||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||||
LangString remove_associations ${LANG_POLISH} "Remove file associations"
|
LangString remove_associations ${LANG_POLISH} "Usuń skojarzenia plików"
|
||||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||||
LangString remove_registry ${LANG_POLISH} "Remove registry keys"
|
LangString remove_registry ${LANG_POLISH} "Usuń klucze rejestru"
|
||||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||||
LangString remove_conf ${LANG_POLISH} "Remove configuration files"
|
LangString remove_conf ${LANG_POLISH} "Usuń pliki konfiguracyjne"
|
||||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||||
LangString remove_firewall ${LANG_POLISH} "Remove Windows Firewall rule"
|
LangString remove_firewall ${LANG_POLISH} "Usuń regułę Zapory systemu Windows"
|
||||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||||
LangString remove_firewallinfo ${LANG_POLISH} "Removing Windows Firewall rule"
|
LangString remove_firewallinfo ${LANG_POLISH} "Usuwanie reguły Zapory systemu 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_POLISH} "Remove torrents and cached data"
|
LangString remove_cache ${LANG_POLISH} "Usuń torrenty i dane z pamięci podręcznej"
|
||||||
;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_POLISH} "qBittorrent is running. Please close the application before uninstalling."
|
LangString uninst_warning ${LANG_POLISH} "qBittorrent jest uruchomiony. Zamknij aplikację przed odinstalowaniem."
|
||||||
;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_POLISH} "Not removing .torrent association. It is associated with:"
|
LangString uninst_tor_warn ${LANG_POLISH} "Bez usuwania skojarzenia .torrent. Skojarzono z:"
|
||||||
;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_POLISH} "Not removing magnet association. It is associated with:"
|
LangString uninst_mag_warn ${LANG_POLISH} "Bez usuwania skojarzenia magnet. Skojarzono z:"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
215
m4/pkg.m4
215
m4/pkg.m4
@@ -1,29 +1,60 @@
|
|||||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
# serial 1 (pkg-config-0.24)
|
# serial 12 (pkg-config-0.29.2)
|
||||||
#
|
|
||||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
# General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
#
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
|
||||||
# distribute this file as part of a program that contains a
|
|
||||||
# configuration script generated by Autoconf, you may include it under
|
|
||||||
# the same distribution terms that you use for the rest of that program.
|
|
||||||
|
|
||||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||||
# ----------------------------------
|
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||||
|
dnl
|
||||||
|
dnl This program is free software; you can redistribute it and/or modify
|
||||||
|
dnl it under the terms of the GNU General Public License as published by
|
||||||
|
dnl the Free Software Foundation; either version 2 of the License, or
|
||||||
|
dnl (at your option) any later version.
|
||||||
|
dnl
|
||||||
|
dnl This program is distributed in the hope that it will be useful, but
|
||||||
|
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
dnl General Public License for more details.
|
||||||
|
dnl
|
||||||
|
dnl You should have received a copy of the GNU General Public License
|
||||||
|
dnl along with this program; if not, write to the Free Software
|
||||||
|
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
dnl 02111-1307, USA.
|
||||||
|
dnl
|
||||||
|
dnl As a special exception to the GNU General Public License, if you
|
||||||
|
dnl distribute this file as part of a program that contains a
|
||||||
|
dnl configuration script generated by Autoconf, you may include it under
|
||||||
|
dnl the same distribution terms that you use for the rest of that
|
||||||
|
dnl program.
|
||||||
|
|
||||||
|
dnl PKG_PREREQ(MIN-VERSION)
|
||||||
|
dnl -----------------------
|
||||||
|
dnl Since: 0.29
|
||||||
|
dnl
|
||||||
|
dnl Verify that the version of the pkg-config macros are at least
|
||||||
|
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
|
||||||
|
dnl installed version of pkg-config, this checks the developer's version
|
||||||
|
dnl of pkg.m4 when generating configure.
|
||||||
|
dnl
|
||||||
|
dnl To ensure that this macro is defined, also add:
|
||||||
|
dnl m4_ifndef([PKG_PREREQ],
|
||||||
|
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
|
||||||
|
dnl
|
||||||
|
dnl See the "Since" comment for each macro you use to see what version
|
||||||
|
dnl of the macros you require.
|
||||||
|
m4_defun([PKG_PREREQ],
|
||||||
|
[m4_define([PKG_MACROS_VERSION], [0.29.2])
|
||||||
|
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
||||||
|
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
||||||
|
])dnl PKG_PREREQ
|
||||||
|
|
||||||
|
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||||
|
dnl ----------------------------------
|
||||||
|
dnl Since: 0.16
|
||||||
|
dnl
|
||||||
|
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||||
|
dnl first found in the path. Checks that the version of pkg-config found
|
||||||
|
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
|
||||||
|
dnl used since that's the first version where most current features of
|
||||||
|
dnl pkg-config existed.
|
||||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||||
@@ -45,18 +76,19 @@ if test -n "$PKG_CONFIG"; then
|
|||||||
PKG_CONFIG=""
|
PKG_CONFIG=""
|
||||||
fi
|
fi
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# PKG_PROG_PKG_CONFIG
|
])dnl PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
#
|
dnl -------------------------------------------------------------------
|
||||||
# Check to see whether a particular set of modules exists. Similar
|
dnl Since: 0.18
|
||||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
dnl
|
||||||
#
|
dnl Check to see whether a particular set of modules exists. Similar to
|
||||||
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||||
# only at the first occurence in configure.ac, so if the first place
|
dnl
|
||||||
# it's called might be skipped (such as if it is within an "if", you
|
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
# have to call PKG_CHECK_EXISTS manually
|
dnl only at the first occurence in configure.ac, so if the first place
|
||||||
# --------------------------------------------------------------
|
dnl it's called might be skipped (such as if it is within an "if", you
|
||||||
|
dnl have to call PKG_CHECK_EXISTS manually
|
||||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
@@ -66,8 +98,10 @@ m4_ifvaln([$3], [else
|
|||||||
$3])dnl
|
$3])dnl
|
||||||
fi])
|
fi])
|
||||||
|
|
||||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||||
# ---------------------------------------------
|
dnl ---------------------------------------------
|
||||||
|
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
|
||||||
|
dnl pkg_failed based on the result.
|
||||||
m4_define([_PKG_CONFIG],
|
m4_define([_PKG_CONFIG],
|
||||||
[if test -n "$$1"; then
|
[if test -n "$$1"; then
|
||||||
pkg_cv_[]$1="$$1"
|
pkg_cv_[]$1="$$1"
|
||||||
@@ -79,10 +113,11 @@ m4_define([_PKG_CONFIG],
|
|||||||
else
|
else
|
||||||
pkg_failed=untried
|
pkg_failed=untried
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# _PKG_CONFIG
|
])dnl _PKG_CONFIG
|
||||||
|
|
||||||
# _PKG_SHORT_ERRORS_SUPPORTED
|
dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
# -----------------------------
|
dnl ---------------------------
|
||||||
|
dnl Internal check to see if pkg-config supports short errors.
|
||||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
@@ -90,26 +125,24 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
|||||||
else
|
else
|
||||||
_pkg_short_errors_supported=no
|
_pkg_short_errors_supported=no
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# _PKG_SHORT_ERRORS_SUPPORTED
|
])dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
# [ACTION-IF-NOT-FOUND])
|
dnl [ACTION-IF-NOT-FOUND])
|
||||||
#
|
dnl --------------------------------------------------------------
|
||||||
#
|
dnl Since: 0.4.0
|
||||||
# Note that if there is a possibility the first call to
|
dnl
|
||||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
dnl Note that if there is a possibility the first call to
|
||||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||||
#
|
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||||
#
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
AC_DEFUN([PKG_CHECK_MODULES],
|
AC_DEFUN([PKG_CHECK_MODULES],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||||
|
|
||||||
pkg_failed=no
|
pkg_failed=no
|
||||||
AC_MSG_CHECKING([for $1])
|
AC_MSG_CHECKING([for $2])
|
||||||
|
|
||||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||||
@@ -119,7 +152,7 @@ and $1[]_LIBS to avoid the need to call pkg-config.
|
|||||||
See the pkg-config man page for more details.])
|
See the pkg-config man page for more details.])
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
if test $pkg_failed = yes; then
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
_PKG_SHORT_ERRORS_SUPPORTED
|
_PKG_SHORT_ERRORS_SUPPORTED
|
||||||
if test $_pkg_short_errors_supported = yes; then
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
||||||
@@ -140,7 +173,7 @@ installed software in a non-standard prefix.
|
|||||||
_PKG_TEXT])[]dnl
|
_PKG_TEXT])[]dnl
|
||||||
])
|
])
|
||||||
elif test $pkg_failed = untried; then
|
elif test $pkg_failed = untried; then
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
m4_default([$4], [AC_MSG_FAILURE(
|
m4_default([$4], [AC_MSG_FAILURE(
|
||||||
[The pkg-config script could not be found or is too old. Make sure it
|
[The pkg-config script could not be found or is too old. Make sure it
|
||||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||||
@@ -156,16 +189,40 @@ else
|
|||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
$3
|
$3
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# PKG_CHECK_MODULES
|
])dnl PKG_CHECK_MODULES
|
||||||
|
|
||||||
|
|
||||||
# PKG_INSTALLDIR(DIRECTORY)
|
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
# -------------------------
|
dnl [ACTION-IF-NOT-FOUND])
|
||||||
# Substitutes the variable pkgconfigdir as the location where a module
|
dnl ---------------------------------------------------------------------
|
||||||
# should install pkg-config .pc files. By default the directory is
|
dnl Since: 0.29
|
||||||
# $libdir/pkgconfig, but the default can be changed by passing
|
dnl
|
||||||
# DIRECTORY. The user can override through the --with-pkgconfigdir
|
dnl Checks for existence of MODULES and gathers its build flags with
|
||||||
# parameter.
|
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
|
||||||
|
dnl and VARIABLE-PREFIX_LIBS from --libs.
|
||||||
|
dnl
|
||||||
|
dnl Note that if there is a possibility the first call to
|
||||||
|
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
|
||||||
|
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
|
||||||
|
dnl configure.ac.
|
||||||
|
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
_save_PKG_CONFIG=$PKG_CONFIG
|
||||||
|
PKG_CONFIG="$PKG_CONFIG --static"
|
||||||
|
PKG_CHECK_MODULES($@)
|
||||||
|
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
|
||||||
|
])dnl PKG_CHECK_MODULES_STATIC
|
||||||
|
|
||||||
|
|
||||||
|
dnl PKG_INSTALLDIR([DIRECTORY])
|
||||||
|
dnl -------------------------
|
||||||
|
dnl Since: 0.27
|
||||||
|
dnl
|
||||||
|
dnl Substitutes the variable pkgconfigdir as the location where a module
|
||||||
|
dnl should install pkg-config .pc files. By default the directory is
|
||||||
|
dnl $libdir/pkgconfig, but the default can be changed by passing
|
||||||
|
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
|
||||||
|
dnl parameter.
|
||||||
AC_DEFUN([PKG_INSTALLDIR],
|
AC_DEFUN([PKG_INSTALLDIR],
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
||||||
m4_pushdef([pkg_description],
|
m4_pushdef([pkg_description],
|
||||||
@@ -176,16 +233,18 @@ AC_ARG_WITH([pkgconfigdir],
|
|||||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
||||||
m4_popdef([pkg_default])
|
m4_popdef([pkg_default])
|
||||||
m4_popdef([pkg_description])
|
m4_popdef([pkg_description])
|
||||||
]) dnl PKG_INSTALLDIR
|
])dnl PKG_INSTALLDIR
|
||||||
|
|
||||||
|
|
||||||
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
|
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
|
||||||
# -------------------------
|
dnl --------------------------------
|
||||||
# Substitutes the variable noarch_pkgconfigdir as the location where a
|
dnl Since: 0.27
|
||||||
# module should install arch-independent pkg-config .pc files. By
|
dnl
|
||||||
# default the directory is $datadir/pkgconfig, but the default can be
|
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
|
||||||
# changed by passing DIRECTORY. The user can override through the
|
dnl module should install arch-independent pkg-config .pc files. By
|
||||||
# --with-noarch-pkgconfigdir parameter.
|
dnl default the directory is $datadir/pkgconfig, but the default can be
|
||||||
|
dnl changed by passing DIRECTORY. The user can override through the
|
||||||
|
dnl --with-noarch-pkgconfigdir parameter.
|
||||||
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
||||||
m4_pushdef([pkg_description],
|
m4_pushdef([pkg_description],
|
||||||
@@ -196,13 +255,15 @@ AC_ARG_WITH([noarch-pkgconfigdir],
|
|||||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
||||||
m4_popdef([pkg_default])
|
m4_popdef([pkg_default])
|
||||||
m4_popdef([pkg_description])
|
m4_popdef([pkg_description])
|
||||||
]) dnl PKG_NOARCH_INSTALLDIR
|
])dnl PKG_NOARCH_INSTALLDIR
|
||||||
|
|
||||||
|
|
||||||
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
||||||
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
# -------------------------------------------
|
dnl -------------------------------------------
|
||||||
# Retrieves the value of the pkg-config variable for the given module.
|
dnl Since: 0.28
|
||||||
|
dnl
|
||||||
|
dnl Retrieves the value of the pkg-config variable for the given module.
|
||||||
AC_DEFUN([PKG_CHECK_VAR],
|
AC_DEFUN([PKG_CHECK_VAR],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
||||||
@@ -211,4 +272,4 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
|||||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||||
|
|
||||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||||
])# PKG_CHECK_VAR
|
])dnl PKG_CHECK_VAR
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
# Sets the QT_QMAKE variable to the path of Qt5 qmake if found.
|
# Sets the QT_QMAKE variable to the path of Qt5 qmake if found.
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
AC_DEFUN([FIND_QT5],
|
AC_DEFUN([FIND_QT5],
|
||||||
[PKG_CHECK_EXISTS([Qt5Core >= 5.14],
|
[PKG_CHECK_EXISTS([Qt5Core >= 5.15.2],
|
||||||
[PKG_CHECK_VAR(QT_QMAKE,
|
[PKG_CHECK_VAR(QT_QMAKE,
|
||||||
[Qt5Core >= 5.14],
|
[Qt5Core >= 5.15.2],
|
||||||
[host_bins])
|
[host_bins])
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ AS_IF([test -f "$QT_QMAKE/qmake"],
|
|||||||
[QT_QMAKE=""])
|
[QT_QMAKE=""])
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING([for Qt5 qmake >= 5.14])
|
AC_MSG_CHECKING([for Qt5 qmake >= 5.15.2])
|
||||||
AS_IF([test "x$QT_QMAKE" != "x"],
|
AS_IF([test "x$QT_QMAKE" != "x"],
|
||||||
[AC_MSG_RESULT([$QT_QMAKE])],
|
[AC_MSG_RESULT([$QT_QMAKE])],
|
||||||
[AC_MSG_RESULT([not found])]
|
[AC_MSG_RESULT([not found])]
|
||||||
@@ -29,8 +29,8 @@ AS_IF([test "x$QT_QMAKE" != "x"],
|
|||||||
# Sets the HAVE_QTDBUS variable to true or false.
|
# Sets the HAVE_QTDBUS variable to true or false.
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
AC_DEFUN([FIND_QTDBUS],
|
AC_DEFUN([FIND_QTDBUS],
|
||||||
[AC_MSG_CHECKING([for Qt5DBus >= 5.14])
|
[AC_MSG_CHECKING([for Qt5DBus >= 5.15.2])
|
||||||
PKG_CHECK_EXISTS([Qt5DBus >= 5.14],
|
PKG_CHECK_EXISTS([Qt5DBus >= 5.15.2],
|
||||||
[AC_MSG_RESULT([found])
|
[AC_MSG_RESULT([found])
|
||||||
HAVE_QTDBUS=[true]],
|
HAVE_QTDBUS=[true]],
|
||||||
[AC_MSG_RESULT([not found])
|
[AC_MSG_RESULT([not found])
|
||||||
|
|||||||
@@ -1,47 +1,66 @@
|
|||||||
if (UNIX AND (NOT APPLE) AND (NOT CYGWIN))
|
macro(find_libtorrent version)
|
||||||
find_package(LibtorrentRasterbar QUIET ${minLibtorrentVersion} COMPONENTS torrent-rasterbar)
|
if (UNIX AND (NOT APPLE) AND (NOT CYGWIN))
|
||||||
if (NOT LibtorrentRasterbar_FOUND)
|
find_package(LibtorrentRasterbar QUIET ${version} COMPONENTS torrent-rasterbar)
|
||||||
include(FindPkgConfig)
|
if (NOT LibtorrentRasterbar_FOUND)
|
||||||
pkg_check_modules(LIBTORRENT_RASTERBAR IMPORTED_TARGET GLOBAL "libtorrent-rasterbar>=${minLibtorrentVersion}")
|
include(FindPkgConfig)
|
||||||
if (NOT LIBTORRENT_RASTERBAR_FOUND)
|
pkg_check_modules(LibtorrentRasterbar IMPORTED_TARGET GLOBAL "libtorrent-rasterbar>=${version}")
|
||||||
message(
|
if (NOT LibtorrentRasterbar_FOUND)
|
||||||
FATAL_ERROR
|
message(
|
||||||
"Package LibtorrentRasterbar >= ${minLibtorrentVersion} not found"
|
FATAL_ERROR
|
||||||
" with CMake or pkg-config.\n- Set LibtorrentRasterbar_DIR to a directory containing"
|
"Package LibtorrentRasterbar >= ${version} not found"
|
||||||
" a LibtorrentRasterbarConfig.cmake file or add the installation prefix of LibtorrentRasterbar"
|
" with CMake or pkg-config.\n- Set LibtorrentRasterbar_DIR to a directory containing"
|
||||||
" to CMAKE_PREFIX_PATH.\n- Alternatively, make sure there is a valid libtorrent-rasterbar.pc"
|
" a LibtorrentRasterbarConfig.cmake file or add the installation prefix of LibtorrentRasterbar"
|
||||||
" file in your system's pkg-config search paths (use the system environment variable PKG_CONFIG_PATH"
|
" to CMAKE_PREFIX_PATH.\n- Alternatively, make sure there is a valid libtorrent-rasterbar.pc"
|
||||||
" to specify additional search paths if needed)."
|
" file in your system's pkg-config search paths (use the system environment variable PKG_CONFIG_PATH"
|
||||||
|
" to specify additional search paths if needed)."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
add_library(LibtorrentRasterbar::torrent-rasterbar ALIAS PkgConfig::LibtorrentRasterbar)
|
||||||
|
# force a fake package to show up in the feature summary
|
||||||
|
set_property(GLOBAL APPEND PROPERTY
|
||||||
|
PACKAGES_FOUND
|
||||||
|
"LibtorrentRasterbar via pkg-config (version >= ${version})"
|
||||||
)
|
)
|
||||||
|
set_package_properties("LibtorrentRasterbar via pkg-config (version >= ${version})"
|
||||||
|
PROPERTIES
|
||||||
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set_package_properties(LibtorrentRasterbar PROPERTIES TYPE REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
add_library(LibtorrentRasterbar::torrent-rasterbar ALIAS PkgConfig::LIBTORRENT_RASTERBAR)
|
|
||||||
# force a fake package to show up in the feature summary
|
|
||||||
set_property(GLOBAL APPEND PROPERTY
|
|
||||||
PACKAGES_FOUND
|
|
||||||
"LibtorrentRasterbar via pkg-config (version >= ${minLibtorrentVersion})"
|
|
||||||
)
|
|
||||||
set_package_properties("LibtorrentRasterbar via pkg-config (version >= ${minLibtorrentVersion})"
|
|
||||||
PROPERTIES
|
|
||||||
TYPE REQUIRED
|
|
||||||
)
|
|
||||||
else()
|
else()
|
||||||
set_package_properties(LibtorrentRasterbar PROPERTIES TYPE REQUIRED)
|
find_package(LibtorrentRasterbar ${version} REQUIRED COMPONENTS torrent-rasterbar)
|
||||||
endif()
|
endif()
|
||||||
else()
|
endmacro()
|
||||||
find_package(LibtorrentRasterbar ${minLibtorrentVersion} REQUIRED COMPONENTS torrent-rasterbar)
|
|
||||||
|
find_libtorrent(${minLibtorrent1Version})
|
||||||
|
if (LibtorrentRasterbar_FOUND AND (LibtorrentRasterbar_VERSION VERSION_GREATER_EQUAL 2.0))
|
||||||
|
find_libtorrent(${minLibtorrentVersion})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# force variable type so that it always shows up in ccmake/cmake-gui frontends
|
# force variable type so that it always shows up in ccmake/cmake-gui frontends
|
||||||
set_property(CACHE LibtorrentRasterbar_DIR PROPERTY TYPE PATH)
|
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
|
||||||
@@ -60,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()
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,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
|
||||||
@@ -435,16 +437,12 @@ void Application::runExternalProgram(const BitTorrent::Torrent *torrent) const
|
|||||||
// enable command injection via torrent name and other arguments
|
// enable command injection via torrent name and other arguments
|
||||||
// (especially when some automated download mechanism has been setup).
|
// (especially when some automated download mechanism has been setup).
|
||||||
// See: https://github.com/qbittorrent/qBittorrent/issues/10925
|
// See: https://github.com/qbittorrent/qBittorrent/issues/10925
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
|
||||||
QStringList args = QProcess::splitCommand(program);
|
QStringList args = QProcess::splitCommand(program);
|
||||||
if (args.isEmpty())
|
if (args.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString command = args.takeFirst();
|
const QString command = args.takeFirst();
|
||||||
QProcess::startDetached(command, args);
|
QProcess::startDetached(command, args);
|
||||||
#else
|
|
||||||
QProcess::startDetached(program);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,7 +563,7 @@ void Application::processParams(const QStringList ¶ms)
|
|||||||
|
|
||||||
if (param.startsWith(QLatin1String("@addPaused=")))
|
if (param.startsWith(QLatin1String("@addPaused=")))
|
||||||
{
|
{
|
||||||
torrentParams.addPaused = (param.midRef(11).toInt() != 0);
|
torrentParams.addPaused = (QStringView(param).mid(11).toInt() != 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,7 +593,7 @@ void Application::processParams(const QStringList ¶ms)
|
|||||||
|
|
||||||
if (param.startsWith(QLatin1String("@skipDialog=")))
|
if (param.startsWith(QLatin1String("@skipDialog=")))
|
||||||
{
|
{
|
||||||
skipTorrentDialog = (param.midRef(12).toInt() != 0);
|
skipTorrentDialog = (QStringView(param).mid(12).toInt() != 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,8 +667,8 @@ int Application::exec(const QStringList ¶ms)
|
|||||||
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
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace RSS
|
|||||||
class Application final : public BaseApplication
|
class Application final : public BaseApplication
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Application)
|
Q_DISABLE_COPY_MOVE(Application)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Application(int &argc, char **argv);
|
Application(int &argc, char **argv);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class QtLocalPeer;
|
|||||||
class ApplicationInstanceManager : public QObject
|
class ApplicationInstanceManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(ApplicationInstanceManager)
|
Q_DISABLE_COPY_MOVE(ApplicationInstanceManager)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ApplicationInstanceManager(const QString &appId, QObject *parent = nullptr);
|
explicit ApplicationInstanceManager(const QString &appId, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Log
|
|||||||
class FileLogger : public QObject
|
class FileLogger : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(FileLogger)
|
Q_DISABLE_COPY_MOVE(FileLogger)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum FileLogAgeType
|
enum FileLogAgeType
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
|
|||||||
|
|
||||||
Qt::HANDLE mutex;
|
Qt::HANDLE mutex;
|
||||||
if (doCreate) {
|
if (doCreate) {
|
||||||
QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
|
QT_WA( { mutex = CreateMutexW(NULL, FALSE, reinterpret_cast<const TCHAR *>(mname.utf16())); },
|
||||||
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
|
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
|
||||||
if (!mutex) {
|
if (!mutex) {
|
||||||
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
||||||
@@ -97,7 +97,7 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
|
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()); } );
|
{ mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
|
||||||
if (!mutex) {
|
if (!mutex) {
|
||||||
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void straceWin::loadHelpStackFrame(IMAGEHLP_STACK_FRAME& ihsf, const STACKFRAME6
|
|||||||
BOOL CALLBACK straceWin::EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user)
|
BOOL CALLBACK straceWin::EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user)
|
||||||
{
|
{
|
||||||
Q_UNUSED(size)
|
Q_UNUSED(size)
|
||||||
QStringList* params = (QStringList*)user;
|
auto params = static_cast<QStringList *>(user);
|
||||||
if (symInfo->Flags & SYMFLAG_PARAMETER)
|
if (symInfo->Flags & SYMFLAG_PARAMETER)
|
||||||
params->append(symInfo->Name);
|
params->append(symInfo->Name);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -91,7 +91,7 @@ BOOL CALLBACK straceWin::EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVO
|
|||||||
{
|
{
|
||||||
Q_UNUSED(ModuleName)
|
Q_UNUSED(ModuleName)
|
||||||
IMAGEHLP_MODULE64 mod;
|
IMAGEHLP_MODULE64 mod;
|
||||||
EnumModulesContext* context = (EnumModulesContext*)UserContext;
|
auto context = static_cast<EnumModulesContext *>(UserContext);
|
||||||
mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
|
mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
|
||||||
if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod))
|
if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod))
|
||||||
{
|
{
|
||||||
@@ -264,7 +264,7 @@ const QString straceWin::getBacktrace()
|
|||||||
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
|
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
|
||||||
MAX_SYM_NAME * sizeof(TCHAR) +
|
MAX_SYM_NAME * sizeof(TCHAR) +
|
||||||
sizeof(ULONG64) - 1) / sizeof(ULONG64)];
|
sizeof(ULONG64) - 1) / sizeof(ULONG64)];
|
||||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
auto pSymbol = reinterpret_cast<PSYMBOL_INFO>(buffer);
|
||||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Ui
|
|||||||
class StacktraceDialog : public QDialog
|
class StacktraceDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(StacktraceDialog)
|
Q_DISABLE_COPY_MOVE(StacktraceDialog)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StacktraceDialog(QWidget *parent = nullptr);
|
explicit StacktraceDialog(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include "upgrade.h"
|
#include "upgrade.h"
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
@@ -37,6 +36,7 @@
|
|||||||
#include "base/profile.h"
|
#include "base/profile.h"
|
||||||
#include "base/settingsstorage.h"
|
#include "base/settingsstorage.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
|
||||||
@@ -53,17 +53,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,12 +95,28 @@ namespace
|
|||||||
settingsStorage->storeValue(newKey, Utils::String::fromEnum(torrentContentLayout));
|
settingsStorage->storeValue(newKey, Utils::String::fromEnum(torrentContentLayout));
|
||||||
settingsStorage->removeValue(oldKey);
|
settingsStorage->removeValue(oldKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void upgradeListenPortSettings()
|
||||||
|
{
|
||||||
|
const auto oldKey = QString::fromLatin1("BitTorrent/Session/UseRandomPort");
|
||||||
|
const auto newKey = QString::fromLatin1("Preferences/Connection/PortRangeMin");
|
||||||
|
auto *settingsStorage = SettingsStorage::instance();
|
||||||
|
|
||||||
|
if (settingsStorage->hasKey(oldKey))
|
||||||
|
{
|
||||||
|
if (settingsStorage->loadValue<bool>(oldKey))
|
||||||
|
settingsStorage->storeValue(newKey, 0);
|
||||||
|
|
||||||
|
settingsStorage->removeValue(oldKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool upgrade(const bool /*ask*/)
|
bool upgrade(const bool /*ask*/)
|
||||||
{
|
{
|
||||||
exportWebUIHttpsFiles();
|
exportWebUIHttpsFiles();
|
||||||
upgradeTorrentContentLayout();
|
upgradeTorrentContentLayout();
|
||||||
|
upgradeListenPortSettings();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2517
src/base/3rdparty/expected.hpp
vendored
Normal file
2517
src/base/3rdparty/expected.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
@@ -16,7 +17,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
|
||||||
@@ -176,7 +177,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 +204,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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
class AsyncFileStorage : public QObject
|
class AsyncFileStorage : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(AsyncFileStorage)
|
Q_DISABLE_COPY_MOVE(AsyncFileStorage)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);
|
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -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 \
|
||||||
@@ -15,7 +16,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 \
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
class BandwidthScheduler : public QObject
|
class BandwidthScheduler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(BandwidthScheduler)
|
Q_DISABLE_COPY_MOVE(BandwidthScheduler)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BandwidthScheduler(QObject *parent = nullptr);
|
explicit BandwidthScheduler(QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -29,15 +29,14 @@
|
|||||||
#include "bencoderesumedatastorage.h"
|
#include "bencoderesumedatastorage.h"
|
||||||
|
|
||||||
#include <libtorrent/bdecode.hpp>
|
#include <libtorrent/bdecode.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
|
||||||
#include <libtorrent/create_torrent.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/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"
|
||||||
@@ -51,13 +50,12 @@
|
|||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "infohash.h"
|
#include "infohash.h"
|
||||||
#include "loadtorrentparams.h"
|
#include "loadtorrentparams.h"
|
||||||
#include "torrentinfo.h"
|
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
class BencodeResumeDataStorage::Worker final : public QObject
|
class BencodeResumeDataStorage::Worker final : public QObject
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY(Worker)
|
Q_DISABLE_COPY_MOVE(Worker)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Worker(const QDir &resumeDataDir);
|
explicit Worker(const QDir &resumeDataDir);
|
||||||
@@ -89,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)
|
||||||
@@ -127,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);
|
||||||
@@ -151,25 +138,36 @@ std::optional<BitTorrent::LoadTorrentParams> BitTorrent::BencodeResumeDataStorag
|
|||||||
const QString fastresumePath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.fastresume").arg(idString));
|
const QString fastresumePath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.fastresume").arg(idString));
|
||||||
const QString torrentFilePath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.torrent").arg(idString));
|
const QString torrentFilePath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.torrent").arg(idString));
|
||||||
|
|
||||||
QFile file {fastresumePath};
|
QFile resumeDataFile {fastresumePath};
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
if (!resumeDataFile.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
LogMsg(tr("Cannot read file %1: %2").arg(fastresumePath, file.errorString()), Log::WARNING);
|
LogMsg(tr("Cannot read file %1: %2").arg(fastresumePath, resumeDataFile.errorString()), Log::WARNING);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray data = file.readAll();
|
QFile metadataFile {torrentFilePath};
|
||||||
const TorrentInfo metadata = TorrentInfo::loadFromFile(torrentFilePath);
|
if (metadataFile.exists() && !metadataFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
LogMsg(tr("Cannot read file %1: %2").arg(torrentFilePath, metadataFile.errorString()), Log::WARNING);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray data = resumeDataFile.readAll();
|
||||||
|
const QByteArray metadata = (metadataFile.isOpen() ? metadataFile.readAll() : "");
|
||||||
|
|
||||||
return loadTorrentResumeData(data, metadata);
|
return loadTorrentResumeData(data, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<BitTorrent::LoadTorrentParams> BitTorrent::BencodeResumeDataStorage::loadTorrentResumeData(
|
std::optional<BitTorrent::LoadTorrentParams> BitTorrent::BencodeResumeDataStorage::loadTorrentResumeData(
|
||||||
const QByteArray &data, const TorrentInfo &metadata) const
|
const QByteArray &data, const QByteArray &metadata) const
|
||||||
{
|
{
|
||||||
|
const QByteArray allData = ((metadata.isEmpty() || data.isEmpty())
|
||||||
|
? data : (data.chopped(1) + metadata.mid(1)));
|
||||||
|
|
||||||
lt::error_code ec;
|
lt::error_code ec;
|
||||||
const lt::bdecode_node root = lt::bdecode(data, ec);
|
const lt::bdecode_node root = lt::bdecode(allData, ec);
|
||||||
if (ec || (root.type() != lt::bdecode_node::dict_t)) return std::nullopt;
|
if (ec || (root.type() != lt::bdecode_node::dict_t))
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
LoadTorrentParams torrentParams;
|
LoadTorrentParams torrentParams;
|
||||||
torrentParams.restored = true;
|
torrentParams.restored = true;
|
||||||
@@ -220,8 +218,6 @@ std::optional<BitTorrent::LoadTorrentParams> BitTorrent::BencodeResumeDataStorag
|
|||||||
|
|
||||||
p = lt::read_resume_data(root, ec);
|
p = lt::read_resume_data(root, ec);
|
||||||
p.save_path = Profile::instance()->fromPortablePath(fromLTString(p.save_path)).toStdString();
|
p.save_path = Profile::instance()->fromPortablePath(fromLTString(p.save_path)).toStdString();
|
||||||
if (metadata.isValid())
|
|
||||||
p.ti = metadata.nativeInfo();
|
|
||||||
|
|
||||||
if (p.flags & lt::torrent_flags::stop_when_ready)
|
if (p.flags & lt::torrent_flags::stop_when_ready)
|
||||||
{
|
{
|
||||||
@@ -333,33 +329,29 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lt::entry data = lt::write_resume_data(p);
|
||||||
|
|
||||||
// metadata is stored in separate .torrent file
|
// metadata is stored in separate .torrent file
|
||||||
const std::shared_ptr<lt::torrent_info> torrentInfo = std::move(p.ti);
|
if (p.ti)
|
||||||
if (torrentInfo)
|
|
||||||
{
|
{
|
||||||
|
lt::entry::dictionary_type &dataDict = data.dict();
|
||||||
|
lt::entry metadata {lt::entry::dictionary_t};
|
||||||
|
lt::entry::dictionary_type &metadataDict = metadata.dict();
|
||||||
|
metadataDict.insert(dataDict.extract("info"));
|
||||||
|
metadataDict.insert(dataDict.extract("creation date"));
|
||||||
|
metadataDict.insert(dataDict.extract("created by"));
|
||||||
|
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)
|
||||||
const auto torrentCreator = lt::create_torrent(*torrentInfo);
|
|
||||||
const lt::entry metadata = torrentCreator.generate();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
catch (const std::exception &err)
|
|
||||||
{
|
|
||||||
LogMsg(tr("Couldn't save torrent metadata to '%1'. Error: %2.")
|
|
||||||
.arg(torrentFilepath, QString::fromLocal8Bit(err.what())), Log::CRITICAL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lt::entry data = lt::write_resume_data(p);
|
|
||||||
|
|
||||||
data["qBt-savePath"] = Profile::instance()->toPortablePath(resumeData.savePath).toStdString();
|
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;
|
||||||
@@ -371,14 +363,11 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
|
|||||||
data["qBt-firstLastPiecePriority"] = resumeData.firstLastPiecePriority;
|
data["qBt-firstLastPiecePriority"] = resumeData.firstLastPiecePriority;
|
||||||
|
|
||||||
const QString resumeFilepath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.fastresume").arg(id.toString()));
|
const QString resumeFilepath = m_resumeDataDir.absoluteFilePath(QString::fromLatin1("%1.fastresume").arg(id.toString()));
|
||||||
try
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(resumeFilepath, data);
|
||||||
{
|
if (!result)
|
||||||
writeEntryToFile(resumeFilepath, data);
|
|
||||||
}
|
|
||||||
catch (const RuntimeError &err)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,10 +388,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,12 +38,10 @@ class QThread;
|
|||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
class TorrentInfo;
|
|
||||||
|
|
||||||
class BencodeResumeDataStorage final : public ResumeDataStorage
|
class BencodeResumeDataStorage final : public ResumeDataStorage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(BencodeResumeDataStorage)
|
Q_DISABLE_COPY_MOVE(BencodeResumeDataStorage)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BencodeResumeDataStorage(const QString &path, QObject *parent = nullptr);
|
explicit BencodeResumeDataStorage(const QString &path, QObject *parent = nullptr);
|
||||||
@@ -57,7 +55,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void loadQueue(const QString &queueFilename);
|
void loadQueue(const QString &queueFilename);
|
||||||
std::optional<LoadTorrentParams> loadTorrentResumeData(const QByteArray &data, const TorrentInfo &metadata) const;
|
std::optional<LoadTorrentParams> loadTorrentResumeData(const QByteArray &data, const QByteArray &metadata) const;
|
||||||
|
|
||||||
const QDir m_resumeDataDir;
|
const QDir m_resumeDataDir;
|
||||||
QVector<TorrentID> m_registeredTorrents;
|
QVector<TorrentID> m_registeredTorrents;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
#include <libtorrent/session.hpp>
|
#include <libtorrent/session.hpp>
|
||||||
|
|
||||||
std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
|
std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
|
||||||
|
|||||||
@@ -30,11 +30,10 @@
|
|||||||
|
|
||||||
#include <libtorrent/aux_/vector.hpp>
|
#include <libtorrent/aux_/vector.hpp>
|
||||||
#include <libtorrent/fwd.hpp>
|
#include <libtorrent/fwd.hpp>
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
#include <libtorrent/disk_interface.hpp>
|
#include <libtorrent/disk_interface.hpp>
|
||||||
#include <libtorrent/file_storage.hpp>
|
#include <libtorrent/file_storage.hpp>
|
||||||
#include <libtorrent/io_context.hpp>
|
#include <libtorrent/io_context.hpp>
|
||||||
@@ -46,7 +45,7 @@
|
|||||||
#include <libtorrent/storage.hpp>
|
#include <libtorrent/storage.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
|
std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
|
||||||
lt::io_context &ioContext, lt::settings_interface const &settings, lt::counters &counters);
|
lt::io_context &ioContext, lt::settings_interface const &settings, lt::counters &counters);
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,9 @@
|
|||||||
|
|
||||||
#include <libtorrent/bdecode.hpp>
|
#include <libtorrent/bdecode.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
#include <libtorrent/create_torrent.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/write_resume_data.hpp>
|
#include <libtorrent/write_resume_data.hpp>
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
@@ -52,7 +52,6 @@
|
|||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "infohash.h"
|
#include "infohash.h"
|
||||||
#include "loadtorrentparams.h"
|
#include "loadtorrentparams.h"
|
||||||
#include "torrentinfo.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -158,7 +157,7 @@ namespace BitTorrent
|
|||||||
{
|
{
|
||||||
class DBResumeDataStorage::Worker final : public QObject
|
class DBResumeDataStorage::Worker final : public QObject
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY(Worker)
|
Q_DISABLE_COPY_MOVE(Worker)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Worker(const QString &dbPath, const QString &dbConnectionName);
|
Worker(const QString &dbPath, const QString &dbConnectionName);
|
||||||
@@ -290,20 +289,19 @@ std::optional<BitTorrent::LoadTorrentParams> BitTorrent::DBResumeDataStorage::lo
|
|||||||
resumeData.stopped = query.value(DB_COLUMN_STOPPED.name).toBool();
|
resumeData.stopped = query.value(DB_COLUMN_STOPPED.name).toBool();
|
||||||
|
|
||||||
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 allData = ((bencodedMetadata.isEmpty() || bencodedResumeData.isEmpty())
|
||||||
|
? bencodedResumeData
|
||||||
|
: (bencodedResumeData.chopped(1) + bencodedMetadata.mid(1)));
|
||||||
|
|
||||||
lt::error_code ec;
|
lt::error_code ec;
|
||||||
const lt::bdecode_node root = lt::bdecode(bencodedResumeData, ec);
|
const lt::bdecode_node root = lt::bdecode(allData, ec);
|
||||||
|
|
||||||
lt::add_torrent_params &p = resumeData.ltAddTorrentParams;
|
lt::add_torrent_params &p = resumeData.ltAddTorrentParams;
|
||||||
|
|
||||||
p = lt::read_resume_data(root, ec);
|
p = lt::read_resume_data(root, ec);
|
||||||
p.save_path = Profile::instance()->fromPortablePath(fromLTString(p.save_path)).toStdString();
|
p.save_path = Profile::instance()->fromPortablePath(fromLTString(p.save_path)).toStdString();
|
||||||
|
|
||||||
const QByteArray bencodedMetadata = query.value(DB_COLUMN_METADATA.name).toByteArray();
|
|
||||||
auto metadata = TorrentInfo::load(bencodedMetadata);
|
|
||||||
if (metadata.isValid())
|
|
||||||
p.ti = metadata.nativeInfo();
|
|
||||||
|
|
||||||
return resumeData;
|
return resumeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,16 +451,23 @@ void BitTorrent::DBResumeDataStorage::Worker::store(const TorrentID &id, const L
|
|||||||
DB_COLUMN_RESUMEDATA
|
DB_COLUMN_RESUMEDATA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
lt::entry data = lt::write_resume_data(p);
|
||||||
|
|
||||||
// metadata is stored in separate column
|
// metadata is stored in separate column
|
||||||
QByteArray bencodedMetadata;
|
QByteArray bencodedMetadata;
|
||||||
bencodedMetadata.reserve(512 * 1024);
|
if (p.ti)
|
||||||
const std::shared_ptr<lt::torrent_info> torrentInfo = std::move(p.ti);
|
|
||||||
if (torrentInfo)
|
|
||||||
{
|
{
|
||||||
|
lt::entry::dictionary_type &dataDict = data.dict();
|
||||||
|
lt::entry metadata {lt::entry::dictionary_t};
|
||||||
|
lt::entry::dictionary_type &metadataDict = metadata.dict();
|
||||||
|
metadataDict.insert(dataDict.extract("info"));
|
||||||
|
metadataDict.insert(dataDict.extract("creation date"));
|
||||||
|
metadataDict.insert(dataDict.extract("created by"));
|
||||||
|
metadataDict.insert(dataDict.extract("comment"));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto torrentCreator = lt::create_torrent(*torrentInfo);
|
bencodedMetadata.reserve(512 * 1024);
|
||||||
const lt::entry metadata = torrentCreator.generate();
|
|
||||||
lt::bencode(std::back_inserter(bencodedMetadata), metadata);
|
lt::bencode(std::back_inserter(bencodedMetadata), metadata);
|
||||||
}
|
}
|
||||||
catch (const std::exception &err)
|
catch (const std::exception &err)
|
||||||
@@ -477,7 +482,7 @@ void BitTorrent::DBResumeDataStorage::Worker::store(const TorrentID &id, const L
|
|||||||
|
|
||||||
QByteArray bencodedResumeData;
|
QByteArray bencodedResumeData;
|
||||||
bencodedResumeData.reserve(256 * 1024);
|
bencodedResumeData.reserve(256 * 1024);
|
||||||
lt::bencode(std::back_inserter(bencodedResumeData), lt::write_resume_data(p));
|
lt::bencode(std::back_inserter(bencodedResumeData), data);
|
||||||
|
|
||||||
const QString insertTorrentStatement = makeInsertStatement(DB_TABLE_TORRENTS, columns)
|
const QString insertTorrentStatement = makeInsertStatement(DB_TABLE_TORRENTS, columns)
|
||||||
+ makeOnConflictUpdateStatement(DB_COLUMN_TORRENT_ID, columns);
|
+ makeOnConflictUpdateStatement(DB_COLUMN_TORRENT_ID, columns);
|
||||||
@@ -503,7 +508,7 @@ void BitTorrent::DBResumeDataStorage::Worker::store(const TorrentID &id, const L
|
|||||||
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);
|
||||||
query.bindValue(DB_COLUMN_RESUMEDATA.placeholder, bencodedResumeData);
|
query.bindValue(DB_COLUMN_RESUMEDATA.placeholder, bencodedResumeData);
|
||||||
if (torrentInfo)
|
if (!bencodedMetadata.isEmpty())
|
||||||
query.bindValue(DB_COLUMN_METADATA.placeholder, bencodedMetadata);
|
query.bindValue(DB_COLUMN_METADATA.placeholder, bencodedMetadata);
|
||||||
|
|
||||||
if (!query.exec())
|
if (!query.exec())
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace BitTorrent
|
|||||||
class DBResumeDataStorage final : public ResumeDataStorage
|
class DBResumeDataStorage final : public ResumeDataStorage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(DBResumeDataStorage)
|
Q_DISABLE_COPY_MOVE(DBResumeDataStorage)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DBResumeDataStorage(const QString &dbPath, QObject *parent = nullptr);
|
explicit DBResumeDataStorage(const QString &dbPath, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace BitTorrent
|
|||||||
class FileSearcher final : public QObject
|
class FileSearcher final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(FileSearcher)
|
Q_DISABLE_COPY_MOVE(FileSearcher)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileSearcher() = default;
|
FileSearcher() = default;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ bool BitTorrent::InfoHash::isValid() const
|
|||||||
|
|
||||||
SHA1Hash BitTorrent::InfoHash::v1() const
|
SHA1Hash BitTorrent::InfoHash::v1() const
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
return (m_nativeHash.has_v1() ? SHA1Hash(m_nativeHash.v1) : SHA1Hash());
|
return (m_nativeHash.has_v1() ? SHA1Hash(m_nativeHash.v1) : SHA1Hash());
|
||||||
#else
|
#else
|
||||||
return {m_nativeHash};
|
return {m_nativeHash};
|
||||||
@@ -52,7 +52,7 @@ SHA1Hash BitTorrent::InfoHash::v1() const
|
|||||||
|
|
||||||
SHA256Hash BitTorrent::InfoHash::v2() const
|
SHA256Hash BitTorrent::InfoHash::v2() const
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
return (m_nativeHash.has_v2() ? SHA256Hash(m_nativeHash.v2) : SHA256Hash());
|
return (m_nativeHash.has_v2() ? SHA256Hash(m_nativeHash.v2) : SHA256Hash());
|
||||||
#else
|
#else
|
||||||
return {};
|
return {};
|
||||||
@@ -61,7 +61,7 @@ SHA256Hash BitTorrent::InfoHash::v2() const
|
|||||||
|
|
||||||
BitTorrent::TorrentID BitTorrent::InfoHash::toTorrentID() const
|
BitTorrent::TorrentID BitTorrent::InfoHash::toTorrentID() const
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
return m_nativeHash.get_best();
|
return m_nativeHash.get_best();
|
||||||
#else
|
#else
|
||||||
return {m_nativeHash};
|
return {m_nativeHash};
|
||||||
|
|||||||
@@ -28,8 +28,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libtorrent/version.hpp>
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
|
||||||
#include <libtorrent/info_hash.hpp>
|
#include <libtorrent/info_hash.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ namespace BitTorrent
|
|||||||
class InfoHash
|
class InfoHash
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
using WrappedType = lt::info_hash_t;
|
using WrappedType = lt::info_hash_t;
|
||||||
#else
|
#else
|
||||||
using WrappedType = lt::sha1_hash;
|
using WrappedType = lt::sha1_hash;
|
||||||
|
|||||||
@@ -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) 2019, 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,31 +28,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <libtorrent/download_priority.hpp>
|
||||||
|
|
||||||
template <typename T, typename = void>
|
#include "downloadpriority.h"
|
||||||
struct HasUnderlyingType
|
|
||||||
: std::false_type
|
namespace BitTorrent::LT
|
||||||
{
|
{
|
||||||
};
|
template <typename T>
|
||||||
|
constexpr typename T::underlying_type toUnderlyingType(const T &t) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<typename T::underlying_type>(t);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
constexpr lt::download_priority_t toNative(const DownloadPriority priority) noexcept
|
||||||
struct HasUnderlyingType<T, std::void_t<typename T::underlying_type>>
|
{
|
||||||
: std::true_type
|
return static_cast<lt::download_priority_t>(static_cast<lt::download_priority_t::underlying_type>(priority));
|
||||||
{
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
constexpr DownloadPriority fromNative(const lt::download_priority_t priority) noexcept
|
||||||
struct LTUnderlying
|
{
|
||||||
{
|
return static_cast<DownloadPriority>(toUnderlyingType(priority));
|
||||||
using type = T;
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct LTUnderlying<T, typename std::enable_if_t<HasUnderlyingType<T>::value>>
|
|
||||||
{
|
|
||||||
using type = typename T::underlying_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using LTUnderlyingType = typename LTUnderlying<T>::type;
|
|
||||||
@@ -39,21 +39,34 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool isSHA1Hash(const QString &string)
|
// BEP9 Extension for Peers to Send Metadata Files
|
||||||
|
|
||||||
|
bool isV1Hash(const QString &string)
|
||||||
{
|
{
|
||||||
// There are 2 representations for BitTorrent info hash:
|
// There are 2 representations for BitTorrent v1 info hash:
|
||||||
// 1. 40 chars hex-encoded string
|
// 1. 40 chars hex-encoded string
|
||||||
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
|
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
|
||||||
// 2. 32 chars Base32 encoded string
|
// 2. 32 chars Base32 encoded string
|
||||||
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
|
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
|
||||||
const int SHA1_HEX_SIZE = SHA1Hash::length() * 2;
|
const int V1_HEX_SIZE = SHA1Hash::length() * 2;
|
||||||
const int SHA1_BASE32_SIZE = SHA1Hash::length() * 1.6;
|
const int V1_BASE32_SIZE = SHA1Hash::length() * 1.6;
|
||||||
|
|
||||||
return ((((string.size() == SHA1_HEX_SIZE))
|
return ((((string.size() == V1_HEX_SIZE))
|
||||||
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
|
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
|
||||||
|| ((string.size() == SHA1_BASE32_SIZE)
|
|| ((string.size() == V1_BASE32_SIZE)
|
||||||
&& !string.contains(QRegularExpression(QLatin1String("[^2-7A-Za-z]")))));
|
&& !string.contains(QRegularExpression(QLatin1String("[^2-7A-Za-z]")))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isV2Hash(const QString &string)
|
||||||
|
{
|
||||||
|
// There are 1 representation for BitTorrent v2 info hash:
|
||||||
|
// 1. 64 chars hex-encoded string
|
||||||
|
// == 32 (SHA-2 256 length in bytes) * 2 (each byte maps to 2 hex characters)
|
||||||
|
const int V2_HEX_SIZE = SHA256Hash::length() * 2;
|
||||||
|
|
||||||
|
return (string.size() == V2_HEX_SIZE)
|
||||||
|
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
@@ -66,8 +79,10 @@ MagnetUri::MagnetUri(const QString &source)
|
|||||||
{
|
{
|
||||||
if (source.isEmpty()) return;
|
if (source.isEmpty()) return;
|
||||||
|
|
||||||
if (isSHA1Hash(source))
|
if (isV2Hash(source))
|
||||||
m_url = QLatin1String("magnet:?xt=urn:btih:") + source;
|
m_url = QString::fromLatin1("magnet:?xt=urn:btmh:1220") + source; // 0x12 0x20 is the "multihash format" tag for the SHA-256 hashing scheme.
|
||||||
|
else if (isV1Hash(source))
|
||||||
|
m_url = QString::fromLatin1("magnet:?xt=urn:btih:") + source;
|
||||||
|
|
||||||
lt::error_code ec;
|
lt::error_code ec;
|
||||||
lt::parse_magnet_uri(m_url.toStdString(), m_addTorrentParams, ec);
|
lt::parse_magnet_uri(m_url.toStdString(), m_addTorrentParams, ec);
|
||||||
@@ -75,7 +90,7 @@ MagnetUri::MagnetUri(const QString &source)
|
|||||||
|
|
||||||
m_valid = true;
|
m_valid = true;
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
m_infoHash = m_addTorrentParams.info_hashes;
|
m_infoHash = m_addTorrentParams.info_hashes;
|
||||||
#else
|
#else
|
||||||
m_infoHash = m_addTorrentParams.info_hash;
|
m_infoHash = m_addTorrentParams.info_hash;
|
||||||
|
|||||||
@@ -29,11 +29,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libtorrent/extensions.hpp>
|
#include <libtorrent/extensions.hpp>
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
|
|
||||||
class NativeSessionExtension final : public lt::plugin
|
class NativeSessionExtension final : public lt::plugin
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
using ClientData = lt::client_data_t;
|
using ClientData = lt::client_data_t;
|
||||||
#else
|
#else
|
||||||
using ClientData = void *;
|
using ClientData = void *;
|
||||||
|
|||||||
@@ -32,18 +32,18 @@
|
|||||||
|
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
|
|
||||||
PeerAddress PeerAddress::parse(const QString &address)
|
PeerAddress PeerAddress::parse(const QStringView address)
|
||||||
{
|
{
|
||||||
QVector<QStringRef> ipPort;
|
QList<QStringView> ipPort;
|
||||||
|
|
||||||
if (address.startsWith('[') && address.contains("]:"))
|
if (address.startsWith(u'[') && address.contains(QLatin1String("]:")))
|
||||||
{ // IPv6
|
{ // IPv6
|
||||||
ipPort = address.splitRef("]:");
|
ipPort = address.split(QString::fromLatin1("]:"));
|
||||||
ipPort[0] = ipPort[0].mid(1); // chop '['
|
ipPort[0] = ipPort[0].mid(1); // chop '['
|
||||||
}
|
}
|
||||||
else if (address.contains(':'))
|
else if (address.contains(u':'))
|
||||||
{ // IPv4
|
{ // IPv4
|
||||||
ipPort = address.splitRef(':');
|
ipPort = address.split(u':');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace BitTorrent
|
|||||||
QHostAddress ip;
|
QHostAddress ip;
|
||||||
ushort port = 0;
|
ushort port = 0;
|
||||||
|
|
||||||
static PeerAddress parse(const QString &address);
|
static PeerAddress parse(QStringView address);
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
class PortForwarderImpl final : public Net::PortForwarder
|
class PortForwarderImpl final : public Net::PortForwarder
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(PortForwarderImpl)
|
Q_DISABLE_COPY_MOVE(PortForwarderImpl)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PortForwarderImpl(lt::session *provider, QObject *parent = nullptr);
|
explicit PortForwarderImpl(lt::session *provider, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace BitTorrent
|
|||||||
class ResumeDataStorage : public QObject
|
class ResumeDataStorage : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(ResumeDataStorage)
|
Q_DISABLE_COPY_MOVE(ResumeDataStorage)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using QObject::QObject;
|
using QObject::QObject;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <ctime>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -69,7 +70,6 @@
|
|||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "base/algorithm.h"
|
#include "base/algorithm.h"
|
||||||
#include "base/exceptions.h"
|
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
@@ -89,10 +89,11 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "customstorage.h"
|
#include "customstorage.h"
|
||||||
#include "dbresumedatastorage.h"
|
#include "dbresumedatastorage.h"
|
||||||
|
#include "downloadpriority.h"
|
||||||
#include "filesearcher.h"
|
#include "filesearcher.h"
|
||||||
#include "filterparserthread.h"
|
#include "filterparserthread.h"
|
||||||
#include "loadtorrentparams.h"
|
#include "loadtorrentparams.h"
|
||||||
#include "ltunderlyingtype.h"
|
#include "lttypecast.h"
|
||||||
#include "magneturi.h"
|
#include "magneturi.h"
|
||||||
#include "nativesessionextension.h"
|
#include "nativesessionextension.h"
|
||||||
#include "portforwarderimpl.h"
|
#include "portforwarderimpl.h"
|
||||||
@@ -209,7 +210,7 @@ namespace
|
|||||||
{
|
{
|
||||||
switch (socketType)
|
switch (socketType)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
case lt::socket_type_t::http:
|
case lt::socket_type_t::http:
|
||||||
return QLatin1String("HTTP");
|
return QLatin1String("HTTP");
|
||||||
case lt::socket_type_t::http_ssl:
|
case lt::socket_type_t::http_ssl:
|
||||||
@@ -219,7 +220,7 @@ namespace
|
|||||||
return QLatin1String("I2P");
|
return QLatin1String("I2P");
|
||||||
case lt::socket_type_t::socks5:
|
case lt::socket_type_t::socks5:
|
||||||
return QLatin1String("SOCKS5");
|
return QLatin1String("SOCKS5");
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
case lt::socket_type_t::socks5_ssl:
|
case lt::socket_type_t::socks5_ssl:
|
||||||
return QLatin1String("SOCKS5_SSL");
|
return QLatin1String("SOCKS5_SSL");
|
||||||
#endif
|
#endif
|
||||||
@@ -227,7 +228,7 @@ namespace
|
|||||||
return QLatin1String("TCP");
|
return QLatin1String("TCP");
|
||||||
case lt::socket_type_t::tcp_ssl:
|
case lt::socket_type_t::tcp_ssl:
|
||||||
return QLatin1String("TCP_SSL");
|
return QLatin1String("TCP_SSL");
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
case lt::socket_type_t::utp:
|
case lt::socket_type_t::utp:
|
||||||
return QLatin1String("UTP");
|
return QLatin1String("UTP");
|
||||||
#else
|
#else
|
||||||
@@ -387,6 +388,7 @@ Session::Session(QObject *parent)
|
|||||||
, m_IDNSupportEnabled(BITTORRENT_SESSION_KEY("IDNSupportEnabled"), false)
|
, m_IDNSupportEnabled(BITTORRENT_SESSION_KEY("IDNSupportEnabled"), false)
|
||||||
, m_multiConnectionsPerIpEnabled(BITTORRENT_SESSION_KEY("MultiConnectionsPerIp"), false)
|
, m_multiConnectionsPerIpEnabled(BITTORRENT_SESSION_KEY("MultiConnectionsPerIp"), false)
|
||||||
, m_validateHTTPSTrackerCertificate(BITTORRENT_SESSION_KEY("ValidateHTTPSTrackerCertificate"), true)
|
, m_validateHTTPSTrackerCertificate(BITTORRENT_SESSION_KEY("ValidateHTTPSTrackerCertificate"), true)
|
||||||
|
, m_SSRFMitigationEnabled(BITTORRENT_SESSION_KEY("SSRFMitigation"), true)
|
||||||
, m_blockPeersOnPrivilegedPorts(BITTORRENT_SESSION_KEY("BlockPeersOnPrivilegedPorts"), false)
|
, m_blockPeersOnPrivilegedPorts(BITTORRENT_SESSION_KEY("BlockPeersOnPrivilegedPorts"), false)
|
||||||
, m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false)
|
, m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false)
|
||||||
, m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers"))
|
, m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers"))
|
||||||
@@ -407,7 +409,6 @@ Session::Session(QObject *parent)
|
|||||||
, m_isBandwidthSchedulerEnabled(BITTORRENT_SESSION_KEY("BandwidthSchedulerEnabled"), false)
|
, m_isBandwidthSchedulerEnabled(BITTORRENT_SESSION_KEY("BandwidthSchedulerEnabled"), false)
|
||||||
, m_saveResumeDataInterval(BITTORRENT_SESSION_KEY("SaveResumeDataInterval"), 60)
|
, m_saveResumeDataInterval(BITTORRENT_SESSION_KEY("SaveResumeDataInterval"), 60)
|
||||||
, m_port(BITTORRENT_SESSION_KEY("Port"), -1)
|
, m_port(BITTORRENT_SESSION_KEY("Port"), -1)
|
||||||
, m_useRandomPort(BITTORRENT_SESSION_KEY("UseRandomPort"), false)
|
|
||||||
, m_networkInterface(BITTORRENT_SESSION_KEY("Interface"))
|
, m_networkInterface(BITTORRENT_SESSION_KEY("Interface"))
|
||||||
, m_networkInterfaceName(BITTORRENT_SESSION_KEY("InterfaceName"))
|
, m_networkInterfaceName(BITTORRENT_SESSION_KEY("InterfaceName"))
|
||||||
, m_networkInterfaceAddress(BITTORRENT_SESSION_KEY("InterfaceAddress"))
|
, m_networkInterfaceAddress(BITTORRENT_SESSION_KEY("InterfaceAddress"))
|
||||||
@@ -1076,14 +1077,14 @@ void Session::initializeNativeSession()
|
|||||||
pack.set_bool(lt::settings_pack::enable_upnp, false);
|
pack.set_bool(lt::settings_pack::enable_upnp, false);
|
||||||
pack.set_bool(lt::settings_pack::enable_natpmp, false);
|
pack.set_bool(lt::settings_pack::enable_natpmp, false);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM > 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
// preserve the same behavior as in earlier libtorrent versions
|
// preserve the same behavior as in earlier libtorrent versions
|
||||||
pack.set_bool(lt::settings_pack::enable_set_file_valid_data, true);
|
pack.set_bool(lt::settings_pack::enable_set_file_valid_data, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
loadLTSettings(pack);
|
loadLTSettings(pack);
|
||||||
lt::session_params sessionParams {pack, {}};
|
lt::session_params sessionParams {pack, {}};
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
sessionParams.disk_io_constructor = customDiskIOConstructor;
|
sessionParams.disk_io_constructor = customDiskIOConstructor;
|
||||||
#endif
|
#endif
|
||||||
m_nativeSession = new lt::session {sessionParams};
|
m_nativeSession = new lt::session {sessionParams};
|
||||||
@@ -1175,7 +1176,7 @@ void Session::initMetrics()
|
|||||||
|
|
||||||
m_metricIndices.disk.diskBlocksInUse = findMetricIndex("disk.disk_blocks_in_use");
|
m_metricIndices.disk.diskBlocksInUse = findMetricIndex("disk.disk_blocks_in_use");
|
||||||
m_metricIndices.disk.numBlocksRead = findMetricIndex("disk.num_blocks_read");
|
m_metricIndices.disk.numBlocksRead = findMetricIndex("disk.num_blocks_read");
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
m_metricIndices.disk.numBlocksCacheHits = findMetricIndex("disk.num_blocks_cache_hits");
|
m_metricIndices.disk.numBlocksCacheHits = findMetricIndex("disk.num_blocks_cache_hits");
|
||||||
#endif
|
#endif
|
||||||
m_metricIndices.disk.writeJobs = findMetricIndex("disk.num_write_ops");
|
m_metricIndices.disk.writeJobs = findMetricIndex("disk.num_write_ops");
|
||||||
@@ -1262,7 +1263,7 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack)
|
|||||||
settingsPack.set_int(lt::settings_pack::peer_turnover_interval, peerTurnoverInterval());
|
settingsPack.set_int(lt::settings_pack::peer_turnover_interval, peerTurnoverInterval());
|
||||||
|
|
||||||
settingsPack.set_int(lt::settings_pack::aio_threads, asyncIOThreads());
|
settingsPack.set_int(lt::settings_pack::aio_threads, asyncIOThreads());
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
settingsPack.set_int(lt::settings_pack::hashing_threads, hashingThreads());
|
settingsPack.set_int(lt::settings_pack::hashing_threads, hashingThreads());
|
||||||
#endif
|
#endif
|
||||||
settingsPack.set_int(lt::settings_pack::file_pool_size, filePoolSize());
|
settingsPack.set_int(lt::settings_pack::file_pool_size, filePoolSize());
|
||||||
@@ -1270,7 +1271,7 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack)
|
|||||||
const int checkingMemUsageSize = checkingMemUsage() * 64;
|
const int checkingMemUsageSize = checkingMemUsage() * 64;
|
||||||
settingsPack.set_int(lt::settings_pack::checking_mem_usage, checkingMemUsageSize);
|
settingsPack.set_int(lt::settings_pack::checking_mem_usage, checkingMemUsageSize);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
const int cacheSize = (diskCacheSize() > -1) ? (diskCacheSize() * 64) : -1;
|
const int cacheSize = (diskCacheSize() > -1) ? (diskCacheSize() * 64) : -1;
|
||||||
settingsPack.set_int(lt::settings_pack::cache_size, cacheSize);
|
settingsPack.set_int(lt::settings_pack::cache_size, cacheSize);
|
||||||
settingsPack.set_int(lt::settings_pack::cache_expiry, diskCacheTTL());
|
settingsPack.set_int(lt::settings_pack::cache_expiry, diskCacheTTL());
|
||||||
@@ -1281,7 +1282,7 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack)
|
|||||||
settingsPack.set_int(lt::settings_pack::disk_io_read_mode, mode);
|
settingsPack.set_int(lt::settings_pack::disk_io_read_mode, mode);
|
||||||
settingsPack.set_int(lt::settings_pack::disk_io_write_mode, mode);
|
settingsPack.set_int(lt::settings_pack::disk_io_write_mode, mode);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
settingsPack.set_bool(lt::settings_pack::coalesce_reads, isCoalesceReadWriteEnabled());
|
settingsPack.set_bool(lt::settings_pack::coalesce_reads, isCoalesceReadWriteEnabled());
|
||||||
settingsPack.set_bool(lt::settings_pack::coalesce_writes, isCoalesceReadWriteEnabled());
|
settingsPack.set_bool(lt::settings_pack::coalesce_writes, isCoalesceReadWriteEnabled());
|
||||||
#endif
|
#endif
|
||||||
@@ -1381,6 +1382,8 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack)
|
|||||||
|
|
||||||
settingsPack.set_bool(lt::settings_pack::validate_https_trackers, validateHTTPSTrackerCertificate());
|
settingsPack.set_bool(lt::settings_pack::validate_https_trackers, validateHTTPSTrackerCertificate());
|
||||||
|
|
||||||
|
settingsPack.set_bool(lt::settings_pack::ssrf_mitigation, isSSRFMitigationEnabled());
|
||||||
|
|
||||||
settingsPack.set_bool(lt::settings_pack::no_connect_privileged_ports, blockPeersOnPrivilegedPorts());
|
settingsPack.set_bool(lt::settings_pack::no_connect_privileged_ports, blockPeersOnPrivilegedPorts());
|
||||||
|
|
||||||
settingsPack.set_bool(lt::settings_pack::apply_ip_filter_to_trackers, isTrackerFilteringEnabled());
|
settingsPack.set_bool(lt::settings_pack::apply_ip_filter_to_trackers, isTrackerFilteringEnabled());
|
||||||
@@ -1421,13 +1424,12 @@ void Session::configureNetworkInterfaces(lt::settings_pack &settingsPack)
|
|||||||
if (m_listenInterfaceConfigured)
|
if (m_listenInterfaceConfigured)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int port = useRandomPort() ? 0 : this->port();
|
if (port() > 0) // user has specified port number
|
||||||
if (port > 0) // user specified port
|
|
||||||
settingsPack.set_int(lt::settings_pack::max_retry_port_bind, 0);
|
settingsPack.set_int(lt::settings_pack::max_retry_port_bind, 0);
|
||||||
|
|
||||||
QStringList endpoints;
|
QStringList endpoints;
|
||||||
QStringList outgoingInterfaces;
|
QStringList outgoingInterfaces;
|
||||||
const QString portString = ':' + QString::number(port);
|
const QString portString = ':' + QString::number(port());
|
||||||
|
|
||||||
for (const QString &ip : asConst(getListeningIPs()))
|
for (const QString &ip : asConst(getListeningIPs()))
|
||||||
{
|
{
|
||||||
@@ -1489,7 +1491,7 @@ void Session::configurePeerClasses()
|
|||||||
// Proactively do the same for 0.0.0.0 and address_v4::any()
|
// Proactively do the same for 0.0.0.0 and address_v4::any()
|
||||||
f.add_rule(lt::address_v4::any()
|
f.add_rule(lt::address_v4::any()
|
||||||
, lt::address_v4::broadcast()
|
, lt::address_v4::broadcast()
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::global_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::global_peer_class_id));
|
||||||
|
|
||||||
// IPv6 may not be available on OS and the parsing
|
// IPv6 may not be available on OS and the parsing
|
||||||
// would result in an exception -> abnormal program termination
|
// would result in an exception -> abnormal program termination
|
||||||
@@ -1498,7 +1500,7 @@ void Session::configurePeerClasses()
|
|||||||
{
|
{
|
||||||
f.add_rule(lt::address_v6::any()
|
f.add_rule(lt::address_v6::any()
|
||||||
, lt::make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
, lt::make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::global_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::global_peer_class_id));
|
||||||
}
|
}
|
||||||
catch (const std::exception &) {}
|
catch (const std::exception &) {}
|
||||||
|
|
||||||
@@ -1507,21 +1509,21 @@ void Session::configurePeerClasses()
|
|||||||
// local networks
|
// local networks
|
||||||
f.add_rule(lt::make_address("10.0.0.0")
|
f.add_rule(lt::make_address("10.0.0.0")
|
||||||
, lt::make_address("10.255.255.255")
|
, lt::make_address("10.255.255.255")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
f.add_rule(lt::make_address("172.16.0.0")
|
f.add_rule(lt::make_address("172.16.0.0")
|
||||||
, lt::make_address("172.31.255.255")
|
, lt::make_address("172.31.255.255")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
f.add_rule(lt::make_address("192.168.0.0")
|
f.add_rule(lt::make_address("192.168.0.0")
|
||||||
, lt::make_address("192.168.255.255")
|
, lt::make_address("192.168.255.255")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
// link local
|
// link local
|
||||||
f.add_rule(lt::make_address("169.254.0.0")
|
f.add_rule(lt::make_address("169.254.0.0")
|
||||||
, lt::make_address("169.254.255.255")
|
, lt::make_address("169.254.255.255")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
// loopback
|
// loopback
|
||||||
f.add_rule(lt::make_address("127.0.0.0")
|
f.add_rule(lt::make_address("127.0.0.0")
|
||||||
, lt::make_address("127.255.255.255")
|
, lt::make_address("127.255.255.255")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
|
|
||||||
// IPv6 may not be available on OS and the parsing
|
// IPv6 may not be available on OS and the parsing
|
||||||
// would result in an exception -> abnormal program termination
|
// would result in an exception -> abnormal program termination
|
||||||
@@ -1531,15 +1533,15 @@ void Session::configurePeerClasses()
|
|||||||
// link local
|
// link local
|
||||||
f.add_rule(lt::make_address("fe80::")
|
f.add_rule(lt::make_address("fe80::")
|
||||||
, lt::make_address("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
, lt::make_address("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
// unique local addresses
|
// unique local addresses
|
||||||
f.add_rule(lt::make_address("fc00::")
|
f.add_rule(lt::make_address("fc00::")
|
||||||
, lt::make_address("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
, lt::make_address("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
// loopback
|
// loopback
|
||||||
f.add_rule(lt::address_v6::loopback()
|
f.add_rule(lt::address_v6::loopback()
|
||||||
, lt::address_v6::loopback()
|
, lt::address_v6::loopback()
|
||||||
, 1 << static_cast<LTUnderlyingType<lt::peer_class_t>>(lt::session::local_peer_class_id));
|
, 1 << LT::toUnderlyingType(lt::session::local_peer_class_id));
|
||||||
}
|
}
|
||||||
catch (const std::exception &) {}
|
catch (const std::exception &) {}
|
||||||
}
|
}
|
||||||
@@ -1590,7 +1592,7 @@ void Session::populateAdditionalTrackers()
|
|||||||
m_additionalTrackerList.clear();
|
m_additionalTrackerList.clear();
|
||||||
|
|
||||||
const QString trackers = additionalTrackers();
|
const QString trackers = additionalTrackers();
|
||||||
for (QStringRef tracker : asConst(trackers.splitRef('\n')))
|
for (QStringView tracker : asConst(QStringView(trackers).split(u'\n')))
|
||||||
{
|
{
|
||||||
tracker = tracker.trimmed();
|
tracker = tracker.trimmed();
|
||||||
if (!tracker.isEmpty())
|
if (!tracker.isEmpty())
|
||||||
@@ -1696,7 +1698,7 @@ void Session::handleDownloadFinished(const Net::DownloadResult &result)
|
|||||||
{
|
{
|
||||||
case Net::DownloadStatus::Success:
|
case Net::DownloadStatus::Success:
|
||||||
emit downloadFromUrlFinished(result.url);
|
emit downloadFromUrlFinished(result.url);
|
||||||
addTorrent(TorrentInfo::load(result.data), m_downloadedTorrents.take(result.url));
|
addTorrent(TorrentInfo::load(result.data).value_or(TorrentInfo()), m_downloadedTorrents.take(result.url));
|
||||||
break;
|
break;
|
||||||
case Net::DownloadStatus::RedirectedToMagnet:
|
case Net::DownloadStatus::RedirectedToMagnet:
|
||||||
emit downloadFromUrlFinished(result.url);
|
emit downloadFromUrlFinished(result.url);
|
||||||
@@ -1725,8 +1727,10 @@ void Session::fileSearchFinished(const TorrentID &id, const QString &savePath, c
|
|||||||
lt::add_torrent_params &p = params.ltAddTorrentParams;
|
lt::add_torrent_params &p = params.ltAddTorrentParams;
|
||||||
|
|
||||||
p.save_path = Utils::Fs::toNativePath(savePath).toStdString();
|
p.save_path = Utils::Fs::toNativePath(savePath).toStdString();
|
||||||
|
const TorrentInfo torrentInfo {p.ti};
|
||||||
|
const auto nativeIndexes = torrentInfo.nativeIndexes();
|
||||||
for (int i = 0; i < fileNames.size(); ++i)
|
for (int i = 0; i < fileNames.size(); ++i)
|
||||||
p.renamed_files[lt::file_index_t {i}] = fileNames[i].toStdString();
|
p.renamed_files[nativeIndexes[i]] = fileNames[i].toStdString();
|
||||||
|
|
||||||
loadTorrent(params);
|
loadTorrent(params);
|
||||||
}
|
}
|
||||||
@@ -2024,7 +2028,7 @@ bool Session::addTorrent(const QString &source, const AddTorrentParams ¶ms)
|
|||||||
return addTorrent(magnetUri, params);
|
return addTorrent(magnetUri, params);
|
||||||
|
|
||||||
TorrentFileGuard guard {source};
|
TorrentFileGuard guard {source};
|
||||||
if (addTorrent(TorrentInfo::loadFromFile(source), params))
|
if (addTorrent(TorrentInfo::loadFromFile(source).value_or(TorrentInfo()), params))
|
||||||
{
|
{
|
||||||
guard.markAsAddedToSession();
|
guard.markAsAddedToSession();
|
||||||
return true;
|
return true;
|
||||||
@@ -2139,19 +2143,20 @@ bool Session::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source
|
|||||||
{
|
{
|
||||||
QString contentName = metadata.rootFolder();
|
QString contentName = metadata.rootFolder();
|
||||||
if (contentName.isEmpty() && (metadata.filesCount() == 1))
|
if (contentName.isEmpty() && (metadata.filesCount() == 1))
|
||||||
contentName = metadata.fileName(0);
|
contentName = Utils::Fs::fileName(metadata.filePath(0));
|
||||||
|
|
||||||
if (!contentName.isEmpty() && (contentName != metadata.name()))
|
if (!contentName.isEmpty() && (contentName != metadata.name()))
|
||||||
loadTorrentParams.name = contentName;
|
loadTorrentParams.name = contentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(p.file_priorities.empty());
|
Q_ASSERT(p.file_priorities.empty());
|
||||||
std::transform(addTorrentParams.filePriorities.cbegin(), addTorrentParams.filePriorities.cend()
|
const int internalFilesCount = metadata.nativeInfo()->files().num_files(); // including .pad files
|
||||||
, std::back_inserter(p.file_priorities), [](const DownloadPriority priority)
|
// Use qBittorrent default priority rather than libtorrent's (4)
|
||||||
{
|
p.file_priorities = std::vector(internalFilesCount, LT::toNative(DownloadPriority::Normal));
|
||||||
return static_cast<lt::download_priority_t>(
|
const auto nativeIndexes = metadata.nativeIndexes();
|
||||||
static_cast<lt::download_priority_t::underlying_type>(priority));
|
Q_ASSERT(addTorrentParams.filePriorities.isEmpty() || (addTorrentParams.filePriorities.size() == nativeIndexes.size()));
|
||||||
});
|
for (int i = 0; i < addTorrentParams.filePriorities.size(); ++i)
|
||||||
|
p.file_priorities[LT::toUnderlyingType(nativeIndexes[i])] = LT::toNative(addTorrentParams.filePriorities[i]);
|
||||||
|
|
||||||
p.ti = metadata.nativeInfo();
|
p.ti = metadata.nativeInfo();
|
||||||
}
|
}
|
||||||
@@ -2192,6 +2197,8 @@ bool Session::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source
|
|||||||
else
|
else
|
||||||
p.flags |= lt::torrent_flags::auto_managed;
|
p.flags |= lt::torrent_flags::auto_managed;
|
||||||
|
|
||||||
|
p.added_time = std::time(nullptr);
|
||||||
|
|
||||||
if (!isFindingIncompleteFiles)
|
if (!isFindingIncompleteFiles)
|
||||||
return loadTorrent(loadTorrentParams);
|
return loadTorrent(loadTorrentParams);
|
||||||
|
|
||||||
@@ -2204,7 +2211,7 @@ bool Session::loadTorrent(LoadTorrentParams params)
|
|||||||
{
|
{
|
||||||
lt::add_torrent_params &p = params.ltAddTorrentParams;
|
lt::add_torrent_params &p = params.ltAddTorrentParams;
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
p.storage = customStorageConstructor;
|
p.storage = customStorageConstructor;
|
||||||
#endif
|
#endif
|
||||||
// Limits
|
// Limits
|
||||||
@@ -2212,7 +2219,7 @@ bool Session::loadTorrent(LoadTorrentParams params)
|
|||||||
p.max_uploads = maxUploadsPerTorrent();
|
p.max_uploads = maxUploadsPerTorrent();
|
||||||
|
|
||||||
const bool hasMetadata = (p.ti && p.ti->is_valid());
|
const bool hasMetadata = (p.ti && p.ti->is_valid());
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? p.ti->info_hashes() : p.info_hashes);
|
const auto id = TorrentID::fromInfoHash(hasMetadata ? p.ti->info_hashes() : p.info_hashes);
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? p.ti->info_hash() : p.info_hash);
|
const auto id = TorrentID::fromInfoHash(hasMetadata ? p.ti->info_hash() : p.info_hash);
|
||||||
@@ -2279,7 +2286,7 @@ bool Session::downloadMetadata(const MagnetUri &magnetUri)
|
|||||||
// Solution to avoid accidental file writes
|
// Solution to avoid accidental file writes
|
||||||
p.flags |= lt::torrent_flags::upload_mode;
|
p.flags |= lt::torrent_flags::upload_mode;
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
p.storage = customStorageConstructor;
|
p.storage = customStorageConstructor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2296,33 +2303,27 @@ bool Session::downloadMetadata(const MagnetUri &magnetUri)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::exportTorrentFile(const Torrent *torrent, TorrentExportFolder folder)
|
void Session::exportTorrentFile(const TorrentInfo &torrentInfo, const QString &folderPath, const QString &baseName)
|
||||||
{
|
{
|
||||||
Q_ASSERT(((folder == TorrentExportFolder::Regular) && !torrentExportDirectory().isEmpty()) ||
|
const QString validName = Utils::Fs::toValidFileSystemName(baseName);
|
||||||
((folder == TorrentExportFolder::Finished) && !finishedTorrentExportDirectory().isEmpty()));
|
|
||||||
|
|
||||||
const QString validName = Utils::Fs::toValidFileSystemName(torrent->name());
|
|
||||||
QString torrentExportFilename = QString::fromLatin1("%1.torrent").arg(validName);
|
QString torrentExportFilename = QString::fromLatin1("%1.torrent").arg(validName);
|
||||||
const QDir exportPath(folder == TorrentExportFolder::Regular ? torrentExportDirectory() : finishedTorrentExportDirectory());
|
const QDir exportDir {folderPath};
|
||||||
if (exportPath.exists() || exportPath.mkpath(exportPath.absolutePath()))
|
if (exportDir.exists() || exportDir.mkpath(exportDir.absolutePath()))
|
||||||
{
|
{
|
||||||
QString newTorrentPath = exportPath.absoluteFilePath(torrentExportFilename);
|
QString newTorrentPath = exportDir.absoluteFilePath(torrentExportFilename);
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while (QFile::exists(newTorrentPath))
|
while (QFile::exists(newTorrentPath))
|
||||||
{
|
{
|
||||||
// Append number to torrent name to make it unique
|
// Append number to torrent name to make it unique
|
||||||
torrentExportFilename = QString::fromLatin1("%1 %2.torrent").arg(validName).arg(++counter);
|
torrentExportFilename = QString::fromLatin1("%1 %2.torrent").arg(validName).arg(++counter);
|
||||||
newTorrentPath = exportPath.absoluteFilePath(torrentExportFilename);
|
newTorrentPath = exportDir.absoluteFilePath(torrentExportFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
const nonstd::expected<void, QString> result = torrentInfo.saveToFile(newTorrentPath);
|
||||||
{
|
if (!result)
|
||||||
torrent->info().saveToFile(newTorrentPath);
|
|
||||||
}
|
|
||||||
catch (const RuntimeError &err)
|
|
||||||
{
|
{
|
||||||
LogMsg(tr("Couldn't export torrent metadata file '%1'. Reason: %2.")
|
LogMsg(tr("Couldn't export torrent metadata file '%1'. Reason: %2.")
|
||||||
.arg(newTorrentPath, err.message()), Log::WARNING);
|
.arg(newTorrentPath, result.error()), Log::WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2380,7 +2381,7 @@ void Session::saveTorrentsQueue() const
|
|||||||
for (const TorrentImpl *torrent : asConst(m_torrents))
|
for (const TorrentImpl *torrent : asConst(m_torrents))
|
||||||
{
|
{
|
||||||
// We require actual (non-cached) queue position here!
|
// We require actual (non-cached) queue position here!
|
||||||
const int queuePos = static_cast<LTUnderlyingType<lt::queue_position_t>>(torrent->nativeHandle().queue_position());
|
const int queuePos = LT::toUnderlyingType(torrent->nativeHandle().queue_position());
|
||||||
if (queuePos >= 0)
|
if (queuePos >= 0)
|
||||||
{
|
{
|
||||||
if (queuePos >= queue.size())
|
if (queuePos >= queue.size())
|
||||||
@@ -2525,7 +2526,7 @@ QStringList Session::getListeningIPs() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QList<QNetworkAddressEntry> addresses = networkIFace.addressEntries();
|
const QList<QNetworkAddressEntry> addresses = networkIFace.addressEntries();
|
||||||
qDebug("This network interface has %d IP addresses", addresses.size());
|
qDebug() << "This network interface has " << addresses.size() << " IP addresses";
|
||||||
for (const QNetworkAddressEntry &entry : addresses)
|
for (const QNetworkAddressEntry &entry : addresses)
|
||||||
checkAndAddIP(entry.ip(), configuredAddr);
|
checkAndAddIP(entry.ip(), configuredAddr);
|
||||||
|
|
||||||
@@ -2754,16 +2755,6 @@ void Session::setPort(const int port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Session::useRandomPort() const
|
|
||||||
{
|
|
||||||
return m_useRandomPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::setUseRandomPort(const bool value)
|
|
||||||
{
|
|
||||||
m_useRandomPort = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Session::networkInterface() const
|
QString Session::networkInterface() const
|
||||||
{
|
{
|
||||||
return m_networkInterface;
|
return m_networkInterface;
|
||||||
@@ -2931,7 +2922,7 @@ void Session::setBannedIPs(const QStringList &newList)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogMsg(tr("%1 is not a valid IP address and was rejected while applying the list of banned addresses.")
|
LogMsg(tr("%1 is not a valid IP address and was rejected while applying the list of banned IP addresses.")
|
||||||
.arg(ip)
|
.arg(ip)
|
||||||
, Log::WARNING);
|
, Log::WARNING);
|
||||||
}
|
}
|
||||||
@@ -3753,6 +3744,19 @@ void Session::setValidateHTTPSTrackerCertificate(const bool enabled)
|
|||||||
configureDeferred();
|
configureDeferred();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Session::isSSRFMitigationEnabled() const
|
||||||
|
{
|
||||||
|
return m_SSRFMitigationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::setSSRFMitigationEnabled(const bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled == m_SSRFMitigationEnabled) return;
|
||||||
|
|
||||||
|
m_SSRFMitigationEnabled = enabled;
|
||||||
|
configureDeferred();
|
||||||
|
}
|
||||||
|
|
||||||
bool Session::blockPeersOnPrivilegedPorts() const
|
bool Session::blockPeersOnPrivilegedPorts() const
|
||||||
{
|
{
|
||||||
return m_blockPeersOnPrivilegedPorts;
|
return m_blockPeersOnPrivilegedPorts;
|
||||||
@@ -3893,7 +3897,14 @@ void Session::handleTorrentMetadataReceived(TorrentImpl *const torrent)
|
|||||||
{
|
{
|
||||||
// Copy the torrent file to the export folder
|
// Copy the torrent file to the export folder
|
||||||
if (!torrentExportDirectory().isEmpty())
|
if (!torrentExportDirectory().isEmpty())
|
||||||
exportTorrentFile(torrent);
|
{
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
const TorrentInfo torrentInfo {torrent->nativeHandle().torrent_file_with_hashes()};
|
||||||
|
#else
|
||||||
|
const TorrentInfo torrentInfo {torrent->nativeHandle().torrent_file()};
|
||||||
|
#endif
|
||||||
|
exportTorrentFile(torrentInfo, torrentExportDirectory(), torrent->name());
|
||||||
|
}
|
||||||
|
|
||||||
emit torrentMetadataReceived(torrent);
|
emit torrentMetadataReceived(torrent);
|
||||||
}
|
}
|
||||||
@@ -3919,16 +3930,14 @@ void Session::handleTorrentFinished(TorrentImpl *const torrent)
|
|||||||
|
|
||||||
qDebug("Checking if the torrent contains torrent files to download");
|
qDebug("Checking if the torrent contains torrent files to download");
|
||||||
// Check if there are torrent files inside
|
// Check if there are torrent files inside
|
||||||
for (int i = 0; i < torrent->filesCount(); ++i)
|
for (const QString &torrentRelpath : asConst(torrent->filePaths()))
|
||||||
{
|
{
|
||||||
const QString torrentRelpath = torrent->filePath(i);
|
|
||||||
if (torrentRelpath.endsWith(".torrent", Qt::CaseInsensitive))
|
if (torrentRelpath.endsWith(".torrent", Qt::CaseInsensitive))
|
||||||
{
|
{
|
||||||
qDebug("Found possible recursive torrent download.");
|
qDebug("Found possible recursive torrent download.");
|
||||||
const QString torrentFullpath = torrent->savePath(true) + '/' + torrentRelpath;
|
const QString torrentFullpath = torrent->savePath(true) + '/' + torrentRelpath;
|
||||||
qDebug("Full subtorrent path is %s", qUtf8Printable(torrentFullpath));
|
qDebug("Full subtorrent path is %s", qUtf8Printable(torrentFullpath));
|
||||||
TorrentInfo torrentInfo = TorrentInfo::loadFromFile(torrentFullpath);
|
if (TorrentInfo::loadFromFile(torrentFullpath))
|
||||||
if (torrentInfo.isValid())
|
|
||||||
{
|
{
|
||||||
qDebug("emitting recursiveTorrentDownloadPossible()");
|
qDebug("emitting recursiveTorrentDownloadPossible()");
|
||||||
emit recursiveTorrentDownloadPossible(torrent);
|
emit recursiveTorrentDownloadPossible(torrent);
|
||||||
@@ -3944,7 +3953,14 @@ void Session::handleTorrentFinished(TorrentImpl *const torrent)
|
|||||||
|
|
||||||
// Move .torrent file to another folder
|
// Move .torrent file to another folder
|
||||||
if (!finishedTorrentExportDirectory().isEmpty())
|
if (!finishedTorrentExportDirectory().isEmpty())
|
||||||
exportTorrentFile(torrent, TorrentExportFolder::Finished);
|
{
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
const TorrentInfo torrentInfo {torrent->nativeHandle().torrent_file_with_hashes()};
|
||||||
|
#else
|
||||||
|
const TorrentInfo torrentInfo {torrent->nativeHandle().torrent_file()};
|
||||||
|
#endif
|
||||||
|
exportTorrentFile(torrentInfo, finishedTorrentExportDirectory(), torrent->name());
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasUnfinishedTorrents())
|
if (!hasUnfinishedTorrents())
|
||||||
emit allTorrentsFinished();
|
emit allTorrentsFinished();
|
||||||
@@ -4023,7 +4039,7 @@ bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const QString &newP
|
|||||||
|
|
||||||
void Session::moveTorrentStorage(const MoveStorageJob &job) const
|
void Session::moveTorrentStorage(const MoveStorageJob &job) const
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(job.torrentHandle.info_hashes());
|
const auto id = TorrentID::fromInfoHash(job.torrentHandle.info_hashes());
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(job.torrentHandle.info_hash());
|
const auto id = TorrentID::fromInfoHash(job.torrentHandle.info_hash());
|
||||||
@@ -4137,9 +4153,8 @@ void Session::recursiveTorrentDownload(const TorrentID &id)
|
|||||||
TorrentImpl *const torrent = m_torrents.value(id);
|
TorrentImpl *const torrent = m_torrents.value(id);
|
||||||
if (!torrent) return;
|
if (!torrent) return;
|
||||||
|
|
||||||
for (int i = 0; i < torrent->filesCount(); ++i)
|
for (const QString &torrentRelpath : asConst(torrent->filePaths()))
|
||||||
{
|
{
|
||||||
const QString torrentRelpath = torrent->filePath(i);
|
|
||||||
if (torrentRelpath.endsWith(".torrent"))
|
if (torrentRelpath.endsWith(".torrent"))
|
||||||
{
|
{
|
||||||
LogMsg(tr("Recursive download of file '%1' embedded in torrent '%2'"
|
LogMsg(tr("Recursive download of file '%1' embedded in torrent '%2'"
|
||||||
@@ -4150,7 +4165,7 @@ void Session::recursiveTorrentDownload(const TorrentID &id)
|
|||||||
AddTorrentParams params;
|
AddTorrentParams params;
|
||||||
// Passing the save path along to the sub torrent file
|
// Passing the save path along to the sub torrent file
|
||||||
params.savePath = torrent->savePath();
|
params.savePath = torrent->savePath();
|
||||||
addTorrent(TorrentInfo::loadFromFile(torrentFullpath), params);
|
addTorrent(TorrentInfo::loadFromFile(torrentFullpath).value_or(TorrentInfo()), params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4322,7 +4337,7 @@ void Session::handleAlert(const lt::alert *a)
|
|||||||
{
|
{
|
||||||
switch (a->type())
|
switch (a->type())
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20003)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
case lt::file_prio_alert::alert_type:
|
case lt::file_prio_alert::alert_type:
|
||||||
#endif
|
#endif
|
||||||
case lt::file_renamed_alert::alert_type:
|
case lt::file_renamed_alert::alert_type:
|
||||||
@@ -4424,7 +4439,7 @@ void Session::dispatchTorrentAlert(const lt::alert *a)
|
|||||||
|
|
||||||
void Session::createTorrent(const lt::torrent_handle &nativeHandle)
|
void Session::createTorrent(const lt::torrent_handle &nativeHandle)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto torrentID = TorrentID::fromInfoHash(nativeHandle.info_hashes());
|
const auto torrentID = TorrentID::fromInfoHash(nativeHandle.info_hashes());
|
||||||
#else
|
#else
|
||||||
const auto torrentID = TorrentID::fromInfoHash(nativeHandle.info_hash());
|
const auto torrentID = TorrentID::fromInfoHash(nativeHandle.info_hash());
|
||||||
@@ -4452,7 +4467,10 @@ void Session::createTorrent(const lt::torrent_handle &nativeHandle)
|
|||||||
{
|
{
|
||||||
// Copy the torrent file to the export folder
|
// Copy the torrent file to the export folder
|
||||||
if (!torrentExportDirectory().isEmpty())
|
if (!torrentExportDirectory().isEmpty())
|
||||||
exportTorrentFile(torrent);
|
{
|
||||||
|
const TorrentInfo torrentInfo {params.ltAddTorrentParams.ti};
|
||||||
|
exportTorrentFile(torrentInfo, torrentExportDirectory(), torrent->name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAddTrackersEnabled() && !torrent->isPrivate())
|
if (isAddTrackersEnabled() && !torrent->isPrivate())
|
||||||
@@ -4487,7 +4505,7 @@ void Session::handleAddTorrentAlert(const lt::add_torrent_alert *p)
|
|||||||
|
|
||||||
const lt::add_torrent_params ¶ms = p->params;
|
const lt::add_torrent_params ¶ms = p->params;
|
||||||
const bool hasMetadata = (params.ti && params.ti->is_valid());
|
const bool hasMetadata = (params.ti && params.ti->is_valid());
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? params.ti->info_hashes() : params.info_hashes);
|
const auto id = TorrentID::fromInfoHash(hasMetadata ? params.ti->info_hashes() : params.info_hashes);
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? params.ti->info_hash() : params.info_hash);
|
const auto id = TorrentID::fromInfoHash(hasMetadata ? params.ti->info_hash() : params.info_hash);
|
||||||
@@ -4502,7 +4520,7 @@ void Session::handleAddTorrentAlert(const lt::add_torrent_alert *p)
|
|||||||
|
|
||||||
void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
|
void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
||||||
@@ -4521,7 +4539,7 @@ void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
|
|||||||
|
|
||||||
void Session::handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p)
|
void Session::handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
||||||
@@ -4539,7 +4557,7 @@ void Session::handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p)
|
|||||||
|
|
||||||
void Session::handleTorrentDeleteFailedAlert(const lt::torrent_delete_failed_alert *p)
|
void Session::handleTorrentDeleteFailedAlert(const lt::torrent_delete_failed_alert *p)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
||||||
@@ -4569,7 +4587,7 @@ void Session::handleTorrentDeleteFailedAlert(const lt::torrent_delete_failed_ale
|
|||||||
|
|
||||||
void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
|
void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(p->handle.info_hashes());
|
const auto id = TorrentID::fromInfoHash(p->handle.info_hashes());
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(p->handle.info_hash());
|
const auto id = TorrentID::fromInfoHash(p->handle.info_hash());
|
||||||
@@ -4579,7 +4597,7 @@ void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
|
|||||||
|
|
||||||
if (downloadedMetadataIter != m_downloadedMetadata.end())
|
if (downloadedMetadataIter != m_downloadedMetadata.end())
|
||||||
{
|
{
|
||||||
TorrentInfo metadata {p->handle.torrent_file()};
|
const TorrentInfo metadata {p->handle.torrent_file()};
|
||||||
|
|
||||||
m_downloadedMetadata.erase(downloadedMetadataIter);
|
m_downloadedMetadata.erase(downloadedMetadataIter);
|
||||||
--m_extraLimit;
|
--m_extraLimit;
|
||||||
@@ -4772,7 +4790,7 @@ void Session::handleSessionStatsAlert(const lt::session_stats_alert *p)
|
|||||||
m_cacheStatus.totalUsedBuffers = stats[m_metricIndices.disk.diskBlocksInUse];
|
m_cacheStatus.totalUsedBuffers = stats[m_metricIndices.disk.diskBlocksInUse];
|
||||||
m_cacheStatus.jobQueueLength = stats[m_metricIndices.disk.queuedDiskJobs];
|
m_cacheStatus.jobQueueLength = stats[m_metricIndices.disk.queuedDiskJobs];
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
const int64_t numBlocksRead = stats[m_metricIndices.disk.numBlocksRead];
|
const int64_t numBlocksRead = stats[m_metricIndices.disk.numBlocksRead];
|
||||||
const int64_t numBlocksCacheHits = stats[m_metricIndices.disk.numBlocksCacheHits];
|
const int64_t numBlocksCacheHits = stats[m_metricIndices.disk.numBlocksCacheHits];
|
||||||
m_cacheStatus.readRatio = static_cast<qreal>(numBlocksCacheHits) / std::max<int64_t>((numBlocksCacheHits + numBlocksRead), 1);
|
m_cacheStatus.readRatio = static_cast<qreal>(numBlocksCacheHits) / std::max<int64_t>((numBlocksCacheHits + numBlocksRead), 1);
|
||||||
@@ -4807,7 +4825,7 @@ void Session::handleStorageMovedAlert(const lt::storage_moved_alert *p)
|
|||||||
const QString newPath {p->storage_path()};
|
const QString newPath {p->storage_path()};
|
||||||
Q_ASSERT(newPath == currentJob.path);
|
Q_ASSERT(newPath == currentJob.path);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hashes());
|
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hashes());
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hash());
|
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hash());
|
||||||
@@ -4827,7 +4845,7 @@ void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert
|
|||||||
const MoveStorageJob ¤tJob = m_moveStorageQueue.first();
|
const MoveStorageJob ¤tJob = m_moveStorageQueue.first();
|
||||||
Q_ASSERT(currentJob.torrentHandle == p->handle);
|
Q_ASSERT(currentJob.torrentHandle == p->handle);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hashes());
|
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hashes());
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hash());
|
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hash());
|
||||||
@@ -4850,7 +4868,7 @@ void Session::handleStateUpdateAlert(const lt::state_update_alert *p)
|
|||||||
|
|
||||||
for (const lt::torrent_status &status : p->status)
|
for (const lt::torrent_status &status : p->status)
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const auto id = TorrentID::fromInfoHash(status.info_hashes);
|
const auto id = TorrentID::fromInfoHash(status.info_hashes);
|
||||||
#else
|
#else
|
||||||
const auto id = TorrentID::fromInfoHash(status.info_hash);
|
const auto id = TorrentID::fromInfoHash(status.info_hash);
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
#include <libtorrent/add_torrent_params.hpp>
|
#include <libtorrent/add_torrent_params.hpp>
|
||||||
#include <libtorrent/fwd.hpp>
|
#include <libtorrent/fwd.hpp>
|
||||||
#include <libtorrent/torrent_handle.hpp>
|
#include <libtorrent/torrent_handle.hpp>
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
@@ -82,12 +81,6 @@ enum DeleteOption
|
|||||||
DeleteTorrentAndFiles
|
DeleteTorrentAndFiles
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TorrentExportFolder
|
|
||||||
{
|
|
||||||
Regular,
|
|
||||||
Finished
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Net
|
namespace Net
|
||||||
{
|
{
|
||||||
struct DownloadResult;
|
struct DownloadResult;
|
||||||
@@ -197,7 +190,7 @@ namespace BitTorrent
|
|||||||
{
|
{
|
||||||
int diskBlocksInUse = -1;
|
int diskBlocksInUse = -1;
|
||||||
int numBlocksRead = -1;
|
int numBlocksRead = -1;
|
||||||
#if (LIBTORRENT_VERSION_NUM < 20000)
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
int numBlocksCacheHits = -1;
|
int numBlocksCacheHits = -1;
|
||||||
#endif
|
#endif
|
||||||
int writeJobs = -1;
|
int writeJobs = -1;
|
||||||
@@ -211,7 +204,7 @@ namespace BitTorrent
|
|||||||
class Session : public QObject
|
class Session : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Session)
|
Q_DISABLE_COPY_MOVE(Session)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initInstance();
|
static void initInstance();
|
||||||
@@ -312,8 +305,6 @@ namespace BitTorrent
|
|||||||
void setSaveResumeDataInterval(int value);
|
void setSaveResumeDataInterval(int value);
|
||||||
int port() const;
|
int port() const;
|
||||||
void setPort(int port);
|
void setPort(int port);
|
||||||
bool useRandomPort() const;
|
|
||||||
void setUseRandomPort(bool value);
|
|
||||||
QString networkInterface() const;
|
QString networkInterface() const;
|
||||||
void setNetworkInterface(const QString &iface);
|
void setNetworkInterface(const QString &iface);
|
||||||
QString networkInterfaceName() const;
|
QString networkInterfaceName() const;
|
||||||
@@ -435,6 +426,8 @@ namespace BitTorrent
|
|||||||
void setMultiConnectionsPerIpEnabled(bool enabled);
|
void setMultiConnectionsPerIpEnabled(bool enabled);
|
||||||
bool validateHTTPSTrackerCertificate() const;
|
bool validateHTTPSTrackerCertificate() const;
|
||||||
void setValidateHTTPSTrackerCertificate(bool enabled);
|
void setValidateHTTPSTrackerCertificate(bool enabled);
|
||||||
|
bool isSSRFMitigationEnabled() const;
|
||||||
|
void setSSRFMitigationEnabled(bool enabled);
|
||||||
bool blockPeersOnPrivilegedPorts() const;
|
bool blockPeersOnPrivilegedPorts() const;
|
||||||
void setBlockPeersOnPrivilegedPorts(bool enabled);
|
void setBlockPeersOnPrivilegedPorts(bool enabled);
|
||||||
bool isTrackerFilteringEnabled() const;
|
bool isTrackerFilteringEnabled() const;
|
||||||
@@ -613,7 +606,7 @@ namespace BitTorrent
|
|||||||
bool addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source, const AddTorrentParams &addTorrentParams);
|
bool addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source, const AddTorrentParams &addTorrentParams);
|
||||||
|
|
||||||
void updateSeedingLimitTimer();
|
void updateSeedingLimitTimer();
|
||||||
void exportTorrentFile(const Torrent *torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
void exportTorrentFile(const TorrentInfo &torrentInfo, const QString &folderPath, const QString &baseName);
|
||||||
|
|
||||||
void handleAlert(const lt::alert *a);
|
void handleAlert(const lt::alert *a);
|
||||||
void dispatchTorrentAlert(const lt::alert *a);
|
void dispatchTorrentAlert(const lt::alert *a);
|
||||||
@@ -708,6 +701,7 @@ namespace BitTorrent
|
|||||||
CachedSettingValue<bool> m_IDNSupportEnabled;
|
CachedSettingValue<bool> m_IDNSupportEnabled;
|
||||||
CachedSettingValue<bool> m_multiConnectionsPerIpEnabled;
|
CachedSettingValue<bool> m_multiConnectionsPerIpEnabled;
|
||||||
CachedSettingValue<bool> m_validateHTTPSTrackerCertificate;
|
CachedSettingValue<bool> m_validateHTTPSTrackerCertificate;
|
||||||
|
CachedSettingValue<bool> m_SSRFMitigationEnabled;
|
||||||
CachedSettingValue<bool> m_blockPeersOnPrivilegedPorts;
|
CachedSettingValue<bool> m_blockPeersOnPrivilegedPorts;
|
||||||
CachedSettingValue<bool> m_isAddTrackersEnabled;
|
CachedSettingValue<bool> m_isAddTrackersEnabled;
|
||||||
CachedSettingValue<QString> m_additionalTrackers;
|
CachedSettingValue<QString> m_additionalTrackers;
|
||||||
@@ -728,7 +722,6 @@ namespace BitTorrent
|
|||||||
CachedSettingValue<bool> m_isBandwidthSchedulerEnabled;
|
CachedSettingValue<bool> m_isBandwidthSchedulerEnabled;
|
||||||
CachedSettingValue<int> m_saveResumeDataInterval;
|
CachedSettingValue<int> m_saveResumeDataInterval;
|
||||||
CachedSettingValue<int> m_port;
|
CachedSettingValue<int> m_port;
|
||||||
CachedSettingValue<bool> m_useRandomPort;
|
|
||||||
CachedSettingValue<QString> m_networkInterface;
|
CachedSettingValue<QString> m_networkInterface;
|
||||||
CachedSettingValue<QString> m_networkInterfaceName;
|
CachedSettingValue<QString> m_networkInterfaceName;
|
||||||
CachedSettingValue<QString> m_networkInterfaceAddress;
|
CachedSettingValue<QString> m_networkInterfaceAddress;
|
||||||
|
|||||||
@@ -38,34 +38,30 @@
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Sample
|
struct Sample
|
||||||
{
|
{
|
||||||
Sample()
|
constexpr Sample() = default;
|
||||||
: download()
|
|
||||||
, upload()
|
constexpr Sample(const T dl, const T ul)
|
||||||
|
: download {dl}
|
||||||
|
, upload {ul}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Sample(T dl, T ul)
|
constexpr Sample<T> &operator+=(const Sample<T> &other)
|
||||||
: download(dl)
|
|
||||||
, upload(ul)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Sample<T> &operator+=(const Sample<T> &other)
|
|
||||||
{
|
{
|
||||||
download += other.download;
|
download += other.download;
|
||||||
upload += other.upload;
|
upload += other.upload;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sample<T> &operator-=(const Sample<T> &other)
|
constexpr Sample<T> &operator-=(const Sample<T> &other)
|
||||||
{
|
{
|
||||||
download -= other.download;
|
download -= other.download;
|
||||||
upload -= other.upload;
|
upload -= other.upload;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T download;
|
T download {};
|
||||||
T upload;
|
T upload {};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Sample<qlonglong> SpeedSample;
|
typedef Sample<qlonglong> SpeedSample;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace BitTorrent
|
|||||||
class Statistics : public QObject
|
class Statistics : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Statistics)
|
Q_DISABLE_COPY_MOVE(Statistics)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Statistics(BitTorrent::Session *session);
|
explicit Statistics(BitTorrent::Session *session);
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
ForcedDownloading,
|
ForcedDownloading,
|
||||||
Downloading,
|
Downloading,
|
||||||
|
ForcedDownloadingMetadata,
|
||||||
DownloadingMetadata,
|
DownloadingMetadata,
|
||||||
StalledDownloading,
|
StalledDownloading,
|
||||||
|
|
||||||
@@ -192,6 +193,7 @@ namespace BitTorrent
|
|||||||
virtual qreal ratioLimit() const = 0;
|
virtual qreal ratioLimit() const = 0;
|
||||||
virtual int seedingTimeLimit() const = 0;
|
virtual int seedingTimeLimit() const = 0;
|
||||||
|
|
||||||
|
virtual QStringList filePaths() const = 0;
|
||||||
virtual QStringList absoluteFilePaths() const = 0;
|
virtual QStringList absoluteFilePaths() const = 0;
|
||||||
virtual QVector<DownloadPriority> filePriorities() const = 0;
|
virtual QVector<DownloadPriority> filePriorities() const = 0;
|
||||||
|
|
||||||
@@ -213,7 +215,6 @@ namespace BitTorrent
|
|||||||
virtual bool hasMetadata() const = 0;
|
virtual bool hasMetadata() const = 0;
|
||||||
virtual bool hasMissingFiles() const = 0;
|
virtual bool hasMissingFiles() const = 0;
|
||||||
virtual bool hasError() const = 0;
|
virtual bool hasError() const = 0;
|
||||||
virtual bool hasFilteredPieces() const = 0;
|
|
||||||
virtual int queuePosition() const = 0;
|
virtual int queuePosition() const = 0;
|
||||||
virtual QVector<TrackerEntry> trackers() const = 0;
|
virtual QVector<TrackerEntry> trackers() const = 0;
|
||||||
virtual QVector<QUrl> urlSeeds() const = 0;
|
virtual QVector<QUrl> urlSeeds() const = 0;
|
||||||
|
|||||||
@@ -30,13 +30,11 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <libtorrent/bencode.hpp>
|
|
||||||
#include <libtorrent/create_torrent.hpp>
|
#include <libtorrent/create_torrent.hpp>
|
||||||
#include <libtorrent/file_storage.hpp>
|
#include <libtorrent/file_storage.hpp>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
|
||||||
@@ -46,7 +44,7 @@
|
|||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/io.h"
|
#include "base/utils/io.h"
|
||||||
#include "base/version.h"
|
#include "base/version.h"
|
||||||
#include "ltunderlyingtype.h"
|
#include "lttypecast.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -57,7 +55,7 @@ namespace
|
|||||||
return !Utils::Fs::fileName(QString::fromStdString(f)).startsWith('.');
|
return !Utils::Fs::fileName(QString::fromStdString(f)).startsWith('.');
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
lt::create_flags_t toNativeTorrentFormatFlag(const BitTorrent::TorrentFormat torrentFormat)
|
lt::create_flags_t toNativeTorrentFormatFlag(const BitTorrent::TorrentFormat torrentFormat)
|
||||||
{
|
{
|
||||||
switch (torrentFormat)
|
switch (torrentFormat)
|
||||||
@@ -159,7 +157,7 @@ void TorrentCreatorThread::run()
|
|||||||
|
|
||||||
checkInterruptionRequested();
|
checkInterruptionRequested();
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
lt::create_torrent newTorrent {fs, m_params.pieceSize, toNativeTorrentFormatFlag(m_params.torrentFormat)};
|
lt::create_torrent newTorrent {fs, m_params.pieceSize, toNativeTorrentFormatFlag(m_params.torrentFormat)};
|
||||||
#else
|
#else
|
||||||
lt::create_torrent newTorrent(fs, m_params.pieceSize, m_params.paddedFileSizeLimit
|
lt::create_torrent newTorrent(fs, m_params.pieceSize, m_params.paddedFileSizeLimit
|
||||||
@@ -188,7 +186,7 @@ void TorrentCreatorThread::run()
|
|||||||
, [this, &newTorrent](const lt::piece_index_t n)
|
, [this, &newTorrent](const lt::piece_index_t n)
|
||||||
{
|
{
|
||||||
checkInterruptionRequested();
|
checkInterruptionRequested();
|
||||||
sendProgressSignal(static_cast<LTUnderlyingType<lt::piece_index_t>>(n), newTorrent.num_pieces());
|
sendProgressSignal(LT::toUnderlyingType(n), newTorrent.num_pieces());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set qBittorrent as creator and add user comment to
|
// Set qBittorrent as creator and add user comment to
|
||||||
@@ -209,16 +207,9 @@ void TorrentCreatorThread::run()
|
|||||||
checkInterruptionRequested();
|
checkInterruptionRequested();
|
||||||
|
|
||||||
// create the torrent
|
// create the torrent
|
||||||
QFile outfile {m_params.savePath};
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(m_params.savePath, entry);
|
||||||
if (!outfile.open(QIODevice::WriteOnly))
|
if (!result)
|
||||||
throw RuntimeError(outfile.errorString());
|
throw RuntimeError(result.error());
|
||||||
|
|
||||||
checkInterruptionRequested();
|
|
||||||
|
|
||||||
lt::bencode(Utils::IO::FileDeviceOutputIterator {outfile}, entry);
|
|
||||||
if (outfile.error() != QFileDevice::NoError)
|
|
||||||
throw RuntimeError(outfile.errorString());
|
|
||||||
outfile.close();
|
|
||||||
|
|
||||||
emit updateProgress(100);
|
emit updateProgress(100);
|
||||||
emit creationSuccess(m_params.savePath, parentPath);
|
emit creationSuccess(m_params.savePath, parentPath);
|
||||||
@@ -233,7 +224,7 @@ void TorrentCreatorThread::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const TorrentFormat torrentFormat)
|
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const TorrentFormat torrentFormat)
|
||||||
#else
|
#else
|
||||||
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized, const int paddedFileSizeLimit)
|
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized, const int paddedFileSizeLimit)
|
||||||
@@ -245,7 +236,7 @@ int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const i
|
|||||||
lt::file_storage fs;
|
lt::file_storage fs;
|
||||||
lt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
lt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
return lt::create_torrent {fs, pieceSize, toNativeTorrentFormatFlag(torrentFormat)}.num_pieces();
|
return lt::create_torrent {fs, pieceSize, toNativeTorrentFormatFlag(torrentFormat)}.num_pieces();
|
||||||
#else
|
#else
|
||||||
return lt::create_torrent(fs, pieceSize, paddedFileSizeLimit
|
return lt::create_torrent(fs, pieceSize, paddedFileSizeLimit
|
||||||
|
|||||||
@@ -28,14 +28,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
enum class TorrentFormat
|
enum class TorrentFormat
|
||||||
{
|
{
|
||||||
V1,
|
V1,
|
||||||
@@ -47,7 +45,7 @@ namespace BitTorrent
|
|||||||
struct TorrentCreatorParams
|
struct TorrentCreatorParams
|
||||||
{
|
{
|
||||||
bool isPrivate;
|
bool isPrivate;
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
TorrentFormat torrentFormat;
|
TorrentFormat torrentFormat;
|
||||||
#else
|
#else
|
||||||
bool isAlignmentOptimized;
|
bool isAlignmentOptimized;
|
||||||
@@ -73,7 +71,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
void create(const TorrentCreatorParams ¶ms);
|
void create(const TorrentCreatorParams ¶ms);
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
static int calculateTotalPieces(const QString &inputPath, const int pieceSize, const TorrentFormat torrentFormat);
|
static int calculateTotalPieces(const QString &inputPath, const int pieceSize, const TorrentFormat torrentFormat);
|
||||||
#else
|
#else
|
||||||
static int calculateTotalPieces(const QString &inputPath
|
static int calculateTotalPieces(const QString &inputPath
|
||||||
|
|||||||
@@ -43,9 +43,8 @@
|
|||||||
#include <libtorrent/session.hpp>
|
#include <libtorrent/session.hpp>
|
||||||
#include <libtorrent/storage_defs.hpp>
|
#include <libtorrent/storage_defs.hpp>
|
||||||
#include <libtorrent/time.hpp>
|
#include <libtorrent/time.hpp>
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
#include <libtorrent/info_hash.hpp>
|
#include <libtorrent/info_hash.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -65,7 +64,7 @@
|
|||||||
#include "downloadpriority.h"
|
#include "downloadpriority.h"
|
||||||
#include "loadtorrentparams.h"
|
#include "loadtorrentparams.h"
|
||||||
#include "ltqhash.h"
|
#include "ltqhash.h"
|
||||||
#include "ltunderlyingtype.h"
|
#include "lttypecast.h"
|
||||||
#include "peeraddress.h"
|
#include "peeraddress.h"
|
||||||
#include "peerinfo.h"
|
#include "peerinfo.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
@@ -75,20 +74,6 @@ using namespace BitTorrent;
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::vector<lt::download_priority_t> toLTDownloadPriorities(const QVector<DownloadPriority> &priorities)
|
|
||||||
{
|
|
||||||
std::vector<lt::download_priority_t> out;
|
|
||||||
out.reserve(priorities.size());
|
|
||||||
|
|
||||||
std::transform(priorities.cbegin(), priorities.cend()
|
|
||||||
, std::back_inserter(out), [](const DownloadPriority priority)
|
|
||||||
{
|
|
||||||
return static_cast<lt::download_priority_t>(
|
|
||||||
static_cast<LTUnderlyingType<lt::download_priority_t>>(priority));
|
|
||||||
});
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lt::announce_entry makeNativeAnnouncerEntry(const QString &url, const int tier)
|
lt::announce_entry makeNativeAnnouncerEntry(const QString &url, const int tier)
|
||||||
{
|
{
|
||||||
lt::announce_entry entry {url.toStdString()};
|
lt::announce_entry entry {url.toStdString()};
|
||||||
@@ -96,7 +81,7 @@ namespace
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
TrackerEntry fromNativeAnnouncerEntry(const lt::announce_entry &nativeEntry
|
TrackerEntry fromNativeAnnouncerEntry(const lt::announce_entry &nativeEntry
|
||||||
, const lt::info_hash_t &hashes, const QMap<lt::tcp::endpoint, int> &trackerPeerCounts)
|
, const lt::info_hash_t &hashes, const QMap<lt::tcp::endpoint, int> &trackerPeerCounts)
|
||||||
#else
|
#else
|
||||||
@@ -111,8 +96,8 @@ namespace
|
|||||||
int numNotWorking = 0;
|
int numNotWorking = 0;
|
||||||
QString firstTrackerMessage;
|
QString firstTrackerMessage;
|
||||||
QString firstErrorMessage;
|
QString firstErrorMessage;
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const size_t numEndpoints = nativeEntry.endpoints.size() * ((hashes.has_v1() && hashes.has_v2()) ? 2 : 1);
|
const auto numEndpoints = static_cast<qsizetype>(nativeEntry.endpoints.size() * ((hashes.has_v1() && hashes.has_v2()) ? 2 : 1));
|
||||||
trackerEntry.endpoints.reserve(static_cast<decltype(trackerEntry.endpoints)::size_type>(numEndpoints));
|
trackerEntry.endpoints.reserve(static_cast<decltype(trackerEntry.endpoints)::size_type>(numEndpoints));
|
||||||
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
|
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
|
||||||
{
|
{
|
||||||
@@ -167,8 +152,8 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
const int numEndpoints = nativeEntry.endpoints.size();
|
const auto numEndpoints = static_cast<qsizetype>(nativeEntry.endpoints.size());
|
||||||
trackerEntry.endpoints.reserve(numEndpoints);
|
trackerEntry.endpoints.reserve(static_cast<decltype(trackerEntry.endpoints)::size_type>(numEndpoints));
|
||||||
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
|
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
|
||||||
{
|
{
|
||||||
TrackerEntry::EndpointStats trackerEndpoint;
|
TrackerEntry::EndpointStats trackerEndpoint;
|
||||||
@@ -265,7 +250,7 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
|||||||
, m_session(session)
|
, m_session(session)
|
||||||
, m_nativeSession(nativeSession)
|
, m_nativeSession(nativeSession)
|
||||||
, m_nativeHandle(nativeHandle)
|
, m_nativeHandle(nativeHandle)
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
, m_infoHash(m_nativeHandle.info_hashes())
|
, m_infoHash(m_nativeHandle.info_hashes())
|
||||||
#else
|
#else
|
||||||
, m_infoHash(m_nativeHandle.info_hash())
|
, m_infoHash(m_nativeHandle.info_hash())
|
||||||
@@ -478,7 +463,7 @@ QVector<TrackerEntry> TorrentImpl::trackers() const
|
|||||||
for (const lt::announce_entry &tracker : nativeTrackers)
|
for (const lt::announce_entry &tracker : nativeTrackers)
|
||||||
{
|
{
|
||||||
const QString trackerURL = QString::fromStdString(tracker.url);
|
const QString trackerURL = QString::fromStdString(tracker.url);
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
entries << fromNativeAnnouncerEntry(tracker, m_nativeHandle.info_hashes(), m_trackerPeerCounts[trackerURL]);
|
entries << fromNativeAnnouncerEntry(tracker, m_nativeHandle.info_hashes(), m_trackerPeerCounts[trackerURL]);
|
||||||
#else
|
#else
|
||||||
entries << fromNativeAnnouncerEntry(tracker, m_trackerPeerCounts[trackerURL]);
|
entries << fromNativeAnnouncerEntry(tracker, m_trackerPeerCounts[trackerURL]);
|
||||||
@@ -763,30 +748,30 @@ int TorrentImpl::seedingTimeLimit() const
|
|||||||
return m_seedingTimeLimit;
|
return m_seedingTimeLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TorrentImpl::filePath(int index) const
|
QString TorrentImpl::filePath(const int index) const
|
||||||
{
|
{
|
||||||
return m_torrentInfo.filePath(index);
|
return m_torrentInfo.filePath(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TorrentImpl::fileName(int index) const
|
qlonglong TorrentImpl::fileSize(const int index) const
|
||||||
{
|
|
||||||
if (!hasMetadata()) return {};
|
|
||||||
return Utils::Fs::fileName(filePath(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
qlonglong TorrentImpl::fileSize(int index) const
|
|
||||||
{
|
{
|
||||||
return m_torrentInfo.fileSize(index);
|
return m_torrentInfo.fileSize(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList TorrentImpl::filePaths() const
|
||||||
|
{
|
||||||
|
return m_torrentInfo.filePaths();
|
||||||
|
}
|
||||||
|
|
||||||
// Return a list of absolute paths corresponding
|
// Return a list of absolute paths corresponding
|
||||||
// to all files in a torrent
|
// to all files in a torrent
|
||||||
QStringList TorrentImpl::absoluteFilePaths() const
|
QStringList TorrentImpl::absoluteFilePaths() const
|
||||||
{
|
{
|
||||||
if (!hasMetadata()) return {};
|
if (!hasMetadata()) return {};
|
||||||
|
|
||||||
const QDir saveDir(savePath(true));
|
const QDir saveDir {savePath(true)};
|
||||||
QStringList res;
|
QStringList res;
|
||||||
|
res.reserve(filesCount());
|
||||||
for (int i = 0; i < filesCount(); ++i)
|
for (int i = 0; i < filesCount(); ++i)
|
||||||
res << Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i)));
|
res << Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i)));
|
||||||
return res;
|
return res;
|
||||||
@@ -794,13 +779,19 @@ QStringList TorrentImpl::absoluteFilePaths() const
|
|||||||
|
|
||||||
QVector<DownloadPriority> TorrentImpl::filePriorities() const
|
QVector<DownloadPriority> TorrentImpl::filePriorities() const
|
||||||
{
|
{
|
||||||
|
if (!hasMetadata())
|
||||||
|
return {};
|
||||||
|
|
||||||
const std::vector<lt::download_priority_t> fp = m_nativeHandle.get_file_priorities();
|
const std::vector<lt::download_priority_t> fp = m_nativeHandle.get_file_priorities();
|
||||||
|
|
||||||
QVector<DownloadPriority> ret;
|
QVector<DownloadPriority> ret;
|
||||||
std::transform(fp.cbegin(), fp.cend(), std::back_inserter(ret), [](lt::download_priority_t priority)
|
ret.reserve(filesCount());
|
||||||
|
for (const lt::file_index_t nativeIndex : asConst(m_torrentInfo.nativeIndexes()))
|
||||||
{
|
{
|
||||||
return static_cast<DownloadPriority>(static_cast<LTUnderlyingType<lt::download_priority_t>>(priority));
|
const auto priority = LT::fromNative(fp[LT::toUnderlyingType(nativeIndex)]);
|
||||||
});
|
ret.append(priority);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -832,6 +823,7 @@ bool TorrentImpl::isDownloading() const
|
|||||||
{
|
{
|
||||||
return m_state == TorrentState::Downloading
|
return m_state == TorrentState::Downloading
|
||||||
|| m_state == TorrentState::DownloadingMetadata
|
|| m_state == TorrentState::DownloadingMetadata
|
||||||
|
|| m_state == TorrentState::ForcedDownloadingMetadata
|
||||||
|| m_state == TorrentState::StalledDownloading
|
|| m_state == TorrentState::StalledDownloading
|
||||||
|| m_state == TorrentState::CheckingDownloading
|
|| m_state == TorrentState::CheckingDownloading
|
||||||
|| m_state == TorrentState::PausedDownloading
|
|| m_state == TorrentState::PausedDownloading
|
||||||
@@ -864,6 +856,7 @@ bool TorrentImpl::isActive() const
|
|||||||
return (uploadPayloadRate() > 0);
|
return (uploadPayloadRate() > 0);
|
||||||
|
|
||||||
return m_state == TorrentState::DownloadingMetadata
|
return m_state == TorrentState::DownloadingMetadata
|
||||||
|
|| m_state == TorrentState::ForcedDownloadingMetadata
|
||||||
|| m_state == TorrentState::Downloading
|
|| m_state == TorrentState::Downloading
|
||||||
|| m_state == TorrentState::ForcedDownloading
|
|| m_state == TorrentState::ForcedDownloading
|
||||||
|| m_state == TorrentState::Uploading
|
|| m_state == TorrentState::Uploading
|
||||||
@@ -933,7 +926,7 @@ void TorrentImpl::updateState()
|
|||||||
else if (m_session->isQueueingSystemEnabled() && isQueued())
|
else if (m_session->isQueueingSystemEnabled() && isQueued())
|
||||||
m_state = TorrentState::QueuedDownloading;
|
m_state = TorrentState::QueuedDownloading;
|
||||||
else
|
else
|
||||||
m_state = TorrentState::DownloadingMetadata;
|
m_state = isForced() ? TorrentState::ForcedDownloadingMetadata : TorrentState::DownloadingMetadata;
|
||||||
}
|
}
|
||||||
else if ((m_nativeStatus.state == lt::torrent_status::checking_files)
|
else if ((m_nativeStatus.state == lt::torrent_status::checking_files)
|
||||||
&& (!isPaused() || (m_nativeStatus.flags & lt::torrent_flags::auto_managed)
|
&& (!isPaused() || (m_nativeStatus.flags & lt::torrent_flags::auto_managed)
|
||||||
@@ -985,15 +978,6 @@ bool TorrentImpl::hasError() const
|
|||||||
return (m_nativeStatus.errc || (m_nativeStatus.flags & lt::torrent_flags::upload_mode));
|
return (m_nativeStatus.errc || (m_nativeStatus.flags & lt::torrent_flags::upload_mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentImpl::hasFilteredPieces() const
|
|
||||||
{
|
|
||||||
const std::vector<lt::download_priority_t> pp = m_nativeHandle.get_piece_priorities();
|
|
||||||
return std::any_of(pp.cbegin(), pp.cend(), [](const lt::download_priority_t priority)
|
|
||||||
{
|
|
||||||
return (priority == lt::download_priority_t {0});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int TorrentImpl::queuePosition() const
|
int TorrentImpl::queuePosition() const
|
||||||
{
|
{
|
||||||
return static_cast<int>(m_nativeStatus.queue_position);
|
return static_cast<int>(m_nativeStatus.queue_position);
|
||||||
@@ -1090,16 +1074,18 @@ QVector<qreal> TorrentImpl::filesProgress() const
|
|||||||
std::vector<int64_t> fp;
|
std::vector<int64_t> fp;
|
||||||
m_nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
|
m_nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
|
||||||
|
|
||||||
const int count = static_cast<int>(fp.size());
|
const int count = filesCount();
|
||||||
|
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||||
QVector<qreal> result;
|
QVector<qreal> result;
|
||||||
result.reserve(count);
|
result.reserve(count);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
|
const int64_t progress = fp[LT::toUnderlyingType(nativeIndexes[i])];
|
||||||
const qlonglong size = fileSize(i);
|
const qlonglong size = fileSize(i);
|
||||||
if ((size <= 0) || (fp[i] == size))
|
if ((size <= 0) || (progress == size))
|
||||||
result << 1;
|
result << 1;
|
||||||
else
|
else
|
||||||
result << (fp[i] / static_cast<qreal>(size));
|
result << (progress / static_cast<qreal>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -1250,7 +1236,7 @@ QBitArray TorrentImpl::downloadingPieces() const
|
|||||||
m_nativeHandle.get_download_queue(queue);
|
m_nativeHandle.get_download_queue(queue);
|
||||||
|
|
||||||
for (const lt::partial_piece_info &info : queue)
|
for (const lt::partial_piece_info &info : queue)
|
||||||
result.setBit(static_cast<LTUnderlyingType<lt::piece_index_t>>(info.piece_index));
|
result.setBit(LT::toUnderlyingType(info.piece_index));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1404,7 +1390,7 @@ void TorrentImpl::move_impl(QString path, const MoveStorageMode mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::forceReannounce(int index)
|
void TorrentImpl::forceReannounce(const int index)
|
||||||
{
|
{
|
||||||
m_nativeHandle.force_reannounce(0, index);
|
m_nativeHandle.force_reannounce(0, index);
|
||||||
}
|
}
|
||||||
@@ -1467,28 +1453,29 @@ void TorrentImpl::applyFirstLastPiecePriority(const bool enabled, const QVector<
|
|||||||
|
|
||||||
// Download first and last pieces first for every file in the torrent
|
// Download first and last pieces first for every file in the torrent
|
||||||
|
|
||||||
const std::vector<lt::download_priority_t> filePriorities = !updatedFilePrio.isEmpty() ? toLTDownloadPriorities(updatedFilePrio)
|
const QVector<DownloadPriority> filePriorities =
|
||||||
: nativeHandle().get_file_priorities();
|
!updatedFilePrio.isEmpty() ? updatedFilePrio : this->filePriorities();
|
||||||
std::vector<lt::download_priority_t> piecePriorities = nativeHandle().get_piece_priorities();
|
std::vector<lt::download_priority_t> piecePriorities = nativeHandle().get_piece_priorities();
|
||||||
|
|
||||||
// Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it
|
// Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it
|
||||||
// we might get the old/wrong values, so we rely on `updatedFilePrio` in this case.
|
// we might get the old/wrong values, so we rely on `updatedFilePrio` in this case.
|
||||||
for (int index = 0; index < static_cast<int>(filePriorities.size()); ++index)
|
for (int index = 0; index < filePriorities.size(); ++index)
|
||||||
{
|
{
|
||||||
const lt::download_priority_t filePrio = filePriorities[index];
|
const DownloadPriority filePrio = filePriorities[index];
|
||||||
if (filePrio <= lt::download_priority_t {0})
|
if (filePrio <= DownloadPriority::Ignored)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Determine the priority to set
|
// Determine the priority to set
|
||||||
const lt::download_priority_t newPrio = enabled ? lt::download_priority_t {7} : filePrio;
|
const DownloadPriority newPrio = enabled ? DownloadPriority::Maximum : filePrio;
|
||||||
|
const auto piecePrio = static_cast<lt::download_priority_t>(static_cast<int>(newPrio));
|
||||||
const TorrentInfo::PieceRange extremities = info().filePieces(index);
|
const TorrentInfo::PieceRange extremities = info().filePieces(index);
|
||||||
|
|
||||||
// worst case: AVI index = 1% of total file size (at the end of the file)
|
// worst case: AVI index = 1% of total file size (at the end of the file)
|
||||||
const int nNumPieces = std::ceil(fileSize(index) * 0.01 / pieceLength());
|
const int nNumPieces = std::ceil(fileSize(index) * 0.01 / pieceLength());
|
||||||
for (int i = 0; i < nNumPieces; ++i)
|
for (int i = 0; i < nNumPieces; ++i)
|
||||||
{
|
{
|
||||||
piecePriorities[extremities.first() + i] = newPrio;
|
piecePriorities[extremities.first() + i] = piecePrio;
|
||||||
piecePriorities[extremities.last() - i] = newPrio;
|
piecePriorities[extremities.last() - i] = piecePrio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1504,10 +1491,16 @@ void TorrentImpl::endReceivedMetadataHandling(const QString &savePath, const QSt
|
|||||||
{
|
{
|
||||||
lt::add_torrent_params &p = m_ltAddTorrentParams;
|
lt::add_torrent_params &p = m_ltAddTorrentParams;
|
||||||
|
|
||||||
p.ti = std::const_pointer_cast<lt::torrent_info>(m_nativeHandle.torrent_file());
|
const TorrentInfo torrentInfo {m_nativeHandle.torrent_file()};
|
||||||
|
const auto nativeIndexes = torrentInfo.nativeIndexes();
|
||||||
for (int i = 0; i < fileNames.size(); ++i)
|
for (int i = 0; i < fileNames.size(); ++i)
|
||||||
p.renamed_files[lt::file_index_t {i}] = fileNames[i].toStdString();
|
p.renamed_files[nativeIndexes[i]] = fileNames[i].toStdString();
|
||||||
p.save_path = Utils::Fs::toNativePath(savePath).toStdString();
|
p.save_path = Utils::Fs::toNativePath(savePath).toStdString();
|
||||||
|
p.ti = torrentInfo.nativeInfo();
|
||||||
|
|
||||||
|
const int internalFilesCount = p.ti->files().num_files(); // including .pad files
|
||||||
|
// Use qBittorrent default priority rather than libtorrent's (4)
|
||||||
|
p.file_priorities = std::vector(internalFilesCount, LT::toNative(DownloadPriority::Normal));
|
||||||
|
|
||||||
reload();
|
reload();
|
||||||
|
|
||||||
@@ -1622,10 +1615,12 @@ void TorrentImpl::moveStorage(const QString &newPath, const MoveStorageMode mode
|
|||||||
|
|
||||||
void TorrentImpl::renameFile(const int index, const QString &path)
|
void TorrentImpl::renameFile(const int index, const QString &path)
|
||||||
{
|
{
|
||||||
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
const QString oldPath = filePath(index);
|
const QString oldPath = filePath(index);
|
||||||
m_oldPath[lt::file_index_t {index}].push_back(oldPath);
|
m_oldPath[index].push_back(oldPath);
|
||||||
|
#endif
|
||||||
++m_renameCount;
|
++m_renameCount;
|
||||||
m_nativeHandle.rename_file(lt::file_index_t {index}, Utils::Fs::toNativePath(path).toStdString());
|
m_nativeHandle.rename_file(m_torrentInfo.nativeIndexes()[index], Utils::Fs::toNativePath(path).toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
|
void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
|
||||||
@@ -1809,8 +1804,6 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms)
|
|||||||
m_ltAddTorrentParams = params;
|
m_ltAddTorrentParams = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ltAddTorrentParams.added_time = addedTime().toSecsSinceEpoch();
|
|
||||||
|
|
||||||
// We shouldn't save upload_mode flag to allow torrent operate normally on next run
|
// We shouldn't save upload_mode flag to allow torrent operate normally on next run
|
||||||
m_ltAddTorrentParams.flags &= ~lt::torrent_flags::upload_mode;
|
m_ltAddTorrentParams.flags &= ~lt::torrent_flags::upload_mode;
|
||||||
|
|
||||||
@@ -1856,18 +1849,24 @@ void TorrentImpl::handleFastResumeRejectedAlert(const lt::fastresume_rejected_al
|
|||||||
|
|
||||||
void TorrentImpl::handleFileRenamedAlert(const lt::file_renamed_alert *p)
|
void TorrentImpl::handleFileRenamedAlert(const lt::file_renamed_alert *p)
|
||||||
{
|
{
|
||||||
|
const int fileIndex = m_torrentInfo.nativeIndexes().indexOf(p->index);
|
||||||
|
Q_ASSERT(fileIndex >= 0);
|
||||||
|
|
||||||
// Remove empty leftover folders
|
// Remove empty leftover folders
|
||||||
// For example renaming "a/b/c" to "d/b/c", then folders "a/b" and "a" will
|
// For example renaming "a/b/c" to "d/b/c", then folders "a/b" and "a" will
|
||||||
// be removed if they are empty
|
// be removed if they are empty
|
||||||
const QString oldFilePath = m_oldPath[p->index].takeFirst();
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
|
const QString oldFilePath = m_oldPath[fileIndex].takeFirst();
|
||||||
|
if (m_oldPath[fileIndex].isEmpty())
|
||||||
|
m_oldPath.remove(fileIndex);
|
||||||
|
#else
|
||||||
|
const QString oldFilePath = Utils::Fs::toUniformPath(p->old_name());
|
||||||
|
#endif
|
||||||
const QString newFilePath = Utils::Fs::toUniformPath(p->new_name());
|
const QString newFilePath = Utils::Fs::toUniformPath(p->new_name());
|
||||||
|
|
||||||
if (m_oldPath[p->index].isEmpty())
|
QList<QStringView> oldPathParts = QStringView(oldFilePath).split('/', Qt::SkipEmptyParts);
|
||||||
m_oldPath.remove(p->index);
|
|
||||||
|
|
||||||
QVector<QStringRef> oldPathParts = oldFilePath.splitRef('/', Qt::SkipEmptyParts);
|
|
||||||
oldPathParts.removeLast(); // drop file name part
|
oldPathParts.removeLast(); // drop file name part
|
||||||
QVector<QStringRef> newPathParts = newFilePath.splitRef('/', Qt::SkipEmptyParts);
|
QList<QStringView> newPathParts = QStringView(newFilePath).split('/', Qt::SkipEmptyParts);
|
||||||
newPathParts.removeLast(); // drop file name part
|
newPathParts.removeLast(); // drop file name part
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
@@ -1886,7 +1885,7 @@ void TorrentImpl::handleFileRenamedAlert(const lt::file_renamed_alert *p)
|
|||||||
|
|
||||||
for (int i = (oldPathParts.size() - 1); i >= pathIdx; --i)
|
for (int i = (oldPathParts.size() - 1); i >= pathIdx; --i)
|
||||||
{
|
{
|
||||||
QDir().rmdir(savePath() + Utils::String::join(oldPathParts, QLatin1String("/")));
|
QDir().rmdir(savePath() + Utils::String::join(oldPathParts, QString::fromLatin1("/")));
|
||||||
oldPathParts.removeLast();
|
oldPathParts.removeLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1899,13 +1898,17 @@ void TorrentImpl::handleFileRenamedAlert(const lt::file_renamed_alert *p)
|
|||||||
|
|
||||||
void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert *p)
|
void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert *p)
|
||||||
{
|
{
|
||||||
LogMsg(tr("File rename failed. Torrent: \"%1\", file: \"%2\", reason: \"%3\"")
|
const int fileIndex = m_torrentInfo.nativeIndexes().indexOf(p->index);
|
||||||
.arg(name(), filePath(static_cast<LTUnderlyingType<lt::file_index_t>>(p->index))
|
Q_ASSERT(fileIndex >= 0);
|
||||||
, QString::fromLocal8Bit(p->error.message().c_str())), Log::WARNING);
|
|
||||||
|
|
||||||
m_oldPath[p->index].removeFirst();
|
LogMsg(tr("File rename failed. Torrent: \"%1\", file: \"%2\", reason: \"%3\"")
|
||||||
if (m_oldPath[p->index].isEmpty())
|
.arg(name(), filePath(fileIndex), QString::fromLocal8Bit(p->error.message().c_str())), Log::WARNING);
|
||||||
m_oldPath.remove(p->index);
|
|
||||||
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
|
m_oldPath[fileIndex].removeFirst();
|
||||||
|
if (m_oldPath[fileIndex].isEmpty())
|
||||||
|
m_oldPath.remove(fileIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
--m_renameCount;
|
--m_renameCount;
|
||||||
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
||||||
@@ -1916,16 +1919,19 @@ void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert
|
|||||||
|
|
||||||
void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p)
|
void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p)
|
||||||
{
|
{
|
||||||
|
const int fileIndex = m_torrentInfo.nativeIndexes().indexOf(p->index);
|
||||||
|
Q_ASSERT(fileIndex >= 0);
|
||||||
|
|
||||||
qDebug("A file completed download in torrent \"%s\"", qUtf8Printable(name()));
|
qDebug("A file completed download in torrent \"%s\"", qUtf8Printable(name()));
|
||||||
if (m_session->isAppendExtensionEnabled())
|
if (m_session->isAppendExtensionEnabled())
|
||||||
{
|
{
|
||||||
QString name = filePath(static_cast<LTUnderlyingType<lt::file_index_t>>(p->index));
|
QString name = filePath(fileIndex);
|
||||||
if (name.endsWith(QB_EXT))
|
if (name.endsWith(QB_EXT))
|
||||||
{
|
{
|
||||||
const QString oldName = name;
|
const QString oldName = name;
|
||||||
name.chop(QB_EXT.size());
|
name.chop(QB_EXT.size());
|
||||||
qDebug("Renaming %s to %s", qUtf8Printable(oldName), qUtf8Printable(name));
|
qDebug("Renaming %s to %s", qUtf8Printable(oldName), qUtf8Printable(name));
|
||||||
renameFile(static_cast<LTUnderlyingType<lt::file_index_t>>(p->index), name);
|
renameFile(fileIndex, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1935,7 +1941,7 @@ void TorrentImpl::handleFileErrorAlert(const lt::file_error_alert *p)
|
|||||||
m_lastFileError = {p->error, p->op};
|
m_lastFileError = {p->error, p->op};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20003)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
void TorrentImpl::handleFilePrioAlert(const lt::file_prio_alert *)
|
void TorrentImpl::handleFilePrioAlert(const lt::file_prio_alert *)
|
||||||
{
|
{
|
||||||
if (m_nativeHandle.need_save_resume_data())
|
if (m_nativeHandle.need_save_resume_data())
|
||||||
@@ -1980,7 +1986,7 @@ void TorrentImpl::handleAlert(const lt::alert *a)
|
|||||||
{
|
{
|
||||||
switch (a->type())
|
switch (a->type())
|
||||||
{
|
{
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20003)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
case lt::file_prio_alert::alert_type:
|
case lt::file_prio_alert::alert_type:
|
||||||
handleFilePrioAlert(static_cast<const lt::file_prio_alert*>(a));
|
handleFilePrioAlert(static_cast<const lt::file_prio_alert*>(a));
|
||||||
break;
|
break;
|
||||||
@@ -2258,7 +2264,8 @@ QString TorrentImpl::createMagnetURI() const
|
|||||||
void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
||||||
{
|
{
|
||||||
if (!hasMetadata()) return;
|
if (!hasMetadata()) return;
|
||||||
if (priorities.size() != filesCount()) return;
|
|
||||||
|
Q_ASSERT(priorities.size() == filesCount());
|
||||||
|
|
||||||
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
||||||
// 'torrent_finished_alert' and eg show tray notifications
|
// 'torrent_finished_alert' and eg show tray notifications
|
||||||
@@ -2275,8 +2282,14 @@ void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int internalFilesCount = m_torrentInfo.nativeInfo()->files().num_files(); // including .pad files
|
||||||
|
auto nativePriorities = std::vector<lt::download_priority_t>(internalFilesCount, LT::toNative(DownloadPriority::Normal));
|
||||||
|
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||||
|
for (int i = 0; i < priorities.size(); ++i)
|
||||||
|
nativePriorities[LT::toUnderlyingType(nativeIndexes[i])] = LT::toNative(priorities[i]);
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Changing files priorities...";
|
qDebug() << Q_FUNC_INFO << "Changing files priorities...";
|
||||||
m_nativeHandle.prioritize_files(toLTDownloadPriorities(priorities));
|
m_nativeHandle.prioritize_files(nativePriorities);
|
||||||
|
|
||||||
// Restore first/last piece first option if necessary
|
// Restore first/last piece first option if necessary
|
||||||
if (m_hasFirstLastPiecePriority)
|
if (m_hasFirstLastPiecePriority)
|
||||||
|
|||||||
@@ -51,16 +51,6 @@
|
|||||||
#include "torrent.h"
|
#include "torrent.h"
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM == 20003)
|
|
||||||
// file_prio_alert is missing to be forward declared in "libtorrent/fwd.hpp"
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
TORRENT_VERSION_NAMESPACE_3
|
|
||||||
struct file_prio_alert;
|
|
||||||
TORRENT_VERSION_NAMESPACE_3_END
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
class Session;
|
class Session;
|
||||||
@@ -86,7 +76,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
class TorrentImpl final : public QObject, public Torrent
|
class TorrentImpl final : public QObject, public Torrent
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY(TorrentImpl)
|
Q_DISABLE_COPY_MOVE(TorrentImpl)
|
||||||
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentImpl)
|
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentImpl)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -136,8 +126,8 @@ namespace BitTorrent
|
|||||||
int seedingTimeLimit() const override;
|
int seedingTimeLimit() const override;
|
||||||
|
|
||||||
QString filePath(int index) const override;
|
QString filePath(int index) const override;
|
||||||
QString fileName(int index) const override;
|
|
||||||
qlonglong fileSize(int index) const override;
|
qlonglong fileSize(int index) const override;
|
||||||
|
QStringList filePaths() const override;
|
||||||
QStringList absoluteFilePaths() const override;
|
QStringList absoluteFilePaths() const override;
|
||||||
QVector<DownloadPriority> filePriorities() const override;
|
QVector<DownloadPriority> filePriorities() const override;
|
||||||
|
|
||||||
@@ -159,7 +149,6 @@ namespace BitTorrent
|
|||||||
bool hasMetadata() const override;
|
bool hasMetadata() const override;
|
||||||
bool hasMissingFiles() const override;
|
bool hasMissingFiles() const override;
|
||||||
bool hasError() const override;
|
bool hasError() const override;
|
||||||
bool hasFilteredPieces() const override;
|
|
||||||
int queuePosition() const override;
|
int queuePosition() const override;
|
||||||
QVector<TrackerEntry> trackers() const override;
|
QVector<TrackerEntry> trackers() const override;
|
||||||
QVector<QUrl> urlSeeds() const override;
|
QVector<QUrl> urlSeeds() const override;
|
||||||
@@ -262,7 +251,7 @@ namespace BitTorrent
|
|||||||
void handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p);
|
void handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p);
|
||||||
void handleFileCompletedAlert(const lt::file_completed_alert *p);
|
void handleFileCompletedAlert(const lt::file_completed_alert *p);
|
||||||
void handleFileErrorAlert(const lt::file_error_alert *p);
|
void handleFileErrorAlert(const lt::file_error_alert *p);
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20003)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
void handleFilePrioAlert(const lt::file_prio_alert *p);
|
void handleFilePrioAlert(const lt::file_prio_alert *p);
|
||||||
#endif
|
#endif
|
||||||
void handleFileRenamedAlert(const lt::file_renamed_alert *p);
|
void handleFileRenamedAlert(const lt::file_renamed_alert *p);
|
||||||
@@ -312,9 +301,11 @@ namespace BitTorrent
|
|||||||
|
|
||||||
MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
|
MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
|
||||||
|
|
||||||
// Until libtorrent provide an "old_name" field in `file_renamed_alert`
|
#ifndef QBT_USES_LIBTORRENT2
|
||||||
// we will rely on this workaround to remove empty leftover folders
|
// Until libtorrent provided an "old_name" field in `file_renamed_alert`
|
||||||
QHash<lt::file_index_t, QVector<QString>> m_oldPath;
|
// we relied on this workaround to remove empty leftover folders
|
||||||
|
QHash<int, QVector<QString>> m_oldPath;
|
||||||
|
#endif
|
||||||
|
|
||||||
QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts;
|
QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts;
|
||||||
FileErrorInfo m_lastFileError;
|
FileErrorInfo m_lastFileError;
|
||||||
|
|||||||
@@ -28,10 +28,8 @@
|
|||||||
|
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
|
|
||||||
#include <libtorrent/bencode.hpp>
|
|
||||||
#include <libtorrent/create_torrent.hpp>
|
#include <libtorrent/create_torrent.hpp>
|
||||||
#include <libtorrent/error_code.hpp>
|
#include <libtorrent/error_code.hpp>
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -42,7 +40,6 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "base/exceptions.h"
|
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/io.h"
|
#include "base/utils/io.h"
|
||||||
@@ -61,7 +58,7 @@ namespace
|
|||||||
{
|
{
|
||||||
if (QDir::isAbsolutePath(filePath)) continue;
|
if (QDir::isAbsolutePath(filePath)) continue;
|
||||||
|
|
||||||
const auto filePathElements = filePath.splitRef('/');
|
const auto filePathElements = QStringView(filePath).split(u'/');
|
||||||
// if at least one file has no root folder, no common root folder exists
|
// if at least one file has no root folder, no common root folder exists
|
||||||
if (filePathElements.count() <= 1) return {};
|
if (filePathElements.count() <= 1) return {};
|
||||||
|
|
||||||
@@ -78,22 +75,37 @@ namespace
|
|||||||
const int torrentInfoId = qRegisterMetaType<TorrentInfo>();
|
const int torrentInfoId = qRegisterMetaType<TorrentInfo>();
|
||||||
|
|
||||||
TorrentInfo::TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo)
|
TorrentInfo::TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo)
|
||||||
|
: m_nativeInfo {std::const_pointer_cast<lt::torrent_info>(nativeInfo)}
|
||||||
{
|
{
|
||||||
m_nativeInfo = std::const_pointer_cast<lt::torrent_info>(nativeInfo);
|
if (!m_nativeInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const lt::file_storage &fileStorage = m_nativeInfo->files();
|
||||||
|
m_nativeIndexes.reserve(fileStorage.num_files());
|
||||||
|
for (const lt::file_index_t nativeIndex : fileStorage.file_range())
|
||||||
|
{
|
||||||
|
if (!fileStorage.pad_file_at(nativeIndex))
|
||||||
|
m_nativeIndexes.append(nativeIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo::TorrentInfo(const TorrentInfo &other)
|
TorrentInfo::TorrentInfo(const TorrentInfo &other)
|
||||||
: m_nativeInfo(other.m_nativeInfo)
|
: m_nativeInfo {other.m_nativeInfo}
|
||||||
|
, m_nativeIndexes {other.m_nativeIndexes}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
||||||
{
|
{
|
||||||
m_nativeInfo = other.m_nativeInfo;
|
if (this != &other)
|
||||||
|
{
|
||||||
|
m_nativeInfo = other.m_nativeInfo;
|
||||||
|
m_nativeIndexes = other.m_nativeIndexes;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
nonstd::expected<TorrentInfo, QString> TorrentInfo::load(const QByteArray &data) noexcept
|
||||||
{
|
{
|
||||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||||
// used in `torrent_info()` constructor
|
// used in `torrent_info()` constructor
|
||||||
@@ -104,42 +116,23 @@ TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
|||||||
const lt::bdecode_node node = lt::bdecode(data, ec
|
const lt::bdecode_node node = lt::bdecode(data, ec
|
||||||
, nullptr, depthLimit, tokenLimit);
|
, nullptr, depthLimit, tokenLimit);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
return nonstd::make_unexpected(QString::fromStdString(ec.message()));
|
||||||
if (error)
|
|
||||||
*error = QString::fromStdString(ec.message());
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
TorrentInfo info {std::shared_ptr<lt::torrent_info>(new lt::torrent_info(node, ec))};
|
TorrentInfo info {std::shared_ptr<lt::torrent_info>(new lt::torrent_info(node, ec))};
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
return nonstd::make_unexpected(QString::fromStdString(ec.message()));
|
||||||
if (error)
|
|
||||||
*error = QString::fromStdString(ec.message());
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
|
nonstd::expected<TorrentInfo, QString> TorrentInfo::loadFromFile(const QString &path) noexcept
|
||||||
{
|
{
|
||||||
if (error)
|
|
||||||
error->clear();
|
|
||||||
|
|
||||||
QFile file {path};
|
QFile file {path};
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
if (!file.open(QIODevice::ReadOnly))
|
||||||
{
|
return nonstd::make_unexpected(file.errorString());
|
||||||
if (error)
|
|
||||||
*error = file.errorString();
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.size() > MAX_TORRENT_SIZE)
|
if (file.size() > MAX_TORRENT_SIZE)
|
||||||
{
|
return nonstd::make_unexpected(tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE)));
|
||||||
if (error)
|
|
||||||
*error = tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE));
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
try
|
try
|
||||||
@@ -148,44 +141,36 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexc
|
|||||||
}
|
}
|
||||||
catch (const std::bad_alloc &e)
|
catch (const std::bad_alloc &e)
|
||||||
{
|
{
|
||||||
if (error)
|
return nonstd::make_unexpected(tr("Torrent file read error: %1").arg(e.what()));
|
||||||
*error = tr("Torrent file read error: %1").arg(e.what());
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.size() != file.size())
|
if (data.size() != file.size())
|
||||||
{
|
return nonstd::make_unexpected(tr("Torrent file read error: size mismatch"));
|
||||||
if (error)
|
|
||||||
*error = tr("Torrent file read error: size mismatch");
|
|
||||||
return TorrentInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return load(data, error);
|
return load(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentInfo::saveToFile(const QString &path) const
|
nonstd::expected<void, QString> TorrentInfo::saveToFile(const QString &path) const
|
||||||
{
|
{
|
||||||
if (!isValid())
|
if (!isValid())
|
||||||
throw RuntimeError {tr("Invalid metadata")};
|
return nonstd::make_unexpected(tr("Invalid metadata"));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto torrentCreator = lt::create_torrent(*nativeInfo());
|
const auto torrentCreator = lt::create_torrent(*nativeInfo());
|
||||||
const lt::entry torrentEntry = torrentCreator.generate();
|
const lt::entry torrentEntry = torrentCreator.generate();
|
||||||
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, torrentEntry);
|
||||||
QFile torrentFile {path};
|
if (!result)
|
||||||
if (!torrentFile.open(QIODevice::WriteOnly))
|
return result.get_unexpected();
|
||||||
throw RuntimeError(torrentFile.errorString());
|
|
||||||
|
|
||||||
lt::bencode(Utils::IO::FileDeviceOutputIterator {torrentFile}, torrentEntry);
|
|
||||||
if (torrentFile.error() != QFileDevice::NoError)
|
|
||||||
throw RuntimeError(torrentFile.errorString());
|
|
||||||
}
|
}
|
||||||
catch (const lt::system_error &err)
|
catch (const lt::system_error &err)
|
||||||
{
|
{
|
||||||
throw RuntimeError(QString::fromLocal8Bit(err.what()));
|
return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentInfo::isValid() const
|
bool TorrentInfo::isValid() const
|
||||||
@@ -197,7 +182,7 @@ InfoHash TorrentInfo::infoHash() const
|
|||||||
{
|
{
|
||||||
if (!isValid()) return {};
|
if (!isValid()) return {};
|
||||||
|
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
return m_nativeInfo->info_hashes();
|
return m_nativeInfo->info_hashes();
|
||||||
#else
|
#else
|
||||||
return m_nativeInfo->info_hash();
|
return m_nativeInfo->info_hash();
|
||||||
@@ -245,7 +230,7 @@ qlonglong TorrentInfo::totalSize() const
|
|||||||
int TorrentInfo::filesCount() const
|
int TorrentInfo::filesCount() const
|
||||||
{
|
{
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
return m_nativeInfo->num_files();
|
return m_nativeIndexes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentInfo::pieceLength() const
|
int TorrentInfo::pieceLength() const
|
||||||
@@ -270,40 +255,36 @@ QString TorrentInfo::filePath(const int index) const
|
|||||||
{
|
{
|
||||||
if (!isValid()) return {};
|
if (!isValid()) return {};
|
||||||
return Utils::Fs::toUniformPath(
|
return Utils::Fs::toUniformPath(
|
||||||
QString::fromStdString(m_nativeInfo->files().file_path(lt::file_index_t {index})));
|
QString::fromStdString(m_nativeInfo->files().file_path(m_nativeIndexes[index])));
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList TorrentInfo::filePaths() const
|
QStringList TorrentInfo::filePaths() const
|
||||||
{
|
{
|
||||||
QStringList list;
|
QStringList list;
|
||||||
|
list.reserve(filesCount());
|
||||||
for (int i = 0; i < filesCount(); ++i)
|
for (int i = 0; i < filesCount(); ++i)
|
||||||
list << filePath(i);
|
list << filePath(i);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TorrentInfo::fileName(const int index) const
|
|
||||||
{
|
|
||||||
return Utils::Fs::fileName(filePath(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TorrentInfo::origFilePath(const int index) const
|
QString TorrentInfo::origFilePath(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return {};
|
if (!isValid()) return {};
|
||||||
return Utils::Fs::toUniformPath(
|
return Utils::Fs::toUniformPath(
|
||||||
QString::fromStdString(m_nativeInfo->orig_files().file_path(lt::file_index_t {index})));
|
QString::fromStdString(m_nativeInfo->orig_files().file_path(m_nativeIndexes[index])));
|
||||||
}
|
}
|
||||||
|
|
||||||
qlonglong TorrentInfo::fileSize(const int index) const
|
qlonglong TorrentInfo::fileSize(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
return m_nativeInfo->files().file_size(lt::file_index_t {index});
|
return m_nativeInfo->files().file_size(m_nativeIndexes[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
qlonglong TorrentInfo::fileOffset(const int index) const
|
qlonglong TorrentInfo::fileOffset(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
return m_nativeInfo->files().file_offset(lt::file_index_t {index});
|
return m_nativeInfo->files().file_offset(m_nativeIndexes[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<TrackerEntry> TorrentInfo::trackers() const
|
QVector<TrackerEntry> TorrentInfo::trackers() const
|
||||||
@@ -342,7 +323,7 @@ QVector<QUrl> TorrentInfo::urlSeeds() const
|
|||||||
QByteArray TorrentInfo::metadata() const
|
QByteArray TorrentInfo::metadata() const
|
||||||
{
|
{
|
||||||
if (!isValid()) return {};
|
if (!isValid()) return {};
|
||||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const lt::span<const char> infoSection {m_nativeInfo->info_section()};
|
const lt::span<const char> infoSection {m_nativeInfo->info_section()};
|
||||||
return {infoSection.data(), static_cast<int>(infoSection.size())};
|
return {infoSection.data(), static_cast<int>(infoSection.size())};
|
||||||
#else
|
#else
|
||||||
@@ -372,8 +353,12 @@ QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
|
|||||||
lt::piece_index_t {pieceIndex}, 0, nativeInfo()->piece_size(lt::piece_index_t {pieceIndex}));
|
lt::piece_index_t {pieceIndex}, 0, nativeInfo()->piece_size(lt::piece_index_t {pieceIndex}));
|
||||||
QVector<int> res;
|
QVector<int> res;
|
||||||
res.reserve(static_cast<decltype(res)::size_type>(files.size()));
|
res.reserve(static_cast<decltype(res)::size_type>(files.size()));
|
||||||
std::transform(files.begin(), files.end(), std::back_inserter(res),
|
for (const lt::file_slice &fileSlice : files)
|
||||||
[](const lt::file_slice &s) { return static_cast<int>(s.file_index); });
|
{
|
||||||
|
const int index = m_nativeIndexes.indexOf(fileSlice.file_index);
|
||||||
|
if (index >= 0)
|
||||||
|
res.append(index);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -419,8 +404,8 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const lt::file_storage &files = nativeInfo()->files();
|
const lt::file_storage &files = nativeInfo()->files();
|
||||||
const auto fileSize = files.file_size(lt::file_index_t {fileIndex});
|
const auto fileSize = files.file_size(m_nativeIndexes[fileIndex]);
|
||||||
const auto fileOffset = files.file_offset(lt::file_index_t {fileIndex});
|
const auto fileOffset = files.file_offset(m_nativeIndexes[fileIndex]);
|
||||||
|
|
||||||
const int beginIdx = (fileOffset / pieceLength());
|
const int beginIdx = (fileOffset / pieceLength());
|
||||||
const int endIdx = ((fileOffset + fileSize - 1) / pieceLength());
|
const int endIdx = ((fileOffset + fileSize - 1) / pieceLength());
|
||||||
@@ -433,7 +418,7 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
|
|||||||
void TorrentInfo::renameFile(const int index, const QString &newPath)
|
void TorrentInfo::renameFile(const int index, const QString &newPath)
|
||||||
{
|
{
|
||||||
if (!isValid()) return;
|
if (!isValid()) return;
|
||||||
nativeInfo()->rename_file(lt::file_index_t {index}, Utils::Fs::toNativePath(newPath).toStdString());
|
nativeInfo()->rename_file(m_nativeIndexes[index], Utils::Fs::toNativePath(newPath).toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentInfo::fileIndex(const QString &fileName) const
|
int TorrentInfo::fileIndex(const QString &fileName) const
|
||||||
@@ -485,8 +470,8 @@ void TorrentInfo::stripRootFolder()
|
|||||||
if (files.name() != newName)
|
if (files.name() != newName)
|
||||||
{
|
{
|
||||||
files.set_name(newName);
|
files.set_name(newName);
|
||||||
for (int i = 0; i < files.num_files(); ++i)
|
for (const lt::file_index_t nativeIndex : files.file_range())
|
||||||
files.rename_file(lt::file_index_t {i}, files.file_path(lt::file_index_t {i}));
|
files.rename_file(nativeIndex, files.file_path(nativeIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
files.set_name("");
|
files.set_name("");
|
||||||
@@ -505,8 +490,8 @@ void TorrentInfo::addRootFolder()
|
|||||||
const std::string rootPrefix = Utils::Fs::toNativePath(rootFolder + QLatin1Char {'/'}).toStdString();
|
const std::string rootPrefix = Utils::Fs::toNativePath(rootFolder + QLatin1Char {'/'}).toStdString();
|
||||||
lt::file_storage files = m_nativeInfo->files();
|
lt::file_storage files = m_nativeInfo->files();
|
||||||
files.set_name(rootFolder.toStdString());
|
files.set_name(rootFolder.toStdString());
|
||||||
for (int i = 0; i < files.num_files(); ++i)
|
for (const lt::file_index_t nativeIndex : files.file_range())
|
||||||
files.rename_file(lt::file_index_t {i}, rootPrefix + files.file_path(lt::file_index_t {i}));
|
files.rename_file(nativeIndex, rootPrefix + files.file_path(nativeIndex));
|
||||||
m_nativeInfo->remap_files(files);
|
m_nativeInfo->remap_files(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,3 +512,8 @@ std::shared_ptr<lt::torrent_info> TorrentInfo::nativeInfo() const
|
|||||||
{
|
{
|
||||||
return m_nativeInfo;
|
return m_nativeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<lt::file_index_t> TorrentInfo::nativeIndexes() const
|
||||||
|
{
|
||||||
|
return m_nativeIndexes;
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QtContainerFwd>
|
#include <QtContainerFwd>
|
||||||
|
|
||||||
|
#include "base/3rdparty/expected.hpp"
|
||||||
#include "base/indexrange.h"
|
#include "base/indexrange.h"
|
||||||
#include "abstractfilestorage.h"
|
#include "abstractfilestorage.h"
|
||||||
#include "torrentcontentlayout.h"
|
#include "torrentcontentlayout.h"
|
||||||
@@ -55,9 +56,9 @@ namespace BitTorrent
|
|||||||
explicit TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo = {});
|
explicit TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo = {});
|
||||||
TorrentInfo(const TorrentInfo &other);
|
TorrentInfo(const TorrentInfo &other);
|
||||||
|
|
||||||
static TorrentInfo load(const QByteArray &data, QString *error = nullptr) noexcept;
|
static nonstd::expected<TorrentInfo, QString> load(const QByteArray &data) noexcept;
|
||||||
static TorrentInfo loadFromFile(const QString &path, QString *error = nullptr) noexcept;
|
static nonstd::expected<TorrentInfo, QString> loadFromFile(const QString &path) noexcept;
|
||||||
void saveToFile(const QString &path) const;
|
nonstd::expected<void, QString> saveToFile(const QString &path) const;
|
||||||
|
|
||||||
TorrentInfo &operator=(const TorrentInfo &other);
|
TorrentInfo &operator=(const TorrentInfo &other);
|
||||||
|
|
||||||
@@ -75,7 +76,6 @@ namespace BitTorrent
|
|||||||
int piecesCount() const;
|
int piecesCount() const;
|
||||||
QString filePath(int index) const override;
|
QString filePath(int index) const override;
|
||||||
QStringList filePaths() const;
|
QStringList filePaths() const;
|
||||||
QString fileName(int index) const override;
|
|
||||||
QString origFilePath(int index) const;
|
QString origFilePath(int index) const;
|
||||||
qlonglong fileSize(int index) const override;
|
qlonglong fileSize(int index) const override;
|
||||||
qlonglong fileOffset(int index) const;
|
qlonglong fileOffset(int index) const;
|
||||||
@@ -99,6 +99,7 @@ namespace BitTorrent
|
|||||||
void setContentLayout(TorrentContentLayout layout);
|
void setContentLayout(TorrentContentLayout layout);
|
||||||
|
|
||||||
std::shared_ptr<lt::torrent_info> nativeInfo() const;
|
std::shared_ptr<lt::torrent_info> nativeInfo() const;
|
||||||
|
QVector<lt::file_index_t> nativeIndexes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// returns file index or -1 if fileName is not found
|
// returns file index or -1 if fileName is not found
|
||||||
@@ -108,6 +109,10 @@ namespace BitTorrent
|
|||||||
TorrentContentLayout defaultContentLayout() const;
|
TorrentContentLayout defaultContentLayout() const;
|
||||||
|
|
||||||
std::shared_ptr<lt::torrent_info> m_nativeInfo;
|
std::shared_ptr<lt::torrent_info> m_nativeInfo;
|
||||||
|
|
||||||
|
// internal indexes of files (payload only, excluding any .pad files)
|
||||||
|
// by which they are addressed in libtorrent
|
||||||
|
QVector<lt::file_index_t> m_nativeIndexes;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace BitTorrent
|
|||||||
class Tracker final : public QObject, public Http::IRequestHandler, private Http::ResponseBuilder
|
class Tracker final : public QObject, public Http::IRequestHandler, private Http::ResponseBuilder
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Tracker)
|
Q_DISABLE_COPY_MOVE(Tracker)
|
||||||
|
|
||||||
struct TrackerAnnounceRequest;
|
struct TrackerAnnounceRequest;
|
||||||
|
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ bool Connection::acceptsGzipEncoding(QString codings)
|
|||||||
{
|
{
|
||||||
// [rfc7231] 5.3.4. Accept-Encoding
|
// [rfc7231] 5.3.4. Accept-Encoding
|
||||||
|
|
||||||
const auto isCodingAvailable = [](const QVector<QStringRef> &list, const QString &encoding) -> bool
|
const auto isCodingAvailable = [](const QList<QStringView> &list, const QStringView encoding) -> bool
|
||||||
{
|
{
|
||||||
for (const QStringRef &str : list)
|
for (const QStringView &str : list)
|
||||||
{
|
{
|
||||||
if (!str.startsWith(encoding))
|
if (!str.startsWith(encoding))
|
||||||
continue;
|
continue;
|
||||||
@@ -149,7 +149,7 @@ bool Connection::acceptsGzipEncoding(QString codings)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// [rfc7231] 5.3.1. Quality Values
|
// [rfc7231] 5.3.1. Quality Values
|
||||||
const QStringRef substr = str.mid(encoding.size() + 3); // ex. skip over "gzip;q="
|
const QStringView substr = str.mid(encoding.size() + 3); // ex. skip over "gzip;q="
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
const double qvalue = substr.toDouble(&ok);
|
const double qvalue = substr.toDouble(&ok);
|
||||||
@@ -161,15 +161,15 @@ bool Connection::acceptsGzipEncoding(QString codings)
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const QVector<QStringRef> list = codings.remove(' ').remove('\t').splitRef(',', Qt::SkipEmptyParts);
|
const QList<QStringView> list = QStringView(codings.remove(' ').remove('\t')).split(u',', Qt::SkipEmptyParts);
|
||||||
if (list.isEmpty())
|
if (list.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool canGzip = isCodingAvailable(list, QLatin1String("gzip"));
|
const bool canGzip = isCodingAvailable(list, QString::fromLatin1("gzip"));
|
||||||
if (canGzip)
|
if (canGzip)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const bool canAny = isCodingAvailable(list, QLatin1String("*"));
|
const bool canAny = isCodingAvailable(list, QString::fromLatin1("*"));
|
||||||
if (canAny)
|
if (canAny)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Http
|
|||||||
class Connection : public QObject
|
class Connection : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Connection)
|
Q_DISABLE_COPY_MOVE(Connection)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = nullptr);
|
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace
|
|||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseHeaderLine(const QString &line, HeaderMap &out)
|
bool parseHeaderLine(const QStringView line, HeaderMap &out)
|
||||||
{
|
{
|
||||||
// [rfc7230] 3.2. Header Fields
|
// [rfc7230] 3.2. Header Fields
|
||||||
const int i = line.indexOf(':');
|
const int i = line.indexOf(':');
|
||||||
@@ -67,8 +67,8 @@ namespace
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString name = line.leftRef(i).trimmed().toString().toLower();
|
const QString name = line.left(i).trimmed().toString().toLower();
|
||||||
const QString value = line.midRef(i + 1).trimmed().toString();
|
const QString value = line.mid(i + 1).trimmed().toString();
|
||||||
out[name] = value;
|
out[name] = value;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -145,10 +145,10 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data)
|
|||||||
return {ParseStatus::BadRequest, Request(), 0}; // TODO: SHOULD respond "501 Not Implemented"
|
return {ParseStatus::BadRequest, Request(), 0}; // TODO: SHOULD respond "501 Not Implemented"
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RequestParser::parseStartLines(const QString &data)
|
bool RequestParser::parseStartLines(const QStringView data)
|
||||||
{
|
{
|
||||||
// we don't handle malformed request which uses `LF` for newline
|
// we don't handle malformed request which uses `LF` for newline
|
||||||
const QVector<QStringRef> lines = data.splitRef(CRLF, Qt::SkipEmptyParts);
|
const QList<QStringView> lines = data.split(QString::fromLatin1(CRLF), Qt::SkipEmptyParts);
|
||||||
|
|
||||||
// [rfc7230] 3.2.2. Field Order
|
// [rfc7230] 3.2.2. Field Order
|
||||||
QStringList requestLines;
|
QStringList requestLines;
|
||||||
@@ -267,7 +267,7 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray delimiter = Utils::String::unquote(contentType.midRef(idx + boundaryFieldName.size())).toLatin1();
|
const QByteArray delimiter = Utils::String::unquote(QStringView(contentType).mid(idx + boundaryFieldName.size())).toLatin1();
|
||||||
if (delimiter.isEmpty())
|
if (delimiter.isEmpty())
|
||||||
{
|
{
|
||||||
qWarning() << Q_FUNC_INFO << "boundary delimiter field empty!";
|
qWarning() << Q_FUNC_INFO << "boundary delimiter field empty!";
|
||||||
@@ -311,13 +311,13 @@ bool RequestParser::parseFormData(const QByteArray &data)
|
|||||||
const QByteArray payload = viewWithoutEndingWith(list[1], CRLF);
|
const QByteArray payload = viewWithoutEndingWith(list[1], CRLF);
|
||||||
|
|
||||||
HeaderMap headersMap;
|
HeaderMap headersMap;
|
||||||
const QVector<QStringRef> headerLines = headers.splitRef(CRLF, Qt::SkipEmptyParts);
|
const QList<QStringView> headerLines = QStringView(headers).split(QString::fromLatin1(CRLF), Qt::SkipEmptyParts);
|
||||||
for (const auto &line : headerLines)
|
for (const auto &line : headerLines)
|
||||||
{
|
{
|
||||||
if (line.trimmed().startsWith(HEADER_CONTENT_DISPOSITION, Qt::CaseInsensitive))
|
if (line.trimmed().startsWith(QString::fromLatin1(HEADER_CONTENT_DISPOSITION), Qt::CaseInsensitive))
|
||||||
{
|
{
|
||||||
// extract out filename & name
|
// extract out filename & name
|
||||||
const QVector<QStringRef> directives = line.split(';', Qt::SkipEmptyParts);
|
const QList<QStringView> directives = line.split(u';', Qt::SkipEmptyParts);
|
||||||
|
|
||||||
for (const auto &directive : directives)
|
for (const auto &directive : directives)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace Http
|
|||||||
RequestParser();
|
RequestParser();
|
||||||
|
|
||||||
ParseResult doParse(const QByteArray &data);
|
ParseResult doParse(const QByteArray &data);
|
||||||
bool parseStartLines(const QString &data);
|
bool parseStartLines(QStringView data);
|
||||||
bool parseRequestLine(const QString &line);
|
bool parseRequestLine(const QString &line);
|
||||||
|
|
||||||
bool parsePostMessage(const QByteArray &data);
|
bool parsePostMessage(const QByteArray &data);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Http
|
|||||||
class Server final : public QTcpServer
|
class Server final : public QTcpServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Server)
|
Q_DISABLE_COPY_MOVE(Server)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Server(IRequestHandler *requestHandler, QObject *parent = nullptr);
|
explicit Server(IRequestHandler *requestHandler, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class QString;
|
|||||||
|
|
||||||
class IconProvider : public QObject
|
class IconProvider : public QObject
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY(IconProvider)
|
Q_DISABLE_COPY_MOVE(IconProvider)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initInstance();
|
static void initInstance();
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Log::MsgTypes)
|
|||||||
class Logger : public QObject
|
class Logger : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Logger)
|
Q_DISABLE_COPY_MOVE(Logger)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initInstance();
|
static void initInstance();
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
|
|||||||
|
|
||||||
if (code == "badagent")
|
if (code == "badagent")
|
||||||
{
|
{
|
||||||
logger->addMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please report a bug at http://bugs.qbittorrent.org."),
|
logger->addMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please submit a bug report at http://bugs.qbittorrent.org."),
|
||||||
Log::CRITICAL);
|
Log::CRITICAL);
|
||||||
m_state = FATAL;
|
m_state = FATAL;
|
||||||
return;
|
return;
|
||||||
@@ -221,7 +221,7 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
|
|||||||
|
|
||||||
if (code == "!donator")
|
if (code == "!donator")
|
||||||
{
|
{
|
||||||
logger->addMessage(tr("Dynamic DNS error: %1 was returned by the service, please report a bug at http://bugs.qbittorrent.org.").arg("!donator"),
|
logger->addMessage(tr("Dynamic DNS error: %1 was returned by the service, please submit a bug report at http://bugs.qbittorrent.org.").arg("!donator"),
|
||||||
Log::CRITICAL);
|
Log::CRITICAL);
|
||||||
m_state = FATAL;
|
m_state = FATAL;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -32,26 +32,24 @@
|
|||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "base/3rdparty/expected.hpp"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/gzip.h"
|
#include "base/utils/gzip.h"
|
||||||
|
#include "base/utils/io.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
|
|
||||||
const int MAX_REDIRECTIONS = 20; // the common value for web browsers
|
const int MAX_REDIRECTIONS = 20; // the common value for web browsers
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool saveToFile(const QByteArray &replyData, QString &filePath)
|
nonstd::expected<QString, QString> saveToTempFile(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QTemporaryFile tmpfile {Utils::Fs::tempPath() + "XXXXXX"};
|
QTemporaryFile file {Utils::Fs::tempPath()};
|
||||||
tmpfile.setAutoRemove(false);
|
if (!file.open() || (file.write(data) != data.length()) || !file.flush())
|
||||||
|
return nonstd::make_unexpected(file.errorString());
|
||||||
|
|
||||||
if (!tmpfile.open())
|
file.setAutoRemove(false);
|
||||||
return false;
|
return file.fileName();
|
||||||
|
|
||||||
filePath = tmpfile.fileName();
|
|
||||||
|
|
||||||
tmpfile.write(replyData);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,11 +127,23 @@ void DownloadHandlerImpl::processFinishedDownload()
|
|||||||
|
|
||||||
if (m_downloadRequest.saveToFile())
|
if (m_downloadRequest.saveToFile())
|
||||||
{
|
{
|
||||||
QString filePath;
|
const QString destinationPath = m_downloadRequest.destFileName();
|
||||||
if (saveToFile(m_result.data, filePath))
|
if (destinationPath.isEmpty())
|
||||||
m_result.filePath = filePath;
|
{
|
||||||
|
const nonstd::expected<QString, QString> result = saveToTempFile(m_result.data);
|
||||||
|
if (result)
|
||||||
|
m_result.filePath = result.value();
|
||||||
|
else
|
||||||
|
setError(tr("I/O Error: %1").arg(result.error()));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
setError(tr("I/O Error"));
|
{
|
||||||
|
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(destinationPath, m_result.data);
|
||||||
|
if (result)
|
||||||
|
m_result.filePath = destinationPath;
|
||||||
|
else
|
||||||
|
setError(tr("I/O Error: %1").arg(result.error()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class QUrl;
|
|||||||
class DownloadHandlerImpl final : public Net::DownloadHandler
|
class DownloadHandlerImpl final : public Net::DownloadHandler
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(DownloadHandlerImpl)
|
Q_DISABLE_COPY_MOVE(DownloadHandlerImpl)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DownloadHandlerImpl(Net::DownloadManager *manager, const Net::DownloadRequest &downloadRequest);
|
DownloadHandlerImpl(Net::DownloadManager *manager, const Net::DownloadRequest &downloadRequest);
|
||||||
|
|||||||
@@ -348,6 +348,17 @@ Net::DownloadRequest &Net::DownloadRequest::saveToFile(const bool value)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Net::DownloadRequest::destFileName() const
|
||||||
|
{
|
||||||
|
return m_destFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Net::DownloadRequest &Net::DownloadRequest::destFileName(const QString &value)
|
||||||
|
{
|
||||||
|
m_destFileName = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Net::ServiceID Net::ServiceID::fromURL(const QUrl &url)
|
Net::ServiceID Net::ServiceID::fromURL(const QUrl &url)
|
||||||
{
|
{
|
||||||
return {url.host(), url.port(80)};
|
return {url.host(), url.port(80)};
|
||||||
|
|||||||
@@ -78,11 +78,18 @@ namespace Net
|
|||||||
bool saveToFile() const;
|
bool saveToFile() const;
|
||||||
DownloadRequest &saveToFile(bool value);
|
DownloadRequest &saveToFile(bool value);
|
||||||
|
|
||||||
|
// if saveToFile is set, the file is saved in destFileName
|
||||||
|
// (deprecated) if destFileName is not provided, the file will be saved
|
||||||
|
// in a temporary file, the name of file is set in DownloadResult::filePath
|
||||||
|
QString destFileName() const;
|
||||||
|
DownloadRequest &destFileName(const QString &value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_url;
|
QString m_url;
|
||||||
QString m_userAgent;
|
QString m_userAgent;
|
||||||
qint64 m_limit = 0;
|
qint64 m_limit = 0;
|
||||||
bool m_saveToFile = false;
|
bool m_saveToFile = false;
|
||||||
|
QString m_destFileName;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DownloadResult
|
struct DownloadResult
|
||||||
@@ -98,7 +105,7 @@ namespace Net
|
|||||||
class DownloadHandler : public QObject
|
class DownloadHandler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(DownloadHandler)
|
Q_DISABLE_COPY_MOVE(DownloadHandler)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using QObject::QObject;
|
using QObject::QObject;
|
||||||
@@ -112,7 +119,7 @@ namespace Net
|
|||||||
class DownloadManager : public QObject
|
class DownloadManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(DownloadManager)
|
Q_DISABLE_COPY_MOVE(DownloadManager)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initInstance();
|
static void initInstance();
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user