mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 22:18:05 -06:00
Compare commits
139 Commits
release-5.
...
release-5.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0188e11dd7 | ||
|
|
1dc348539b | ||
|
|
241a0e91bf | ||
|
|
68f7295500 | ||
|
|
53adb7bfa8 | ||
|
|
6128f6eecc | ||
|
|
d156a44f8d | ||
|
|
c3c7f28bad | ||
|
|
9ac14cdf9f | ||
|
|
b899ea8c40 | ||
|
|
0d7c367332 | ||
|
|
22826499d5 | ||
|
|
dbfd830b56 | ||
|
|
ad3348b95f | ||
|
|
44b08fcb74 | ||
|
|
71b752baf3 | ||
|
|
15b6091261 | ||
|
|
abe457389d | ||
|
|
abce4cd1bc | ||
|
|
2bfb336905 | ||
|
|
2dee65fa52 | ||
|
|
423b3ed9bf | ||
|
|
3454f064f0 | ||
|
|
ac9ca4f452 | ||
|
|
09899a7d0d | ||
|
|
9ab3c573dc | ||
|
|
993eb25323 | ||
|
|
1e27e6504e | ||
|
|
330dce6aa2 | ||
|
|
39b965af48 | ||
|
|
5e105b0348 | ||
|
|
f2b2a2b034 | ||
|
|
10499dffe9 | ||
|
|
eea01b94a3 | ||
|
|
374951f6f2 | ||
|
|
6d6f9bc619 | ||
|
|
84ee620fdc | ||
|
|
6079b25419 | ||
|
|
fe24bc825b | ||
|
|
94136262a8 | ||
|
|
f52947e27e | ||
|
|
315e88aee9 | ||
|
|
565c6d843a | ||
|
|
9104351c89 | ||
|
|
e58b0a65d2 | ||
|
|
878d829904 | ||
|
|
063f77bc6c | ||
|
|
2a4077414f | ||
|
|
2a44253802 | ||
|
|
4712eba0dc | ||
|
|
983b7814aa | ||
|
|
e082a21751 | ||
|
|
7dd1d1bac8 | ||
|
|
49f57b1049 | ||
|
|
fbf68a0649 | ||
|
|
39229dc06a | ||
|
|
bb314e1555 | ||
|
|
a3a8b15828 | ||
|
|
b579afe1aa | ||
|
|
93096dba56 | ||
|
|
6379c33964 | ||
|
|
84372de675 | ||
|
|
403b7c7c35 | ||
|
|
b2fab43865 | ||
|
|
387821267f | ||
|
|
dd7ef8e934 | ||
|
|
cce295faeb | ||
|
|
db5479ea01 | ||
|
|
e1216c4c9a | ||
|
|
f4a0868426 | ||
|
|
59a5fcf7d0 | ||
|
|
f9a2b02a8d | ||
|
|
04f6a565f3 | ||
|
|
3e96048ee4 | ||
|
|
d4ccf3001c | ||
|
|
64506f16bd | ||
|
|
24a7a835af | ||
|
|
93b9bf9552 | ||
|
|
f4125601de | ||
|
|
2d67729617 | ||
|
|
878ebbed41 | ||
|
|
c61c3d7cd8 | ||
|
|
978fbbdc0d | ||
|
|
63689cf763 | ||
|
|
cebc72d3cf | ||
|
|
a67bd271c6 | ||
|
|
a8cffbb205 | ||
|
|
7dfb0110d4 | ||
|
|
3ad8fcbdd2 | ||
|
|
195eae5f3d | ||
|
|
920ae26f7b | ||
|
|
09ed0d6b66 | ||
|
|
4f0cc8aa11 | ||
|
|
4d490c84e7 | ||
|
|
96607ce874 | ||
|
|
418edc7471 | ||
|
|
bd01b7c4df | ||
|
|
b0ac763048 | ||
|
|
127d2d6f0b | ||
|
|
4149609e78 | ||
|
|
78c549f83e | ||
|
|
a3a53e2e0e | ||
|
|
5aaa43e01d | ||
|
|
86745d7b07 | ||
|
|
210650a5ee | ||
|
|
fe93b6d0d8 | ||
|
|
e8b585acd8 | ||
|
|
cea20141a9 | ||
|
|
0f5a27ed50 | ||
|
|
c2cf898ccd | ||
|
|
5e5aa8a563 | ||
|
|
12a4c3fda2 | ||
|
|
5f50b701d2 | ||
|
|
9f20d9c3aa | ||
|
|
05e3130baa | ||
|
|
683492648f | ||
|
|
2f2e158877 | ||
|
|
e60e96cb0e | ||
|
|
5f31208bf1 | ||
|
|
fa58e58e70 | ||
|
|
671943a9a6 | ||
|
|
8bad80bcdd | ||
|
|
c44e300507 | ||
|
|
318a677e8f | ||
|
|
0246df790a | ||
|
|
782fbc1425 | ||
|
|
7deccd5592 | ||
|
|
4a36fe7278 | ||
|
|
1c5af96ad8 | ||
|
|
3bb47a5410 | ||
|
|
d7abeb4bf0 | ||
|
|
a19d623ead | ||
|
|
1ef21bc2b7 | ||
|
|
4687b4e8e4 | ||
|
|
d2e5163861 | ||
|
|
8a15ea8026 | ||
|
|
2b99554813 | ||
|
|
e6638f9c19 | ||
|
|
ec6eac2ba1 |
18
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
18
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,17 +7,19 @@ body:
|
||||
#### 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."
|
||||
"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.
|
||||
- Perform a **[search of the issue tracker (including closed ones)](https://github.com/qbittorrent/qBittorrent/issues?q=is%3Aissue+is%3Aopen+-label%3A%22Feature+request%22)** to avoid posting a duplicate.
|
||||
- (Optional, but recommended) Verify that the issue is not fixed and is reproducible in the latest CI (currently only on **[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:
|
||||
@@ -26,10 +28,10 @@ body:
|
||||
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.6.6 x64
|
||||
Operating system: Windows 10 Pro x64 (22H2) 10.0.19045
|
||||
Qt: 6.4.3
|
||||
libtorrent-rasterbar: 1.2.19
|
||||
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:
|
||||
@@ -71,4 +73,4 @@ body:
|
||||
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: true
|
||||
required: false
|
||||
|
||||
2
.github/workflows/ci_file_health.yaml
vendored
2
.github/workflows/ci_file_health.yaml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
curl \
|
||||
-L \
|
||||
-o "${{ runner.temp }}/pandoc.tar.gz" \
|
||||
"https://github.com/jgm/pandoc/releases/download/3.4/pandoc-3.4-linux-amd64.tar.gz"
|
||||
"https://github.com/jgm/pandoc/releases/download/3.1.7/pandoc-3.1.7-linux-amd64.tar.gz"
|
||||
tar -xf "${{ runner.temp }}/pandoc.tar.gz" -C "${{ github.workspace }}/.."
|
||||
mv "${{ github.workspace }}/.."/pandoc-* "${{ env.pandoc_path }}"
|
||||
# run pandoc
|
||||
|
||||
4
.github/workflows/ci_macos.yaml
vendored
4
.github/workflows/ci_macos.yaml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
- name: Install boost
|
||||
env:
|
||||
BOOST_MAJOR_VERSION: "1"
|
||||
BOOST_MINOR_VERSION: "86"
|
||||
BOOST_MINOR_VERSION: "85"
|
||||
BOOST_PATCH_VERSION: "0"
|
||||
run: |
|
||||
boost_url="https://boostorg.jfrog.io/artifactory/main/release/${{ env.BOOST_MAJOR_VERSION }}.${{ env.BOOST_MINOR_VERSION }}.${{ env.BOOST_PATCH_VERSION }}/source/boost_${{ env.BOOST_MAJOR_VERSION }}_${{ env.BOOST_MINOR_VERSION }}_${{ env.BOOST_PATCH_VERSION }}.tar.gz"
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
|
||||
- name: Build qBittorrent
|
||||
run: |
|
||||
CXXFLAGS="$CXXFLAGS -DQT_FORCE_ASSERTS -Werror -Wno-error=deprecated-declarations" \
|
||||
CXXFLAGS="$CXXFLAGS -Werror -Wno-error=deprecated-declarations" \
|
||||
LDFLAGS="$LDFLAGS -gz" \
|
||||
cmake \
|
||||
-B build \
|
||||
|
||||
2
.github/workflows/ci_python.yaml
vendored
2
.github/workflows/ci_python.yaml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
- name: Setup python (search engine)
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
python-version: '3.7'
|
||||
|
||||
- name: Install tools (search engine)
|
||||
run: pip install bandit mypy pycodestyle pyflakes pyright
|
||||
|
||||
2
.github/workflows/ci_ubuntu.yaml
vendored
2
.github/workflows/ci_ubuntu.yaml
vendored
@@ -101,7 +101,7 @@ jobs:
|
||||
|
||||
- name: Build qBittorrent
|
||||
run: |
|
||||
CXXFLAGS="$CXXFLAGS ${{ env.harden_flags }} -DQT_FORCE_ASSERTS -Werror" \
|
||||
CXXFLAGS="$CXXFLAGS ${{ env.harden_flags }} -Werror" \
|
||||
LDFLAGS="$LDFLAGS -gz" \
|
||||
cmake \
|
||||
-B build \
|
||||
|
||||
7
.github/workflows/ci_windows.yaml
vendored
7
.github/workflows/ci_windows.yaml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
- name: Install boost
|
||||
env:
|
||||
BOOST_MAJOR_VERSION: "1"
|
||||
BOOST_MINOR_VERSION: "86"
|
||||
BOOST_MINOR_VERSION: "85"
|
||||
BOOST_PATCH_VERSION: "0"
|
||||
run: |
|
||||
$boost_url="https://boostorg.jfrog.io/artifactory/main/release/${{ env.BOOST_MAJOR_VERSION }}.${{ env.BOOST_MINOR_VERSION }}.${{ env.BOOST_PATCH_VERSION }}/source/boost_${{ env.BOOST_MAJOR_VERSION }}_${{ env.BOOST_MINOR_VERSION }}_${{ env.BOOST_PATCH_VERSION }}.tar.gz"
|
||||
@@ -95,8 +95,7 @@ jobs:
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: "6.8.0"
|
||||
arch: win64_msvc2022_64
|
||||
version: "6.7.3"
|
||||
archives: qtbase qtsvg qttools
|
||||
cache: true
|
||||
|
||||
@@ -128,7 +127,7 @@ jobs:
|
||||
|
||||
- name: Build qBittorrent
|
||||
run: |
|
||||
$env:CXXFLAGS+="/DQT_FORCE_ASSERTS /WX"
|
||||
$env:CXXFLAGS+=" /WX"
|
||||
cmake `
|
||||
-B build `
|
||||
-G "Ninja" `
|
||||
|
||||
2
.github/workflows/coverity-scan.yaml
vendored
2
.github/workflows/coverity-scan.yaml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
- name: Install boost
|
||||
env:
|
||||
BOOST_MAJOR_VERSION: "1"
|
||||
BOOST_MINOR_VERSION: "86"
|
||||
BOOST_MINOR_VERSION: "85"
|
||||
BOOST_PATCH_VERSION: "0"
|
||||
run: |
|
||||
boost_url="https://boostorg.jfrog.io/artifactory/main/release/${{ env.BOOST_MAJOR_VERSION }}.${{ env.BOOST_MINOR_VERSION }}.${{ env.BOOST_PATCH_VERSION }}/source/boost_${{ env.BOOST_MAJOR_VERSION }}_${{ env.BOOST_MINOR_VERSION }}_${{ env.BOOST_PATCH_VERSION }}.tar.gz"
|
||||
|
||||
@@ -16,5 +16,3 @@ ths = "ths"
|
||||
[default.extend-words]
|
||||
BA = "BA"
|
||||
helo = "helo"
|
||||
Pn = "Pn"
|
||||
UIU = "UIU"
|
||||
|
||||
@@ -13,7 +13,7 @@ repos:
|
||||
- ts
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks.git
|
||||
rev: v4.6.0
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: check-json
|
||||
name: Check JSON files
|
||||
@@ -63,17 +63,19 @@ repos:
|
||||
- ts
|
||||
|
||||
- repo: https://github.com/codespell-project/codespell.git
|
||||
rev: v2.3.0
|
||||
rev: v2.2.6
|
||||
hooks:
|
||||
- id: codespell
|
||||
name: Check spelling (codespell)
|
||||
args: ["--ignore-words-list", "additionals,categor,curren,fo,ist,ket,notin,searchin,sectionin,superseeding,te,ths"]
|
||||
args: ["--ignore-words-list", "additionals,curren,fo,ist,ket,searchin,superseeding,te,ths"]
|
||||
exclude: |
|
||||
(?x)^(
|
||||
.*\.desktop |
|
||||
.*\.qrc |
|
||||
build-aux/.* |
|
||||
Changelog |
|
||||
dist/windows/installer-translations/.* |
|
||||
m4/.* |
|
||||
src/base/3rdparty/.* |
|
||||
src/searchengine/nova3/socks.py |
|
||||
src/webui/www/private/scripts/lib/.*
|
||||
@@ -82,7 +84,7 @@ repos:
|
||||
- ts
|
||||
|
||||
- repo: https://github.com/crate-ci/typos.git
|
||||
rev: v1.25.0
|
||||
rev: v1.16.18
|
||||
hooks:
|
||||
- id: typos
|
||||
name: Check spelling (typos)
|
||||
@@ -93,8 +95,11 @@ repos:
|
||||
.*\.desktop |
|
||||
.*\.qrc |
|
||||
\.pre-commit-config\.yaml |
|
||||
build-aux/.* |
|
||||
Changelog |
|
||||
configure.* |
|
||||
dist/windows/installer-translations/.* |
|
||||
m4/.* |
|
||||
src/base/3rdparty/.* |
|
||||
src/searchengine/nova3/socks.py |
|
||||
src/webui/www/private/scripts/lib/.*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_master]
|
||||
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_v50x]
|
||||
file_filter = src/lang/qbittorrent_<lang>.ts
|
||||
source_file = src/lang/qbittorrent_en.ts
|
||||
source_lang = en
|
||||
@@ -9,7 +9,7 @@ type = QT
|
||||
minimum_perc = 23
|
||||
lang_map = pt: pt_PT, zh: zh_CN
|
||||
|
||||
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_webui]
|
||||
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_webui_v50x]
|
||||
file_filter = src/webui/www/translations/webui_<lang>.ts
|
||||
source_file = src/webui/www/translations/webui_en.ts
|
||||
source_lang = en
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
<https://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -304,7 +304,8 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
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, see <https://www.gnu.org/licenses/>.
|
||||
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.
|
||||
|
||||
@@ -328,8 +329,8 @@ 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 Moe Ghoul>, 1 April 1989
|
||||
Moe Ghoul, President of Vice
|
||||
<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
|
||||
|
||||
62
Changelog
62
Changelog
@@ -1,4 +1,28 @@
|
||||
Unreleased - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.1.0
|
||||
Mon Dec 16th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.3
|
||||
- BUGFIX: Discard obsolete "state update" events after torrent is reloaded (glassez)
|
||||
- BUGFIX: Fix incorrect SQL column definition (glassez)
|
||||
- BUGFIX: Avoid redundant requests of announce entries from libtorrent (glassez)
|
||||
- WEBUI: Fix removing tracker URL with '|' character (Thomas Piccirello)
|
||||
- WEBUI: Fix reloading page after login (Evgenii Ryshkov)
|
||||
- WEBAPI: Fix incorrect key in torrent creator (Bartu Özen)
|
||||
- RSS: Don't add duplicate episodes to previously matched (wavygecko)
|
||||
- RSS: Use cached current time when parsing RSS feed (glassez)
|
||||
- WINDOWS: Don't follow symlink when creating torrents on Windows (Chocobo1)
|
||||
- WINDOWS: NSIS: Update Italian translation (Giacomo411)
|
||||
|
||||
Sun Nov 17th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.2
|
||||
- BUGFIX: Remove trackers from previous category when moved to new one (glassez)
|
||||
- BUGFIX: Fix `.torrent` file could not be deleted when torrent is canceled (glassez)
|
||||
- BUGFIX: Reset tracker entries when pausing the session (glassez)
|
||||
- BUGFIX: Check real palette darkness to detect "dark theme" (glassez)
|
||||
- BUGFIX: Correctly handle "torrent finished" events (glassez)
|
||||
- BUGFIX: Preserve initial torrent progress while checking resume data (glassez)
|
||||
- BUGFIX: Avoid reapplying Mark-of-the-Web when it already exists (Chocobo1)
|
||||
- BUGFIX: Don't apply Mark-of-the-Web on existing files (Chocobo1)
|
||||
- WEBUI: Add color scheme switcher (sledgehammer999)
|
||||
- SEARCH: Correctly delete the moved search tab (glassez)
|
||||
- WINDOWS: Correctly save and restore Qt style setting (glassez)
|
||||
- WINDOWS: NSIS: update Luxembourgish, Simplified Chinese and Traditional Chinese translations (Ikko Eltociear Ashimine, 3gf8jv4dv)
|
||||
|
||||
Mon Oct 28th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.1
|
||||
- FEATURE: Add "Simple pread/pwrite" disk IO type (Hanabishi)
|
||||
@@ -106,42 +130,6 @@ Sun Sep 29th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.0
|
||||
- OTHER: Minimum supported versions: Qt: 6.5, Boost: 1.76, OpenSSL: 3.0.2
|
||||
- OTHER: Switch to C++20
|
||||
|
||||
Mon Sep 16th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.6.7
|
||||
- BUGFIX: The updater will launch the link to the build variant you're currently using (sledgehammer999)
|
||||
- BUGFIX: Focus on Download button if torrent link retrieved from the clipboard (glassez)
|
||||
- WEBUI: RSS: The list of feeds wouldn't load for Apply Rule (glassez)
|
||||
|
||||
Sun Aug 18th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.6.6
|
||||
- BUGFIX: Fix handling of tags containing '&' character (glassez)
|
||||
- BUGFIX: Show scroll bar in Torrent Tags dialog (glassez)
|
||||
- BUGFIX: Apply bulk changes to correct content widget items (glassez)
|
||||
- BUGFIX: Hide zero status filters when torrents are removed (glassez)
|
||||
- BUGFIX: Fix `Incomplete Save Path` cannot be changed for torrents without metadata (glassez)
|
||||
- WEBUI: Correctly apply changed "save path" of RSS rules (glassez)
|
||||
- WEBUI: Clear tracker list on full update (skomerko)
|
||||
- OTHER: Update User-Agent string for internal downloader and search engines (cayenne17)
|
||||
|
||||
Sun May 26th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.6.5
|
||||
- BUGFIX: Prevent app from being closed when disabling system tray icon (glassez)
|
||||
- BUGFIX: Fix <kbd>Enter</kbd> key behavior in Add new torrent dialog (glassez)
|
||||
- BUGFIX: Prevent invalid status filter index from being used (glassez)
|
||||
- BUGFIX: Add extra offset for dialog frame (glassez)
|
||||
- BUGFIX: Don't overwrite stored layout of main window with incorrect one (glassez)
|
||||
- BUGFIX: Don't forget to resume "missing files" torrent when rechecking (glassez)
|
||||
- WEBUI: Restore ability to use server-side translation by custom WebUI (glassez)
|
||||
- WEBUI: Fix wrong peer number (Chocobo1)
|
||||
- LINUX: Improve AppStream metadata (Chocobo1)
|
||||
|
||||
Sun Mar 24th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.6.4
|
||||
- BUGFIX: Correctly adjust "Add New torrent" dialog position in all the cases (glassez)
|
||||
- BUGFIX: Change "metadata received" stop condition behavior (glassez)
|
||||
- BUGFIX: Add a small delay before processing the key input of search boxes (Chocobo1)
|
||||
- BUGFIX: Ensure the profile path is pointing to a directory (Chocobo1)
|
||||
- RSS: Use better icons for RSS articles (glassez)
|
||||
- WINDOWS: NSIS: Update French, Hungarian translations (MarcDrieu, foxi69)
|
||||
- LINUX: Fix sorting when ICU isn't used (Chocobo1)
|
||||
- LINUX: Fix invisible tray icon on Plasma 6 (tehcneko)
|
||||
|
||||
Mon Jan 15th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.6.3
|
||||
- BUGFIX: Correctly update number of filtered items (glassez)
|
||||
- BUGFIX: Don't forget to store Stop condition value (glassez)
|
||||
|
||||
2
INSTALL
2
INSTALL
@@ -18,7 +18,7 @@ qBittorrent - A BitTorrent client in C++ / Qt
|
||||
- CMake >= 3.16
|
||||
* Compile-time only
|
||||
|
||||
- Python >= 3.9.0
|
||||
- Python >= 3.7.0
|
||||
* Optional, run-time only
|
||||
* Used by the bundled search engine
|
||||
|
||||
|
||||
18
SECURITY.md
18
SECURITY.md
@@ -1,18 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
qBittorrent takes the security of our software seriously, including all source code repositories managed through our GitHub organisation.
|
||||
If you believe you have found a security vulnerability in qBittorrent, please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
Please do not report security vulnerabilities through public GitHub issues. Instead, please use GitHubs private vulnerability reporting functionality associated to this repository. Additionally, you may email us with all security-related inquiries and notifications at `security@qbittorrent.org`.
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
1. Type of issue
|
||||
2. Step-by-step instructions to reproduce the issue
|
||||
3. Proof-of-concept or exploit code (if possible)
|
||||
4. Potential impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly. Any and all CVEs will be requested and issued through GitHubs private vulnerability reporting functionality, which will be published alongside the disclosure.
|
||||
|
||||
This security policy only applies to the most recent stable branch of qBittorrent. Flaws in old versions that are not present in the current stable branch will not be fixed.
|
||||
2
dist/mac/Info.plist
vendored
2
dist/mac/Info.plist
vendored
@@ -55,7 +55,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>5.1.0</string>
|
||||
<string>5.0.3</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
||||
146
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
146
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
@@ -14,216 +14,220 @@ Keywords=bittorrent;torrent;magnet;download;p2p;
|
||||
SingleMainWindow=true
|
||||
|
||||
# Translations
|
||||
Comment[af]=Aflaai en deel lêers oor BitTorrent
|
||||
GenericName[af]=BitTorrent kliënt
|
||||
Comment[af]=Aflaai en deel lêers oor BitTorrent
|
||||
Name[af]=qBittorrent
|
||||
Comment[ar]=نزّل وشارك الملفات عبر كيوبتتورنت
|
||||
GenericName[ar]=عميل بتتورنت
|
||||
Comment[ar]=نزّل وشارك الملفات عبر كيوبتتورنت
|
||||
Name[ar]=qBittorrent
|
||||
Comment[be]=Спампоўванне і раздача файлаў праз пратакол BitTorrent
|
||||
GenericName[be]=Кліент BitTorrent
|
||||
Comment[be]=Спампоўванне і раздача файлаў праз пратакол BitTorrent
|
||||
Name[be]=qBittorrent
|
||||
Comment[bg]=Сваляне и споделяне на файлове чрез BitTorrent
|
||||
GenericName[bg]=BitTorrent клиент
|
||||
Comment[bg]=Сваляне и споделяне на файлове чрез BitTorrent
|
||||
Name[bg]=qBittorrent
|
||||
Comment[bn]=বিটটরেন্টে ফাইল ডাউনলোড এবং শেয়ার করুন
|
||||
GenericName[bn]=বিটটরেন্ট ক্লায়েন্ট
|
||||
Comment[bn]=বিটটরেন্টে ফাইল ডাউনলোড এবং শেয়ার করুন
|
||||
Name[bn]=qBittorrent
|
||||
Comment[zh]=通过 BitTorrent 下载和分享文件
|
||||
GenericName[zh]=BitTorrent 客户端
|
||||
Comment[zh]=通过 BitTorrent 下载和分享文件
|
||||
Name[zh]=qBittorrent
|
||||
Comment[bs]=Preuzmi i dijeli datoteke preko BitTorrent-a
|
||||
GenericName[bs]=BitTorrent klijent
|
||||
Comment[bs]=Preuzmi i dijeli datoteke preko BitTorrent-a
|
||||
Name[bs]=qBittorrent
|
||||
Comment[ca]=Baixeu i compartiu fitxers amb el BitTorrent
|
||||
GenericName[ca]=Client de BitTorrent
|
||||
Comment[ca]=Baixeu i compartiu fitxers amb el BitTorrent
|
||||
Name[ca]=qBittorrent
|
||||
Comment[cs]=Stahování a sdílení souborů přes síť BitTorrent
|
||||
GenericName[cs]=BitTorrent klient
|
||||
Comment[cs]=Stahování a sdílení souborů přes síť BitTorrent
|
||||
Name[cs]=qBittorrent
|
||||
Comment[da]=Download og del filer over BitTorrent
|
||||
GenericName[da]=BitTorrent-klient
|
||||
Comment[da]=Download og del filer over BitTorrent
|
||||
Name[da]=qBittorrent
|
||||
Comment[de]=Über BitTorrent Dateien herunterladen und teilen
|
||||
GenericName[de]=BitTorrent Client
|
||||
Comment[de]=Über BitTorrent Dateien herunterladen und teilen
|
||||
Name[de]=qBittorrent
|
||||
Comment[el]=Κάντε λήψη και μοιραστείτε αρχεία μέσω BitTorrent
|
||||
GenericName[el]=BitTorrent client
|
||||
Comment[el]=Κάντε λήψη και μοιραστείτε αρχεία μέσω BitTorrent
|
||||
Name[el]=qBittorrent
|
||||
Comment[en_GB]=Download and share files over BitTorrent
|
||||
GenericName[en_GB]=BitTorrent client
|
||||
Comment[en_GB]=Download and share files over BitTorrent
|
||||
Name[en_GB]=qBittorrent
|
||||
Comment[es]=Descargue y comparta archivos por BitTorrent
|
||||
GenericName[es]=Cliente BitTorrent
|
||||
Comment[es]=Descargue y comparta archivos por BitTorrent
|
||||
Name[es]=qBittorrent
|
||||
Comment[et]=Lae alla ja jaga faile üle BitTorrenti
|
||||
GenericName[et]=BitTorrent klient
|
||||
Comment[et]=Lae alla ja jaga faile üle BitTorrenti
|
||||
Name[et]=qBittorrent
|
||||
Comment[eu]=Jeitsi eta elkarbanatu agiriak BitTorrent bidez
|
||||
GenericName[eu]=BitTorrent bezeroa
|
||||
Comment[eu]=Jeitsi eta elkarbanatu agiriak BitTorrent bidez
|
||||
Name[eu]=qBittorrent
|
||||
Comment[fa]=دانلود و به اشتراک گذاری فایل های بوسیله بیت تورنت
|
||||
GenericName[fa]=بیت تورنت نسخه کلاینت
|
||||
Comment[fa]=دانلود و به اشتراک گذاری فایل های بوسیله بیت تورنت
|
||||
Name[fa]=qBittorrent
|
||||
Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen
|
||||
GenericName[fi]=BitTorrent-asiakasohjelma
|
||||
Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen
|
||||
Name[fi]=qBittorrent
|
||||
Comment[fr]=Télécharger et partager des fichiers sur BitTorrent
|
||||
GenericName[fr]=Client BitTorrent
|
||||
Comment[fr]=Télécharger et partager des fichiers sur BitTorrent
|
||||
Name[fr]=qBittorrent
|
||||
Comment[gl]=Descargar e compartir ficheiros co protocolo BitTorrent
|
||||
GenericName[gl]=Cliente BitTorrent
|
||||
Comment[gl]=Descargar e compartir ficheiros co protocolo BitTorrent
|
||||
Name[gl]=qBittorrent
|
||||
Comment[gu]=બિટ્ટોરેંટ પર ફાઈલો ડાઉનલોડ અને શેર કરો
|
||||
GenericName[gu]=બિટ્ટોરેંટ ક્લાયન્ટ
|
||||
Comment[gu]=બિટ્ટોરેંટ પર ફાઈલો ડાઉનલોડ અને શેર કરો
|
||||
Name[gu]=qBittorrent
|
||||
Comment[he]=הורד ושתף קבצים על גבי ביטורנט
|
||||
GenericName[he]=לקוח ביטורנט
|
||||
Comment[he]=הורד ושתף קבצים על גבי ביטורנט
|
||||
Name[he]=qBittorrent
|
||||
Comment[hr]=Preuzmite i dijelite datoteke putem BitTorrenta
|
||||
GenericName[hr]=BitTorrent klijent
|
||||
Comment[hr]=Preuzmite i dijelite datoteke putem BitTorrenta
|
||||
Name[hr]=qBittorrent
|
||||
Comment[hu]=Fájlok letöltése és megosztása a BitTorrent hálózaton keresztül
|
||||
GenericName[hu]=BitTorrent kliens
|
||||
Comment[hu]=Fájlok letöltése és megosztása a BitTorrent hálózaton keresztül
|
||||
Name[hu]=qBittorrent
|
||||
Comment[hy]=Նիշքերի փոխանցում BitTorrent-ի միջոցով
|
||||
GenericName[hy]=BitTorrent սպասառու
|
||||
Comment[hy]=Նիշքերի փոխանցում BitTorrent-ի միջոցով
|
||||
Name[hy]=qBittorrent
|
||||
Comment[id]=Unduh dan berbagi berkas melalui BitTorrent
|
||||
GenericName[id]=Klien BitTorrent
|
||||
Comment[id]=Unduh dan berbagi berkas melalui BitTorrent
|
||||
Name[id]=qBittorrent
|
||||
Comment[is]=Sækja og deila skrám yfir BitTorrent
|
||||
GenericName[is]=BitTorrent biðlarar
|
||||
Comment[is]=Sækja og deila skrám yfir BitTorrent
|
||||
Name[is]=qBittorrent
|
||||
Comment[it]=Scarica e condividi file tramite BitTorrent
|
||||
GenericName[it]=Client BitTorrent
|
||||
Comment[it]=Scarica e condividi file tramite BitTorrent
|
||||
Name[it]=qBittorrent
|
||||
Comment[ja]=BitTorrentでファイルのダウンロードと共有
|
||||
GenericName[ja]=BitTorrentクライアント
|
||||
Comment[ja]=BitTorrentでファイルのダウンロードと共有
|
||||
Name[ja]=qBittorrent
|
||||
Comment[ka]=გადმოტვირთეთ და გააზიარეთ ფაილები BitTorrent-ის საშუალებით
|
||||
GenericName[ka]=BitTorrent კლიენტი
|
||||
Comment[ka]=გადმოტვირთეთ და გააზიარეთ ფაილები BitTorrent-ის საშუალებით
|
||||
Name[ka]=qBittorrent
|
||||
Comment[ko]=BitTorrent를 통한 파일 내려받기 및 공유
|
||||
GenericName[ko]=BitTorrent 클라이언트
|
||||
Comment[ko]=BitTorrent를 통한 파일 다운로드 및 공유
|
||||
Name[ko]=qBittorrent
|
||||
Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle
|
||||
GenericName[lt]=BitTorrent klientas
|
||||
Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle
|
||||
Name[lt]=qBittorrent
|
||||
Comment[mk]=Превземајте и споделувајте фајлови преку BitTorrent
|
||||
GenericName[mk]=BitTorrent клиент
|
||||
Comment[mk]=Превземајте и споделувајте фајлови преку BitTorrent
|
||||
Name[mk]=qBittorrent
|
||||
Comment[my]=တောရန့်ဖြင့်ဖိုင်များဒေါင်းလုဒ်ဆွဲရန်နှင့်မျှဝေရန်
|
||||
GenericName[my]=တောရန့်စီမံခန့်ခွဲသည့်အရာ
|
||||
Comment[my]=တောရန့်ဖြင့်ဖိုင်များဒေါင်းလုဒ်ဆွဲရန်နှင့်မျှဝေရန်
|
||||
Name[my]=qBittorrent
|
||||
Comment[nb]=Last ned og del filer over BitTorrent
|
||||
GenericName[nb]=BitTorrent-klient
|
||||
Comment[nb]=Last ned og del filer over BitTorrent
|
||||
Name[nb]=qBittorrent
|
||||
Comment[nl]=Bestanden downloaden en delen via BitTorrent
|
||||
GenericName[nl]=BitTorrent-client
|
||||
Comment[nl]=Bestanden downloaden en delen via BitTorrent
|
||||
Name[nl]=qBittorrent
|
||||
Comment[pl]=Pobieraj i dziel się plikami przez BitTorrent
|
||||
GenericName[pl]=Klient BitTorrent
|
||||
Comment[pl]=Pobieraj i dziel się plikami przez BitTorrent
|
||||
Name[pl]=qBittorrent
|
||||
Comment[pt]=Transferir e partilhar ficheiros por BitTorrent
|
||||
GenericName[pt]=Cliente BitTorrent
|
||||
Comment[pt]=Transferir e partilhar ficheiros por BitTorrent
|
||||
Name[pt]=qBittorrent
|
||||
Comment[pt_BR]=Baixe e compartilhe arquivos pelo BitTorrent
|
||||
GenericName[pt_BR]=Cliente BitTorrent
|
||||
Comment[pt_BR]=Baixe e compartilhe arquivos pelo BitTorrent
|
||||
Name[pt_BR]=qBittorrent
|
||||
Comment[ro]=Descărcați și partajați fișiere prin BitTorrent
|
||||
GenericName[ro]=Client BitTorrent
|
||||
Comment[ro]=Descărcați și partajați fișiere prin BitTorrent
|
||||
Name[ro]=qBittorrent
|
||||
Comment[ru]=Обмен файлами по сети БитТоррент
|
||||
GenericName[ru]=Клиент сети БитТоррент
|
||||
Comment[ru]=Обмен файлами по сети БитТоррент
|
||||
Name[ru]=qBittorrent
|
||||
Comment[sk]=Sťahovanie a zdieľanie súborov prostredníctvom siete BitTorrent
|
||||
GenericName[sk]=Klient siete BitTorrent
|
||||
Comment[sk]=Sťahovanie a zdieľanie súborov prostredníctvom siete BitTorrent
|
||||
Name[sk]=qBittorrent
|
||||
Comment[sl]=Prenesite in delite datoteke preko BitTorrenta
|
||||
GenericName[sl]=BitTorrent odjemalec
|
||||
Comment[sl]=Prenesite in delite datoteke preko BitTorrenta
|
||||
Name[sl]=qBittorrent
|
||||
GenericName[sq]=Klienti BitTorrent
|
||||
Comment[sq]=Shkarko dhe shpërndaj skedarë në BitTorrent
|
||||
Name[sq]=qBittorrent
|
||||
Comment[sr]=Преузимајте и делите фајлове преко BitTorrent протокола
|
||||
GenericName[sr]=BitTorrent-клијент
|
||||
GenericName[sr]=BitTorrent клијент
|
||||
Comment[sr]=Преузимајте и делите фајлове преко BitTorrent-а
|
||||
Name[sr]=qBittorrent
|
||||
Comment[sr@latin]=Preuzimanje i deljenje fajlova preko BitTorrent-a
|
||||
GenericName[sr@latin]=BitTorrent klijent
|
||||
Comment[sr@latin]=Preuzimanje i deljenje fajlova preko BitTorrent-a
|
||||
Name[sr@latin]=qBittorrent
|
||||
Comment[sv]=Hämta och dela filer över BitTorrent
|
||||
GenericName[sv]=BitTorrent-klient
|
||||
Comment[sv]=Hämta och dela filer över BitTorrent
|
||||
Name[sv]=qBittorrent
|
||||
Comment[ta]=BitTorrent வழியாக கோப்புகளை பதிவிறக்க மற்றும் பகிர
|
||||
GenericName[ta]=BitTorrent வாடிக்கையாளர்
|
||||
Comment[ta]=BitTorrent வழியாக கோப்புகளை பதிவிறக்க மற்றும் பகிர
|
||||
Name[ta]=qBittorrent
|
||||
Comment[te]=క్యు బిట్ టొరెంట్ తో ఫైల్స్ దిగుమతి చేసుకోండి , పంచుకోండి
|
||||
GenericName[te]=క్యు బిట్ టొరెంట్ క్లయింట్
|
||||
Comment[te]=క్యు బిట్ టొరెంట్ తో ఫైల్స్ దిగుమతి చేసుకోండి , పంచుకోండి
|
||||
Name[te]=qBittorrent
|
||||
Comment[th]=ดาวน์โหลดและแชร์ไฟล์ผ่าน BitTorrent
|
||||
GenericName[th]=โปรแกรมบิททอเร้นท์
|
||||
GenericName[th]=ไคลเอนต์บิททอร์เรนต์
|
||||
Comment[th]=ดาวน์โหลดและแชร์ไฟล์ผ่านบิตทอร์เรนต์
|
||||
Name[th]=qBittorrent
|
||||
Comment[tr]=Dosyaları BitTorrent üzerinden indirin ve paylaşın
|
||||
GenericName[tr]=BitTorrent istemcisi
|
||||
Comment[tr]=Dosyaları BitTorrent üzerinden indirin ve paylaşın
|
||||
Name[tr]=qBittorrent
|
||||
Comment[ur]=BitTorrent پر فائلوں کو ڈاؤن لوڈ کریں اور اشتراک کریں
|
||||
GenericName[ur]=قیو بٹ ٹورنٹ کلائنٹ
|
||||
Comment[ur]=BitTorrent پر فائلوں کو ڈاؤن لوڈ کریں اور اشتراک کریں
|
||||
Name[ur]=qBittorrent
|
||||
Comment[uk]=Завантажуйте та поширюйте файли через BitTorrent
|
||||
GenericName[uk]=BitTorrent-клієнт
|
||||
Comment[uk]=Завантажуйте та поширюйте файли через BitTorrent
|
||||
Name[uk]=qBittorrent
|
||||
Comment[vi]=Tải xuống và chia sẻ tệp qua BitTorrent
|
||||
GenericName[vi]=Máy khách BitTorrent
|
||||
Comment[vi]=Tải xuống và chia sẻ tệp qua BitTorrent
|
||||
Name[vi]=qBittorrent
|
||||
Comment[zh_HK]=經由BitTorrent下載並分享檔案
|
||||
GenericName[zh_HK]=BitTorrent用戶端
|
||||
Comment[zh_HK]=經由BitTorrent下載並分享檔案
|
||||
Name[zh_HK]=qBittorrent
|
||||
Comment[zh_TW]=經由 BitTorrent 下載並分享檔案
|
||||
GenericName[zh_TW]=BitTorrent 用戶端
|
||||
Comment[zh_TW]=使用 BitTorrent 下載並分享檔案
|
||||
Name[zh_TW]=qBittorrent
|
||||
Comment[eo]=Elŝutu kaj kunhavigu dosierojn per BitTorrent
|
||||
GenericName[eo]=BitTorrent-kliento
|
||||
Comment[eo]=Elŝutu kaj kunhavigu dosierojn per BitTorrent
|
||||
Name[eo]=qBittorrent
|
||||
Comment[kk]=BitTorrent арқылы файл жүктеу және бөлісу
|
||||
GenericName[kk]=BitTorrent клиенті
|
||||
Comment[kk]=BitTorrent арқылы файл жүктеу және бөлісу
|
||||
Name[kk]=qBittorrent
|
||||
Comment[en_AU]=Download and share files over BitTorrent
|
||||
GenericName[en_AU]=BitTorrent client
|
||||
Comment[en_AU]=Download and share files over BitTorrent
|
||||
Name[en_AU]=qBittorrent
|
||||
Name[rm]=qBittorrent
|
||||
Name[jv]=qBittorrent
|
||||
Comment[oc]=Telecargar e partejar de fichièrs amb BitTorrent
|
||||
GenericName[oc]=Client BitTorrent
|
||||
Comment[oc]=Telecargar e partejar de fichièrs amb BitTorrent
|
||||
Name[oc]=qBittorrent
|
||||
Name[ug]=qBittorrent
|
||||
Name[yi]=qBittorrent
|
||||
Comment[nqo]=ߞߐߕߐ߯ߘߐ ߟߎ߬ ߟߊߖߌ߰ ߞߊ߬ ߓߊ߲߫ ߞߵߊ߬ߟߎ߬ ߘߐߕߟߊ߫ ߓߌߙߏߙߍ߲ߕ ߞߊ߲߬
|
||||
GenericName[nqo]=ߓߌߙߏߙߍ߲ߕ ߕߣߐ߬ߓߐ߬ߟߊ
|
||||
Comment[nqo]=ߞߐߕߐ߯ߘߐ ߟߎ߬ ߟߊߖߌ߰ ߞߊ߬ ߓߊ߲߫ ߞߵߊ߬ߟߎ߬ ߘߐߕߟߊ߫ ߓߌߙߏߙߍ߲ߕ ߞߊ߲߬
|
||||
Name[nqo]=qBittorrent
|
||||
Comment[uz@Latn]=BitTorrent orqali fayllarni yuklab olish va baham ko‘rish
|
||||
GenericName[uz@Latn]=BitTorrent mijozi
|
||||
Comment[uz@Latn]=BitTorrent orqali fayllarni yuklab olish va baham ko‘rish
|
||||
Name[uz@Latn]=qBittorrent
|
||||
Comment[ltg]=Atsasyuteit i daleit failus ar BitTorrent
|
||||
GenericName[ltg]=BitTorrent klients
|
||||
Comment[ltg]=Atsasyuteit i daleit failus ar BitTorrent
|
||||
Name[ltg]=qBittorrent
|
||||
Comment[hi_IN]=BitTorrent द्वारा फाइल डाउनलोड व सहभाजन
|
||||
GenericName[hi_IN]=Bittorrent साधन
|
||||
Comment[hi_IN]=BitTorrent द्वारा फाइल डाउनलोड व सहभाजन
|
||||
Name[hi_IN]=qBittorrent
|
||||
Comment[az@latin]=Faylları BitTorrent vasitəsilə endirin və paylaşın
|
||||
GenericName[az@latin]=BitTorrent client
|
||||
Comment[az@latin]=Faylları BitTorrent vasitəsilə endirin və paylaşın
|
||||
Name[az@latin]=qBittorrent
|
||||
Comment[lv_LV]=Lejupielādēt un koplietot failus ar BitTorrent
|
||||
GenericName[lv_LV]=BitTorrent klients
|
||||
Comment[lv_LV]=Lejupielādēt un koplietot failus ar BitTorrent
|
||||
Name[lv_LV]=qBittorrent
|
||||
Comment[ms_MY]=Muat turun dan kongsi fail melalui BitTorrent
|
||||
GenericName[ms_MY]=Klien BitTorrent
|
||||
Comment[ms_MY]=Muat turun dan kongsi fail melalui BitTorrent
|
||||
Name[ms_MY]=qBittorrent
|
||||
Comment[mn_MN]=BitTorrent-оор файлуудаа тат, түгээ
|
||||
GenericName[mn_MN]=BitTorrent татагч
|
||||
Comment[mn_MN]=BitTorrent-оор файлуудаа тат, түгээ
|
||||
Name[mn_MN]=qBittorrent
|
||||
Comment[ne_NP]=फाइलहरू डाउनलोड गर्नुहोस् र BitTorrent मा साझा गर्नुहोस्
|
||||
GenericName[ne_NP]=BitTorrent क्लाइन्ट
|
||||
Comment[ne_NP]=फाइलहरू डाउनलोड गर्नुहोस् र BitTorrent मा साझा गर्नुहोस्
|
||||
Name[ne_NP]=qBittorrent
|
||||
Comment[pt_PT]=Transferir e partilhar ficheiros por BitTorrent
|
||||
GenericName[pt_PT]=Cliente BitTorrent
|
||||
Comment[pt_PT]=Transferir e partilhar ficheiros por BitTorrent
|
||||
Name[pt_PT]=qBittorrent
|
||||
GenericName[si_LK]=BitTorrent සේවාදායකයා
|
||||
Comment[si_LK]=BitTorrent හරහා ගොනු බාගත කර බෙදාගන්න.
|
||||
Name[si_LK]=qBittorrent
|
||||
|
||||
@@ -62,6 +62,6 @@
|
||||
<url type="contribute">https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md</url>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="5.1.0~beta1" date="2024-12-16"/>
|
||||
<release version="5.0.3" date="2024-12-16"/>
|
||||
</releases>
|
||||
</component>
|
||||
|
||||
2
dist/windows/config.nsh
vendored
2
dist/windows/config.nsh
vendored
@@ -14,7 +14,7 @@
|
||||
; 4.5.1.3 -> good
|
||||
; 4.5.1.3.2 -> bad
|
||||
; 4.5.0beta -> bad
|
||||
!define /ifndef QBT_VERSION "5.1.0"
|
||||
!define /ifndef QBT_VERSION "5.0.3"
|
||||
|
||||
; Option that controls the installer's window name
|
||||
; If set, its value will be used like this:
|
||||
|
||||
@@ -1,44 +1,41 @@
|
||||
.\" Automatically generated by Pandoc 3.4
|
||||
.\" Automatically generated by Pandoc 3.1.7
|
||||
.\"
|
||||
.TH "QBITTORRENT\-NOX" "1" "January 16th 2010" "Command line Bittorrent client written in C++ / Qt"
|
||||
.TH "QBITTORRENT-NOX" "1" "January 16th 2010" "Command line Bittorrent client written in C++ / Qt" ""
|
||||
.SH NAME
|
||||
qBittorrent\-nox \- a command line Bittorrent client written in C++ / Qt
|
||||
qBittorrent-nox - a command line Bittorrent client written in C++ / Qt
|
||||
.SH SYNOPSIS
|
||||
\f[B]qbittorrent\-nox\f[R]
|
||||
\f[CR][\-\-d|\-\-daemon] [\-\-webui\-port=x] [TORRENT_FILE | URL]...\f[R]
|
||||
\f[B]qbittorrent-nox\f[R]
|
||||
\f[CR][--d|--daemon] [--webui-port=x] [TORRENT_FILE | URL]...\f[R]
|
||||
.PP
|
||||
\f[B]qbittorrent\-nox\f[R] \f[CR]\-\-help\f[R]
|
||||
\f[B]qbittorrent-nox\f[R] \f[CR]--help\f[R]
|
||||
.PP
|
||||
\f[B]qbittorrent\-nox\f[R] \f[CR]\-\-version\f[R]
|
||||
\f[B]qbittorrent-nox\f[R] \f[CR]--version\f[R]
|
||||
.SH DESCRIPTION
|
||||
\f[B]qBittorrent\-nox\f[R] is an advanced command\-line Bittorrent
|
||||
client written in C++ / Qt using the \f[B]libtorrent\-rasterbar\f[R]
|
||||
library by Arvid Norberg.
|
||||
qBittorrent\-nox aims to be a good alternative to other command line
|
||||
\f[B]qBittorrent-nox\f[R] is an advanced command-line Bittorrent client
|
||||
written in C++ / Qt using the \f[B]libtorrent-rasterbar\f[R] library by
|
||||
Arvid Norberg.
|
||||
qBittorrent-nox aims to be a good alternative to other command line
|
||||
bittorrent clients and provides features similar to popular graphical
|
||||
clients.
|
||||
.PP
|
||||
qBittorrent\-nox is fast, stable, light and it supports unicode.
|
||||
It also comes with UPnP port forwarding / NAT\-PMP, encryption (Vuze
|
||||
qBittorrent-nox is fast, stable, light and it supports unicode.
|
||||
It also comes with UPnP port forwarding / NAT-PMP, encryption (Vuze
|
||||
compatible), FAST extension (mainline) and PeX support (utorrent
|
||||
compatible).
|
||||
.PP
|
||||
qBittorrent\-nox is meant to be controlled via its feature\-rich Web UI
|
||||
qBittorrent-nox is meant to be controlled via its feature-rich Web UI
|
||||
which is accessible as a default on http://localhost:8080.
|
||||
The Web UI access is secured and the default account user name is
|
||||
\[lq]admin\[rq] with \[lq]adminadmin\[rq] as a password.
|
||||
.SH OPTIONS
|
||||
\f[B]\f[CB]\-\-help\f[B]\f[R] Prints the command line options.
|
||||
\f[B]\f[CB]--help\f[B]\f[R] Prints the command line options.
|
||||
.PP
|
||||
\f[B]\f[CB]\-\-version\f[B]\f[R] Prints qbittorrent program version
|
||||
\f[B]\f[CB]--version\f[B]\f[R] Prints qbittorrent program version
|
||||
number.
|
||||
.PP
|
||||
\f[B]\f[CB]\-\-webui\-port=x\f[B]\f[R] Changes Web UI port to x
|
||||
(default: 8080).
|
||||
\f[B]\f[CB]--webui-port=x\f[B]\f[R] Changes Web UI port to x (default:
|
||||
8080).
|
||||
.SH BUGS
|
||||
If you find a bug, please report it at https://bugs.qbittorrent.org
|
||||
.SH AUTHORS
|
||||
Christophe Dumez \c
|
||||
.MT chris@qbittorrent.org
|
||||
.ME \c
|
||||
\&.
|
||||
Christophe Dumez <chris@qbittorrent.org>.
|
||||
|
||||
@@ -1,38 +1,35 @@
|
||||
.\" Automatically generated by Pandoc 3.4
|
||||
.\" Automatically generated by Pandoc 3.1.7
|
||||
.\"
|
||||
.TH "QBITTORRENT" "1" "January 16th 2010" "Bittorrent client written in C++ / Qt"
|
||||
.TH "QBITTORRENT" "1" "January 16th 2010" "Bittorrent client written in C++ / Qt" ""
|
||||
.SH NAME
|
||||
qBittorrent \- a Bittorrent client written in C++ / Qt
|
||||
qBittorrent - a Bittorrent client written in C++ / Qt
|
||||
.SH SYNOPSIS
|
||||
\f[B]qbittorrent\f[R]
|
||||
\f[CR][\-\-no\-splash] [\-\-webui\-port=x] [TORRENT_FILE | URL]...\f[R]
|
||||
\f[CR][--no-splash] [--webui-port=x] [TORRENT_FILE | URL]...\f[R]
|
||||
.PP
|
||||
\f[B]qbittorrent\f[R] \f[CR]\-\-help\f[R]
|
||||
\f[B]qbittorrent\f[R] \f[CR]--help\f[R]
|
||||
.PP
|
||||
\f[B]qbittorrent\f[R] \f[CR]\-\-version\f[R]
|
||||
\f[B]qbittorrent\f[R] \f[CR]--version\f[R]
|
||||
.SH DESCRIPTION
|
||||
\f[B]qBittorrent\f[R] is an advanced Bittorrent client written in C++ /
|
||||
Qt, using the \f[B]libtorrent\-rasterbar\f[R] library by Arvid Norberg.
|
||||
Qt, using the \f[B]libtorrent-rasterbar\f[R] library by Arvid Norberg.
|
||||
qBittorrent is similar to uTorrent.
|
||||
qBittorrent is fast, stable, light, it supports unicode and it provides
|
||||
a good integrated search engine.
|
||||
It also comes with UPnP port forwarding / NAT\-PMP, encryption (Vuze
|
||||
It also comes with UPnP port forwarding / NAT-PMP, encryption (Vuze
|
||||
compatible), FAST extension (mainline) and PeX support (utorrent
|
||||
compatible).
|
||||
.SH OPTIONS
|
||||
\f[B]\f[CB]\-\-help\f[B]\f[R] Prints the command line options.
|
||||
\f[B]\f[CB]--help\f[B]\f[R] Prints the command line options.
|
||||
.PP
|
||||
\f[B]\f[CB]\-\-version\f[B]\f[R] Prints qbittorrent program version
|
||||
\f[B]\f[CB]--version\f[B]\f[R] Prints qbittorrent program version
|
||||
number.
|
||||
.PP
|
||||
\f[B]\f[CB]\-\-no\-splash\f[B]\f[R] Disables splash screen on startup.
|
||||
\f[B]\f[CB]--no-splash\f[B]\f[R] Disables splash screen on startup.
|
||||
.PP
|
||||
\f[B]\f[CB]\-\-webui\-port=x\f[B]\f[R] Changes Web UI port to x
|
||||
(default: 8080).
|
||||
\f[B]\f[CB]--webui-port=x\f[B]\f[R] Changes Web UI port to x (default:
|
||||
8080).
|
||||
.SH BUGS
|
||||
If you find a bug, please report it at https://bugs.qbittorrent.org
|
||||
.SH AUTHORS
|
||||
Christophe Dumez \c
|
||||
.MT chris@qbittorrent.org
|
||||
.ME \c
|
||||
\&.
|
||||
Christophe Dumez <chris@qbittorrent.org>.
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
.\" Automatically generated by Pandoc 3.4
|
||||
.\" Automatically generated by Pandoc 3.1.7
|
||||
.\"
|
||||
.TH "QBITTORRENT\-NOX" "1" "16 января 2010" "Клиент сети БитТоррент для командной строки"
|
||||
.TH "QBITTORRENT-NOX" "1" "16 января 2010" "Клиент сети БитТоррент для командной строки" ""
|
||||
.SH НАЗВАНИЕ
|
||||
qBittorrent\-nox \[em] клиент сети БитТоррент для командной строки.
|
||||
qBittorrent-nox \[em] клиент сети БитТоррент для командной строки.
|
||||
.SH АВТОРЫ
|
||||
Christophe Dumez \c
|
||||
.MT chris@qbittorrent.org
|
||||
.ME \c
|
||||
\&.
|
||||
Christophe Dumez <chris@qbittorrent.org>.
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
.\" Automatically generated by Pandoc 3.4
|
||||
.\" Automatically generated by Pandoc 3.1.7
|
||||
.\"
|
||||
.TH "QBITTORRENT" "1" "16 января 2010" "Клиент сети БитТоррент"
|
||||
.TH "QBITTORRENT" "1" "16 января 2010" "Клиент сети БитТоррент" ""
|
||||
.SH НАЗВАНИЕ
|
||||
qBittorrent \[em] клиент сети БитТоррент.
|
||||
.SH АВТОРЫ
|
||||
Christophe Dumez \c
|
||||
.MT chris@qbittorrent.org
|
||||
.ME \c
|
||||
\&.
|
||||
Christophe Dumez <chris@qbittorrent.org>.
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QStringView>
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
|
||||
#include <QMessageBox>
|
||||
@@ -61,7 +60,7 @@ namespace
|
||||
class Option
|
||||
{
|
||||
protected:
|
||||
explicit constexpr Option(const QStringView name, const QChar shortcut = QChar::Null)
|
||||
explicit constexpr Option(const char *name, char shortcut = 0)
|
||||
: m_name {name}
|
||||
, m_shortcut {shortcut}
|
||||
{
|
||||
@@ -69,23 +68,23 @@ namespace
|
||||
|
||||
QString fullParameter() const
|
||||
{
|
||||
return u"--" + m_name.toString();
|
||||
return u"--" + QString::fromLatin1(m_name);
|
||||
}
|
||||
|
||||
QString shortcutParameter() const
|
||||
{
|
||||
return u"-" + m_shortcut;
|
||||
return u"-" + QChar::fromLatin1(m_shortcut);
|
||||
}
|
||||
|
||||
bool hasShortcut() const
|
||||
{
|
||||
return !m_shortcut.isNull();
|
||||
return m_shortcut != 0;
|
||||
}
|
||||
|
||||
QString envVarName() const
|
||||
{
|
||||
return u"QBT_"
|
||||
+ m_name.toString().toUpper().replace(u'-', u'_');
|
||||
+ QString::fromLatin1(m_name).toUpper().replace(u'-', u'_');
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -100,15 +99,15 @@ namespace
|
||||
}
|
||||
|
||||
private:
|
||||
const QStringView m_name;
|
||||
const QChar m_shortcut;
|
||||
const char *m_name = nullptr;
|
||||
const char m_shortcut;
|
||||
};
|
||||
|
||||
// Boolean option.
|
||||
class BoolOption : protected Option
|
||||
{
|
||||
public:
|
||||
explicit constexpr BoolOption(const QStringView name, const QChar shortcut = QChar::Null)
|
||||
explicit constexpr BoolOption(const char *name, char shortcut = 0)
|
||||
: Option {name, shortcut}
|
||||
{
|
||||
}
|
||||
@@ -140,8 +139,8 @@ namespace
|
||||
struct StringOption : protected Option
|
||||
{
|
||||
public:
|
||||
explicit constexpr StringOption(const QStringView name)
|
||||
: Option {name, QChar::Null}
|
||||
explicit constexpr StringOption(const char *name)
|
||||
: Option {name, 0}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -182,7 +181,7 @@ namespace
|
||||
class IntOption : protected StringOption
|
||||
{
|
||||
public:
|
||||
explicit constexpr IntOption(const QStringView name)
|
||||
explicit constexpr IntOption(const char *name)
|
||||
: StringOption {name}
|
||||
{
|
||||
}
|
||||
@@ -230,8 +229,8 @@ namespace
|
||||
class TriStateBoolOption : protected Option
|
||||
{
|
||||
public:
|
||||
constexpr TriStateBoolOption(const QStringView name, const bool defaultValue)
|
||||
: Option {name, QChar::Null}
|
||||
constexpr TriStateBoolOption(const char *name, bool defaultValue)
|
||||
: Option {name, 0}
|
||||
, m_defaultValue(defaultValue)
|
||||
{
|
||||
}
|
||||
@@ -300,32 +299,31 @@ namespace
|
||||
return arg.section(u'=', 0, 0) == option.fullParameter();
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_defaultValue = false;
|
||||
bool m_defaultValue;
|
||||
};
|
||||
|
||||
constexpr const BoolOption SHOW_HELP_OPTION {u"help", u'h'};
|
||||
constexpr const BoolOption SHOW_HELP_OPTION {"help", 'h'};
|
||||
#if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
|
||||
constexpr const BoolOption SHOW_VERSION_OPTION {u"version", u'v'};
|
||||
constexpr const BoolOption SHOW_VERSION_OPTION {"version", 'v'};
|
||||
#endif
|
||||
constexpr const BoolOption CONFIRM_LEGAL_NOTICE {u"confirm-legal-notice"};
|
||||
constexpr const BoolOption CONFIRM_LEGAL_NOTICE {"confirm-legal-notice"};
|
||||
#if defined(DISABLE_GUI) && !defined(Q_OS_WIN)
|
||||
constexpr const BoolOption DAEMON_OPTION {u"daemon", u'd'};
|
||||
constexpr const BoolOption DAEMON_OPTION {"daemon", 'd'};
|
||||
#else
|
||||
constexpr const BoolOption NO_SPLASH_OPTION {u"no-splash"};
|
||||
constexpr const BoolOption NO_SPLASH_OPTION {"no-splash"};
|
||||
#endif
|
||||
constexpr const IntOption WEBUI_PORT_OPTION {u"webui-port"};
|
||||
constexpr const IntOption TORRENTING_PORT_OPTION {u"torrenting-port"};
|
||||
constexpr const StringOption PROFILE_OPTION {u"profile"};
|
||||
constexpr const StringOption CONFIGURATION_OPTION {u"configuration"};
|
||||
constexpr const BoolOption RELATIVE_FASTRESUME {u"relative-fastresume"};
|
||||
constexpr const StringOption SAVE_PATH_OPTION {u"save-path"};
|
||||
constexpr const TriStateBoolOption STOPPED_OPTION {u"add-stopped", true};
|
||||
constexpr const BoolOption SKIP_HASH_CHECK_OPTION {u"skip-hash-check"};
|
||||
constexpr const StringOption CATEGORY_OPTION {u"category"};
|
||||
constexpr const BoolOption SEQUENTIAL_OPTION {u"sequential"};
|
||||
constexpr const BoolOption FIRST_AND_LAST_OPTION {u"first-and-last"};
|
||||
constexpr const TriStateBoolOption SKIP_DIALOG_OPTION {u"skip-dialog", true};
|
||||
constexpr const IntOption WEBUI_PORT_OPTION {"webui-port"};
|
||||
constexpr const IntOption TORRENTING_PORT_OPTION {"torrenting-port"};
|
||||
constexpr const StringOption PROFILE_OPTION {"profile"};
|
||||
constexpr const StringOption CONFIGURATION_OPTION {"configuration"};
|
||||
constexpr const BoolOption RELATIVE_FASTRESUME {"relative-fastresume"};
|
||||
constexpr const StringOption SAVE_PATH_OPTION {"save-path"};
|
||||
constexpr const TriStateBoolOption STOPPED_OPTION {"add-stopped", true};
|
||||
constexpr const BoolOption SKIP_HASH_CHECK_OPTION {"skip-hash-check"};
|
||||
constexpr const StringOption CATEGORY_OPTION {"category"};
|
||||
constexpr const BoolOption SEQUENTIAL_OPTION {"sequential"};
|
||||
constexpr const BoolOption FIRST_AND_LAST_OPTION {"first-and-last"};
|
||||
constexpr const TriStateBoolOption SKIP_DIALOG_OPTION {"skip-dialog", true};
|
||||
}
|
||||
|
||||
QBtCommandLineParameters::QBtCommandLineParameters(const QProcessEnvironment &env)
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QList>
|
||||
#include <QTextStream>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
#include <QFileInfo>
|
||||
#include <QLocalServer>
|
||||
@@ -91,7 +90,7 @@ namespace QtLP_Private
|
||||
#endif
|
||||
}
|
||||
|
||||
const QByteArray ACK = QByteArrayLiteral("ack");
|
||||
const char ACK[] = "ack";
|
||||
|
||||
QtLocalPeer::QtLocalPeer(const QString &path, QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -170,7 +169,7 @@ bool QtLocalPeer::sendMessage(const QString &message, const int timeout)
|
||||
{
|
||||
res &= socket.waitForReadyRead(timeout); // wait for ack
|
||||
if (res)
|
||||
res &= (socket.read(ACK.size()) == ACK);
|
||||
res &= (socket.read(qstrlen(ACK)) == ACK);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -221,7 +220,7 @@ void QtLocalPeer::receiveConnection()
|
||||
return;
|
||||
}
|
||||
QString message(QString::fromUtf8(uMsg));
|
||||
socket->write(ACK);
|
||||
socket->write(ACK, qstrlen(ACK));
|
||||
socket->waitForBytesWritten(1000);
|
||||
socket->waitForDisconnected(1000); // make sure client reads ack
|
||||
delete socket;
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
#include <QFile>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
namespace QtLP_Private
|
||||
@@ -105,7 +105,7 @@ namespace QtLP_Private
|
||||
|
||||
Qt::HANDLE m_writeMutex = nullptr;
|
||||
Qt::HANDLE m_readMutex = nullptr;
|
||||
QList<Qt::HANDLE> m_readMutexes;
|
||||
QVector<Qt::HANDLE> m_readMutexes;
|
||||
QString m_mutexName;
|
||||
#endif
|
||||
|
||||
|
||||
1096
src/base/3rdparty/expected.hpp
vendored
1096
src/base/3rdparty/expected.hpp
vendored
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,6 @@ add_library(qbt_base STATIC
|
||||
asyncfilestorage.h
|
||||
bittorrent/abstractfilestorage.h
|
||||
bittorrent/addtorrentparams.h
|
||||
bittorrent/announcetimepoint.h
|
||||
bittorrent/bandwidthscheduler.h
|
||||
bittorrent/bencoderesumedatastorage.h
|
||||
bittorrent/cachestatus.h
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include <QDir>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/exceptions.h"
|
||||
#include "base/path.h"
|
||||
@@ -71,7 +71,7 @@ void BitTorrent::AbstractFileStorage::renameFolder(const Path &oldFolderPath, co
|
||||
if (newFolderPath.isAbsolute())
|
||||
throw RuntimeError(tr("Absolute path isn't allowed: '%1'.").arg(newFolderPath.toString()));
|
||||
|
||||
QList<int> renamingFileIndexes;
|
||||
QVector<int> renamingFileIndexes;
|
||||
renamingFileIndexes.reserve(filesCount());
|
||||
|
||||
for (int i = 0; i < filesCount(); ++i)
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/path.h"
|
||||
#include "base/tagset.h"
|
||||
@@ -62,7 +62,7 @@ namespace BitTorrent
|
||||
std::optional<bool> addStopped;
|
||||
std::optional<Torrent::StopCondition> stopCondition;
|
||||
PathList filePaths; // used if TorrentInfo is set
|
||||
QList<DownloadPriority> filePriorities; // used if TorrentInfo is set
|
||||
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
|
||||
bool skipChecking = false;
|
||||
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
|
||||
std::optional<bool> useAutoTMM;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
using AnnounceTimePoint = std::chrono::high_resolution_clock::time_point;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ bool BandwidthScheduler::isTimeForAlternative() const
|
||||
alternative = !alternative;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace BitTorrent
|
||||
|
||||
void store(const TorrentID &id, const LoadTorrentParams &resumeData) const;
|
||||
void remove(const TorrentID &id) const;
|
||||
void storeQueue(const QList<TorrentID> &queue) const;
|
||||
void storeQueue(const QVector<TorrentID> &queue) const;
|
||||
|
||||
private:
|
||||
const Path m_resumeDataDir;
|
||||
@@ -131,11 +131,10 @@ BitTorrent::BencodeResumeDataStorage::BencodeResumeDataStorage(const Path &path,
|
||||
|
||||
m_asyncWorker->moveToThread(m_ioThread.get());
|
||||
connect(m_ioThread.get(), &QThread::finished, m_asyncWorker, &QObject::deleteLater);
|
||||
m_ioThread->setObjectName("BencodeResumeDataStorage m_ioThread");
|
||||
m_ioThread->start();
|
||||
}
|
||||
|
||||
QList<BitTorrent::TorrentID> BitTorrent::BencodeResumeDataStorage::registeredTorrents() const
|
||||
QVector<BitTorrent::TorrentID> BitTorrent::BencodeResumeDataStorage::registeredTorrents() const
|
||||
{
|
||||
return m_registeredTorrents;
|
||||
}
|
||||
@@ -293,6 +292,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
|
||||
|
||||
if (!metadata.isEmpty())
|
||||
{
|
||||
const auto *pref = Preferences::instance();
|
||||
const lt::bdecode_node torentInfoRoot = lt::bdecode(metadata, ec
|
||||
, nullptr, pref->getBdecodeDepthLimit(), pref->getBdecodeTokenLimit());
|
||||
if (ec)
|
||||
@@ -354,7 +354,7 @@ void BitTorrent::BencodeResumeDataStorage::remove(const TorrentID &id) const
|
||||
});
|
||||
}
|
||||
|
||||
void BitTorrent::BencodeResumeDataStorage::storeQueue(const QList<TorrentID> &queue) const
|
||||
void BitTorrent::BencodeResumeDataStorage::storeQueue(const QVector<TorrentID> &queue) const
|
||||
{
|
||||
QMetaObject::invokeMethod(m_asyncWorker, [this, queue]()
|
||||
{
|
||||
@@ -460,7 +460,7 @@ void BitTorrent::BencodeResumeDataStorage::Worker::remove(const TorrentID &id) c
|
||||
Utils::Fs::removeFile(m_resumeDataDir / torrentFilename);
|
||||
}
|
||||
|
||||
void BitTorrent::BencodeResumeDataStorage::Worker::storeQueue(const QList<TorrentID> &queue) const
|
||||
void BitTorrent::BencodeResumeDataStorage::Worker::storeQueue(const QVector<TorrentID> &queue) const
|
||||
{
|
||||
QByteArray data;
|
||||
data.reserve(((BitTorrent::TorrentID::length() * 2) + 1) * queue.size());
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDir>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/pathfwd.h"
|
||||
#include "base/utils/thread.h"
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "resumedatastorage.h"
|
||||
|
||||
class QByteArray;
|
||||
class QThread;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
@@ -48,18 +49,18 @@ namespace BitTorrent
|
||||
public:
|
||||
explicit BencodeResumeDataStorage(const Path &path, QObject *parent = nullptr);
|
||||
|
||||
QList<TorrentID> registeredTorrents() const override;
|
||||
QVector<TorrentID> registeredTorrents() const override;
|
||||
LoadResumeDataResult load(const TorrentID &id) const override;
|
||||
void store(const TorrentID &id, const LoadTorrentParams &resumeData) const override;
|
||||
void remove(const TorrentID &id) const override;
|
||||
void storeQueue(const QList<TorrentID> &queue) const override;
|
||||
void storeQueue(const QVector<TorrentID> &queue) const override;
|
||||
|
||||
private:
|
||||
void doLoadAll() const override;
|
||||
void loadQueue(const Path &queueFilename);
|
||||
LoadResumeDataResult loadTorrentResumeData(const QByteArray &data, const QByteArray &metadata) const;
|
||||
|
||||
QList<TorrentID> m_registeredTorrents;
|
||||
QVector<TorrentID> m_registeredTorrents;
|
||||
Utils::Thread::UniquePtr m_ioThread;
|
||||
|
||||
class Worker;
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QMutex>
|
||||
#include <QSet>
|
||||
#include <QSqlDatabase>
|
||||
@@ -49,6 +48,7 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlRecord>
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "base/exceptions.h"
|
||||
@@ -107,11 +107,11 @@ namespace
|
||||
class StoreQueueJob final : public Job
|
||||
{
|
||||
public:
|
||||
explicit StoreQueueJob(const QList<TorrentID> &queue);
|
||||
explicit StoreQueueJob(const QVector<TorrentID> &queue);
|
||||
void perform(QSqlDatabase db) override;
|
||||
|
||||
private:
|
||||
const QList<TorrentID> m_queue;
|
||||
const QVector<TorrentID> m_queue;
|
||||
};
|
||||
|
||||
struct Column
|
||||
@@ -120,35 +120,36 @@ namespace
|
||||
QString placeholder;
|
||||
};
|
||||
|
||||
Column makeColumn(const QString &columnName)
|
||||
Column makeColumn(const char *columnName)
|
||||
{
|
||||
return {.name = columnName, .placeholder = (u':' + columnName)};
|
||||
const QString name = QString::fromLatin1(columnName);
|
||||
return {.name = name, .placeholder = (u':' + name)};
|
||||
}
|
||||
|
||||
const Column DB_COLUMN_ID = makeColumn(u"id"_s);
|
||||
const Column DB_COLUMN_TORRENT_ID = makeColumn(u"torrent_id"_s);
|
||||
const Column DB_COLUMN_QUEUE_POSITION = makeColumn(u"queue_position"_s);
|
||||
const Column DB_COLUMN_NAME = makeColumn(u"name"_s);
|
||||
const Column DB_COLUMN_CATEGORY = makeColumn(u"category"_s);
|
||||
const Column DB_COLUMN_TAGS = makeColumn(u"tags"_s);
|
||||
const Column DB_COLUMN_TARGET_SAVE_PATH = makeColumn(u"target_save_path"_s);
|
||||
const Column DB_COLUMN_DOWNLOAD_PATH = makeColumn(u"download_path"_s);
|
||||
const Column DB_COLUMN_CONTENT_LAYOUT = makeColumn(u"content_layout"_s);
|
||||
const Column DB_COLUMN_RATIO_LIMIT = makeColumn(u"ratio_limit"_s);
|
||||
const Column DB_COLUMN_SEEDING_TIME_LIMIT = makeColumn(u"seeding_time_limit"_s);
|
||||
const Column DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT = makeColumn(u"inactive_seeding_time_limit"_s);
|
||||
const Column DB_COLUMN_SHARE_LIMIT_ACTION = makeColumn(u"share_limit_action"_s);
|
||||
const Column DB_COLUMN_HAS_OUTER_PIECES_PRIORITY = makeColumn(u"has_outer_pieces_priority"_s);
|
||||
const Column DB_COLUMN_HAS_SEED_STATUS = makeColumn(u"has_seed_status"_s);
|
||||
const Column DB_COLUMN_OPERATING_MODE = makeColumn(u"operating_mode"_s);
|
||||
const Column DB_COLUMN_STOPPED = makeColumn(u"stopped"_s);
|
||||
const Column DB_COLUMN_STOP_CONDITION = makeColumn(u"stop_condition"_s);
|
||||
const Column DB_COLUMN_SSL_CERTIFICATE = makeColumn(u"ssl_certificate"_s);
|
||||
const Column DB_COLUMN_SSL_PRIVATE_KEY = makeColumn(u"ssl_private_key"_s);
|
||||
const Column DB_COLUMN_SSL_DH_PARAMS = makeColumn(u"ssl_dh_params"_s);
|
||||
const Column DB_COLUMN_RESUMEDATA = makeColumn(u"libtorrent_resume_data"_s);
|
||||
const Column DB_COLUMN_METADATA = makeColumn(u"metadata"_s);
|
||||
const Column DB_COLUMN_VALUE = makeColumn(u"value"_s);
|
||||
const Column DB_COLUMN_ID = makeColumn("id");
|
||||
const Column DB_COLUMN_TORRENT_ID = makeColumn("torrent_id");
|
||||
const Column DB_COLUMN_QUEUE_POSITION = makeColumn("queue_position");
|
||||
const Column DB_COLUMN_NAME = makeColumn("name");
|
||||
const Column DB_COLUMN_CATEGORY = makeColumn("category");
|
||||
const Column DB_COLUMN_TAGS = makeColumn("tags");
|
||||
const Column DB_COLUMN_TARGET_SAVE_PATH = makeColumn("target_save_path");
|
||||
const Column DB_COLUMN_DOWNLOAD_PATH = makeColumn("download_path");
|
||||
const Column DB_COLUMN_CONTENT_LAYOUT = makeColumn("content_layout");
|
||||
const Column DB_COLUMN_RATIO_LIMIT = makeColumn("ratio_limit");
|
||||
const Column DB_COLUMN_SEEDING_TIME_LIMIT = makeColumn("seeding_time_limit");
|
||||
const Column DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT = makeColumn("inactive_seeding_time_limit");
|
||||
const Column DB_COLUMN_SHARE_LIMIT_ACTION = makeColumn("share_limit_action");
|
||||
const Column DB_COLUMN_HAS_OUTER_PIECES_PRIORITY = makeColumn("has_outer_pieces_priority");
|
||||
const Column DB_COLUMN_HAS_SEED_STATUS = makeColumn("has_seed_status");
|
||||
const Column DB_COLUMN_OPERATING_MODE = makeColumn("operating_mode");
|
||||
const Column DB_COLUMN_STOPPED = makeColumn("stopped");
|
||||
const Column DB_COLUMN_STOP_CONDITION = makeColumn("stop_condition");
|
||||
const Column DB_COLUMN_SSL_CERTIFICATE = makeColumn("ssl_certificate");
|
||||
const Column DB_COLUMN_SSL_PRIVATE_KEY = makeColumn("ssl_private_key");
|
||||
const Column DB_COLUMN_SSL_DH_PARAMS = makeColumn("ssl_dh_params");
|
||||
const Column DB_COLUMN_RESUMEDATA = makeColumn("libtorrent_resume_data");
|
||||
const Column DB_COLUMN_METADATA = makeColumn("metadata");
|
||||
const Column DB_COLUMN_VALUE = makeColumn("value");
|
||||
|
||||
template <typename LTStr>
|
||||
QString fromLTString(const LTStr &str)
|
||||
@@ -167,7 +168,7 @@ namespace
|
||||
return u"CREATE TABLE %1 (%2)"_s.arg(quoted(tableName), items.join(u','));
|
||||
}
|
||||
|
||||
std::pair<QString, QString> joinColumns(const QList<Column> &columns)
|
||||
std::pair<QString, QString> joinColumns(const QVector<Column> &columns)
|
||||
{
|
||||
int namesSize = columns.size();
|
||||
int valuesSize = columns.size();
|
||||
@@ -192,30 +193,30 @@ namespace
|
||||
return std::make_pair(names, values);
|
||||
}
|
||||
|
||||
QString makeInsertStatement(const QString &tableName, const QList<Column> &columns)
|
||||
QString makeInsertStatement(const QString &tableName, const QVector<Column> &columns)
|
||||
{
|
||||
const auto [names, values] = joinColumns(columns);
|
||||
return u"INSERT INTO %1 (%2) VALUES (%3)"_s
|
||||
.arg(quoted(tableName), names, values);
|
||||
}
|
||||
|
||||
QString makeUpdateStatement(const QString &tableName, const QList<Column> &columns)
|
||||
QString makeUpdateStatement(const QString &tableName, const QVector<Column> &columns)
|
||||
{
|
||||
const auto [names, values] = joinColumns(columns);
|
||||
return u"UPDATE %1 SET (%2) = (%3)"_s
|
||||
.arg(quoted(tableName), names, values);
|
||||
}
|
||||
|
||||
QString makeOnConflictUpdateStatement(const Column &constraint, const QList<Column> &columns)
|
||||
QString makeOnConflictUpdateStatement(const Column &constraint, const QVector<Column> &columns)
|
||||
{
|
||||
const auto [names, values] = joinColumns(columns);
|
||||
return u" ON CONFLICT (%1) DO UPDATE SET (%2) = (%3)"_s
|
||||
.arg(quoted(constraint.name), names, values);
|
||||
}
|
||||
|
||||
QString makeColumnDefinition(const Column &column, const QString &definition)
|
||||
QString makeColumnDefinition(const Column &column, const char *definition)
|
||||
{
|
||||
return u"%1 %2"_s.arg(quoted(column.name), definition);
|
||||
return u"%1 %2"_s.arg(quoted(column.name), QString::fromLatin1(definition));
|
||||
}
|
||||
|
||||
LoadTorrentParams parseQueryResultRow(const QSqlQuery &query)
|
||||
@@ -307,7 +308,7 @@ namespace BitTorrent
|
||||
|
||||
void store(const TorrentID &id, const LoadTorrentParams &resumeData);
|
||||
void remove(const TorrentID &id);
|
||||
void storeQueue(const QList<TorrentID> &queue);
|
||||
void storeQueue(const QVector<TorrentID> &queue);
|
||||
|
||||
private:
|
||||
void addJob(std::unique_ptr<Job> job);
|
||||
@@ -324,6 +325,7 @@ namespace BitTorrent
|
||||
|
||||
BitTorrent::DBResumeDataStorage::DBResumeDataStorage(const Path &dbPath, QObject *parent)
|
||||
: ResumeDataStorage(dbPath, parent)
|
||||
, m_ioThread {new QThread}
|
||||
{
|
||||
const bool needCreateDB = !dbPath.exists();
|
||||
|
||||
@@ -354,7 +356,7 @@ BitTorrent::DBResumeDataStorage::~DBResumeDataStorage()
|
||||
QSqlDatabase::removeDatabase(DB_CONNECTION_NAME);
|
||||
}
|
||||
|
||||
QList<BitTorrent::TorrentID> BitTorrent::DBResumeDataStorage::registeredTorrents() const
|
||||
QVector<BitTorrent::TorrentID> BitTorrent::DBResumeDataStorage::registeredTorrents() const
|
||||
{
|
||||
const auto selectTorrentIDStatement = u"SELECT %1 FROM %2 ORDER BY %3;"_s
|
||||
.arg(quoted(DB_COLUMN_TORRENT_ID.name), quoted(DB_TABLE_TORRENTS), quoted(DB_COLUMN_QUEUE_POSITION.name));
|
||||
@@ -365,7 +367,7 @@ QList<BitTorrent::TorrentID> BitTorrent::DBResumeDataStorage::registeredTorrents
|
||||
if (!query.exec(selectTorrentIDStatement))
|
||||
throw RuntimeError(query.lastError().text());
|
||||
|
||||
QList<TorrentID> registeredTorrents;
|
||||
QVector<TorrentID> registeredTorrents;
|
||||
registeredTorrents.reserve(query.size());
|
||||
while (query.next())
|
||||
registeredTorrents.append(BitTorrent::TorrentID::fromString(query.value(0).toString()));
|
||||
@@ -411,7 +413,7 @@ void BitTorrent::DBResumeDataStorage::remove(const BitTorrent::TorrentID &id) co
|
||||
m_asyncWorker->remove(id);
|
||||
}
|
||||
|
||||
void BitTorrent::DBResumeDataStorage::storeQueue(const QList<TorrentID> &queue) const
|
||||
void BitTorrent::DBResumeDataStorage::storeQueue(const QVector<TorrentID> &queue) const
|
||||
{
|
||||
m_asyncWorker->storeQueue(queue);
|
||||
}
|
||||
@@ -436,7 +438,7 @@ void BitTorrent::DBResumeDataStorage::doLoadAll() const
|
||||
if (!query.exec(selectTorrentIDStatement))
|
||||
throw RuntimeError(query.lastError().text());
|
||||
|
||||
QList<TorrentID> registeredTorrents;
|
||||
QVector<TorrentID> registeredTorrents;
|
||||
registeredTorrents.reserve(query.size());
|
||||
while (query.next())
|
||||
registeredTorrents.append(TorrentID::fromString(query.value(0).toString()));
|
||||
@@ -510,9 +512,9 @@ void BitTorrent::DBResumeDataStorage::createDB() const
|
||||
try
|
||||
{
|
||||
const QStringList tableMetaItems = {
|
||||
makeColumnDefinition(DB_COLUMN_ID, u"INTEGER PRIMARY KEY"_s),
|
||||
makeColumnDefinition(DB_COLUMN_NAME, u"TEXT NOT NULL UNIQUE"_s),
|
||||
makeColumnDefinition(DB_COLUMN_VALUE, u"BLOB"_s)
|
||||
makeColumnDefinition(DB_COLUMN_ID, "INTEGER PRIMARY KEY"),
|
||||
makeColumnDefinition(DB_COLUMN_NAME, "TEXT NOT NULL UNIQUE"),
|
||||
makeColumnDefinition(DB_COLUMN_VALUE, "BLOB")
|
||||
};
|
||||
const QString createTableMetaQuery = makeCreateTableStatement(DB_TABLE_META, tableMetaItems);
|
||||
if (!query.exec(createTableMetaQuery))
|
||||
@@ -529,29 +531,29 @@ void BitTorrent::DBResumeDataStorage::createDB() const
|
||||
throw RuntimeError(query.lastError().text());
|
||||
|
||||
const QStringList tableTorrentsItems = {
|
||||
makeColumnDefinition(DB_COLUMN_ID, u"INTEGER PRIMARY KEY"_s),
|
||||
makeColumnDefinition(DB_COLUMN_TORRENT_ID, u"BLOB NOT NULL UNIQUE"_s),
|
||||
makeColumnDefinition(DB_COLUMN_QUEUE_POSITION, u"INTEGER NOT NULL DEFAULT -1"_s),
|
||||
makeColumnDefinition(DB_COLUMN_NAME, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_CATEGORY, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_TAGS, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_TARGET_SAVE_PATH, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_DOWNLOAD_PATH, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_CONTENT_LAYOUT, u"TEXT NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_RATIO_LIMIT, u"INTEGER NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_SEEDING_TIME_LIMIT, u"INTEGER NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, u"INTEGER NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_SHARE_LIMIT_ACTION, u"TEXT NOT NULL DEFAULT `Default`"_s),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY, u"INTEGER NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_SEED_STATUS, u"INTEGER NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_OPERATING_MODE, u"TEXT NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_STOPPED, u"INTEGER NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_STOP_CONDITION, u"TEXT NOT NULL DEFAULT `None`"_s),
|
||||
makeColumnDefinition(DB_COLUMN_SSL_CERTIFICATE, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_SSL_PRIVATE_KEY, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_SSL_DH_PARAMS, u"TEXT"_s),
|
||||
makeColumnDefinition(DB_COLUMN_RESUMEDATA, u"BLOB NOT NULL"_s),
|
||||
makeColumnDefinition(DB_COLUMN_METADATA, u"BLOB"_s)
|
||||
makeColumnDefinition(DB_COLUMN_ID, "INTEGER PRIMARY KEY"),
|
||||
makeColumnDefinition(DB_COLUMN_TORRENT_ID, "BLOB NOT NULL UNIQUE"),
|
||||
makeColumnDefinition(DB_COLUMN_QUEUE_POSITION, "INTEGER NOT NULL DEFAULT -1"),
|
||||
makeColumnDefinition(DB_COLUMN_NAME, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_CATEGORY, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_TAGS, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_TARGET_SAVE_PATH, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_DOWNLOAD_PATH, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_CONTENT_LAYOUT, "TEXT NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_RATIO_LIMIT, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_SHARE_LIMIT_ACTION, "TEXT NOT NULL DEFAULT `Default`"),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_SEED_STATUS, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_OPERATING_MODE, "TEXT NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_STOPPED, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_STOP_CONDITION, "TEXT NOT NULL DEFAULT `None`"),
|
||||
makeColumnDefinition(DB_COLUMN_SSL_CERTIFICATE, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_SSL_PRIVATE_KEY, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_SSL_DH_PARAMS, "TEXT"),
|
||||
makeColumnDefinition(DB_COLUMN_RESUMEDATA, "BLOB NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_METADATA, "BLOB")
|
||||
};
|
||||
const QString createTableTorrentsQuery = makeCreateTableStatement(DB_TABLE_TORRENTS, tableTorrentsItems);
|
||||
if (!query.exec(createTableTorrentsQuery))
|
||||
@@ -589,7 +591,7 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
|
||||
|
||||
try
|
||||
{
|
||||
const auto addColumn = [&query](const QString &table, const Column &column, const QString &definition)
|
||||
const auto addColumn = [&query](const QString &table, const Column &column, const char *definition)
|
||||
{
|
||||
const auto testQuery = u"SELECT COUNT(%1) FROM %2;"_s.arg(quoted(column.name), quoted(table));
|
||||
if (query.exec(testQuery))
|
||||
@@ -601,10 +603,10 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
|
||||
};
|
||||
|
||||
if (fromVersion <= 1)
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_DOWNLOAD_PATH, u"TEXT"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_DOWNLOAD_PATH, "TEXT");
|
||||
|
||||
if (fromVersion <= 2)
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_STOP_CONDITION, u"TEXT NOT NULL DEFAULT `None`"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_STOP_CONDITION, "TEXT NOT NULL DEFAULT `None`");
|
||||
|
||||
if (fromVersion <= 3)
|
||||
{
|
||||
@@ -616,17 +618,17 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
|
||||
}
|
||||
|
||||
if (fromVersion <= 4)
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, u"INTEGER NOT NULL DEFAULT -2"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, "INTEGER NOT NULL DEFAULT -2");
|
||||
|
||||
if (fromVersion <= 5)
|
||||
{
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_CERTIFICATE, u"TEXT"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_PRIVATE_KEY, u"TEXT"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_DH_PARAMS, u"TEXT"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_CERTIFICATE, "TEXT");
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_PRIVATE_KEY, "TEXT");
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_DH_PARAMS, "TEXT");
|
||||
}
|
||||
|
||||
if (fromVersion <= 6)
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SHARE_LIMIT_ACTION, u"TEXT NOT NULL DEFAULT `Default`"_s);
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SHARE_LIMIT_ACTION, "TEXT NOT NULL DEFAULT `Default`");
|
||||
|
||||
if (fromVersion == 7)
|
||||
{
|
||||
@@ -769,7 +771,7 @@ void BitTorrent::DBResumeDataStorage::Worker::remove(const TorrentID &id)
|
||||
addJob(std::make_unique<RemoveJob>(id));
|
||||
}
|
||||
|
||||
void BitTorrent::DBResumeDataStorage::Worker::storeQueue(const QList<TorrentID> &queue)
|
||||
void BitTorrent::DBResumeDataStorage::Worker::storeQueue(const QVector<TorrentID> &queue)
|
||||
{
|
||||
addJob(std::make_unique<StoreQueueJob>(queue));
|
||||
}
|
||||
@@ -819,7 +821,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
QList<Column> columns {
|
||||
QVector<Column> columns {
|
||||
DB_COLUMN_TORRENT_ID,
|
||||
DB_COLUMN_NAME,
|
||||
DB_COLUMN_CATEGORY,
|
||||
@@ -951,7 +953,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
StoreQueueJob::StoreQueueJob(const QList<TorrentID> &queue)
|
||||
StoreQueueJob::StoreQueueJob(const QVector<TorrentID> &queue)
|
||||
: m_queue {queue}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "base/utils/thread.h"
|
||||
#include "resumedatastorage.h"
|
||||
|
||||
class QThread;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class DBResumeDataStorage final : public ResumeDataStorage
|
||||
@@ -45,12 +47,12 @@ namespace BitTorrent
|
||||
explicit DBResumeDataStorage(const Path &dbPath, QObject *parent = nullptr);
|
||||
~DBResumeDataStorage() override;
|
||||
|
||||
QList<TorrentID> registeredTorrents() const override;
|
||||
QVector<TorrentID> registeredTorrents() const override;
|
||||
LoadResumeDataResult load(const TorrentID &id) const override;
|
||||
|
||||
void store(const TorrentID &id, const LoadTorrentParams &resumeData) const override;
|
||||
void remove(const TorrentID &id) const override;
|
||||
void storeQueue(const QList<TorrentID> &queue) const override;
|
||||
void storeQueue(const QVector<TorrentID> &queue) const override;
|
||||
|
||||
private:
|
||||
void doLoadAll() const override;
|
||||
@@ -59,6 +61,8 @@ namespace BitTorrent
|
||||
void updateDB(int fromVersion) const;
|
||||
void enableWALMode() const;
|
||||
|
||||
Utils::Thread::UniquePtr m_ioThread;
|
||||
|
||||
class Worker;
|
||||
Worker *m_asyncWorker = nullptr;
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ int FilterParserThread::parseDATFilterFile()
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
std::vector<char> buffer(BUFFER_SIZE, 0); // seems a bit faster than QList
|
||||
std::vector<char> buffer(BUFFER_SIZE, 0); // seems a bit faster than QVector
|
||||
qint64 bytesRead = 0;
|
||||
int offset = 0;
|
||||
int start = 0;
|
||||
@@ -297,7 +297,7 @@ int FilterParserThread::parseP2PFilterFile()
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
std::vector<char> buffer(BUFFER_SIZE, 0); // seems a bit faster than QList
|
||||
std::vector<char> buffer(BUFFER_SIZE, 0); // seems a bit faster than QVector
|
||||
qint64 bytesRead = 0;
|
||||
int offset = 0;
|
||||
int start = 0;
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaObject>
|
||||
#include <QMutexLocker>
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
|
||||
const int TORRENTIDLIST_TYPEID = qRegisterMetaType<QList<BitTorrent::TorrentID>>();
|
||||
const int TORRENTIDLIST_TYPEID = qRegisterMetaType<QVector<BitTorrent::TorrentID>>();
|
||||
|
||||
BitTorrent::ResumeDataStorage::ResumeDataStorage(const Path &path, QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -56,7 +56,6 @@ void BitTorrent::ResumeDataStorage::loadAll() const
|
||||
{
|
||||
doLoadAll();
|
||||
});
|
||||
loadingThread->setObjectName("ResumeDataStorage::loadAll loadingThread");
|
||||
connect(loadingThread, &QThread::finished, loadingThread, &QObject::deleteLater);
|
||||
loadingThread->start();
|
||||
}
|
||||
|
||||
@@ -58,17 +58,17 @@ namespace BitTorrent
|
||||
|
||||
Path path() const;
|
||||
|
||||
virtual QList<TorrentID> registeredTorrents() const = 0;
|
||||
virtual QVector<TorrentID> registeredTorrents() const = 0;
|
||||
virtual LoadResumeDataResult load(const TorrentID &id) const = 0;
|
||||
virtual void store(const TorrentID &id, const LoadTorrentParams &resumeData) const = 0;
|
||||
virtual void remove(const TorrentID &id) const = 0;
|
||||
virtual void storeQueue(const QList<TorrentID> &queue) const = 0;
|
||||
virtual void storeQueue(const QVector<TorrentID> &queue) const = 0;
|
||||
|
||||
void loadAll() const;
|
||||
QList<LoadedResumeData> fetchLoadedResumeData() const;
|
||||
|
||||
signals:
|
||||
void loadStarted(const QList<BitTorrent::TorrentID> &torrents);
|
||||
void loadStarted(const QVector<BitTorrent::TorrentID> &torrents);
|
||||
void loadFinished();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -258,8 +258,6 @@ namespace BitTorrent
|
||||
virtual void setPerformanceWarningEnabled(bool enable) = 0;
|
||||
virtual int saveResumeDataInterval() const = 0;
|
||||
virtual void setSaveResumeDataInterval(int value) = 0;
|
||||
virtual std::chrono::minutes saveStatisticsInterval() const = 0;
|
||||
virtual void setSaveStatisticsInterval(std::chrono::minutes value) = 0;
|
||||
virtual int shutdownTimeout() const = 0;
|
||||
virtual void setShutdownTimeout(int value) = 0;
|
||||
virtual int port() const = 0;
|
||||
@@ -449,7 +447,7 @@ namespace BitTorrent
|
||||
|
||||
virtual Torrent *getTorrent(const TorrentID &id) const = 0;
|
||||
virtual Torrent *findTorrent(const InfoHash &infoHash) const = 0;
|
||||
virtual QList<Torrent *> torrents() const = 0;
|
||||
virtual QVector<Torrent *> torrents() const = 0;
|
||||
virtual qsizetype torrentsCount() const = 0;
|
||||
virtual const SessionStatus &status() const = 0;
|
||||
virtual const CacheStatus &cacheStatus() const = 0;
|
||||
@@ -463,13 +461,10 @@ namespace BitTorrent
|
||||
virtual bool downloadMetadata(const TorrentDescriptor &torrentDescr) = 0;
|
||||
virtual bool cancelDownloadMetadata(const TorrentID &id) = 0;
|
||||
|
||||
virtual void increaseTorrentsQueuePos(const QList<TorrentID> &ids) = 0;
|
||||
virtual void decreaseTorrentsQueuePos(const QList<TorrentID> &ids) = 0;
|
||||
virtual void topTorrentsQueuePos(const QList<TorrentID> &ids) = 0;
|
||||
virtual void bottomTorrentsQueuePos(const QList<TorrentID> &ids) = 0;
|
||||
|
||||
virtual QString lastExternalIPv4Address() const = 0;
|
||||
virtual QString lastExternalIPv6Address() const = 0;
|
||||
virtual void increaseTorrentsQueuePos(const QVector<TorrentID> &ids) = 0;
|
||||
virtual void decreaseTorrentsQueuePos(const QVector<TorrentID> &ids) = 0;
|
||||
virtual void topTorrentsQueuePos(const QVector<TorrentID> &ids) = 0;
|
||||
virtual void bottomTorrentsQueuePos(const QVector<TorrentID> &ids) = 0;
|
||||
|
||||
signals:
|
||||
void startupProgressUpdated(int progress);
|
||||
@@ -500,12 +495,12 @@ namespace BitTorrent
|
||||
void torrentStarted(Torrent *torrent);
|
||||
void torrentSavePathChanged(Torrent *torrent);
|
||||
void torrentSavingModeChanged(Torrent *torrent);
|
||||
void torrentsLoaded(const QList<Torrent *> &torrents);
|
||||
void torrentsUpdated(const QList<Torrent *> &torrents);
|
||||
void torrentsLoaded(const QVector<Torrent *> &torrents);
|
||||
void torrentsUpdated(const QVector<Torrent *> &torrents);
|
||||
void torrentTagAdded(Torrent *torrent, const Tag &tag);
|
||||
void torrentTagRemoved(Torrent *torrent, const Tag &tag);
|
||||
void trackerError(Torrent *torrent, const QString &tracker);
|
||||
void trackersAdded(Torrent *torrent, const QList<TrackerEntry> &trackers);
|
||||
void trackersAdded(Torrent *torrent, const QVector<TrackerEntry> &trackers);
|
||||
void trackersChanged(Torrent *torrent);
|
||||
void trackersRemoved(Torrent *torrent, const QStringList &trackers);
|
||||
void trackerSuccess(Torrent *torrent, const QString &tracker);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "sessionimpl.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <queue>
|
||||
@@ -57,7 +58,6 @@
|
||||
#include <libtorrent/session_status.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDeadlineTimer>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
@@ -72,6 +72,7 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QThreadPool>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
|
||||
@@ -87,7 +88,6 @@
|
||||
#include "base/utils/net.h"
|
||||
#include "base/utils/number.h"
|
||||
#include "base/utils/random.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "base/version.h"
|
||||
#include "bandwidthscheduler.h"
|
||||
#include "bencoderesumedatastorage.h"
|
||||
@@ -107,19 +107,19 @@
|
||||
#include "torrentimpl.h"
|
||||
#include "tracker.h"
|
||||
#include "trackerentry.h"
|
||||
#include "trackerentrystatus.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace BitTorrent;
|
||||
|
||||
const Path CATEGORIES_FILE_NAME {u"categories.json"_s};
|
||||
const int MAX_PROCESSING_RESUMEDATA_COUNT = 50;
|
||||
const int STATISTICS_SAVE_INTERVAL = std::chrono::milliseconds(15min).count();
|
||||
|
||||
namespace
|
||||
{
|
||||
const char PEER_ID[] = "qB";
|
||||
const auto USER_AGENT = QStringLiteral("qBittorrent/" QBT_VERSION_2);
|
||||
const QString DEFAULT_DHT_BOOTSTRAP_NODES = u"dht.libtorrent.org:25401, dht.transmissionbt.com:6881, router.silotis.us:6881"_s;
|
||||
const QString DEFAULT_DHT_BOOTSTRAP_NODES = u"dht.libtorrent.org:25401, dht.transmissionbt.com:6881, router.bittorrent.com:6881, router.utorrent.com:6881, dht.aelitis.com:6881"_s;
|
||||
|
||||
void torrentQueuePositionUp(const lt::torrent_handle &handle)
|
||||
{
|
||||
@@ -225,7 +225,7 @@ namespace
|
||||
{
|
||||
try
|
||||
{
|
||||
return Utils::String::fromLatin1(address.to_string());
|
||||
return QString::fromLatin1(address.to_string().c_str());
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
@@ -299,15 +299,14 @@ namespace
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
case MoveStorageMode::FailIfExist:
|
||||
return lt::move_flags_t::fail_if_exist;
|
||||
case MoveStorageMode::KeepExistingFiles:
|
||||
return lt::move_flags_t::dont_replace;
|
||||
case MoveStorageMode::Overwrite:
|
||||
return lt::move_flags_t::always_replace_files;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,7 +483,6 @@ SessionImpl::SessionImpl(QObject *parent)
|
||||
, m_isBandwidthSchedulerEnabled(BITTORRENT_SESSION_KEY(u"BandwidthSchedulerEnabled"_s), false)
|
||||
, m_isPerformanceWarningEnabled(BITTORRENT_SESSION_KEY(u"PerformanceWarning"_s), false)
|
||||
, m_saveResumeDataInterval(BITTORRENT_SESSION_KEY(u"SaveResumeDataInterval"_s), 60)
|
||||
, m_saveStatisticsInterval(BITTORRENT_SESSION_KEY(u"SaveStatisticsInterval"_s), 15)
|
||||
, m_shutdownTimeout(BITTORRENT_SESSION_KEY(u"ShutdownTimeout"_s), -1)
|
||||
, m_port(BITTORRENT_SESSION_KEY(u"Port"_s), -1)
|
||||
, m_sslEnabled(BITTORRENT_SESSION_KEY(u"SSL/Enabled"_s), false)
|
||||
@@ -539,7 +537,6 @@ SessionImpl::SessionImpl(QObject *parent)
|
||||
{
|
||||
// It is required to perform async access to libtorrent sequentially
|
||||
m_asyncWorker->setMaxThreadCount(1);
|
||||
m_asyncWorker->setObjectName("SessionImpl m_asyncWorker");
|
||||
|
||||
if (port() < 0)
|
||||
m_port = Utils::Random::rand(1024, 65535);
|
||||
@@ -604,7 +601,6 @@ SessionImpl::SessionImpl(QObject *parent)
|
||||
connect(m_ioThread.get(), &QThread::finished, m_torrentContentRemover, &QObject::deleteLater);
|
||||
connect(m_torrentContentRemover, &TorrentContentRemover::jobFinished, this, &SessionImpl::torrentContentRemovingFinished);
|
||||
|
||||
m_ioThread->setObjectName("SessionImpl m_ioThread");
|
||||
m_ioThread->start();
|
||||
|
||||
initMetrics();
|
||||
@@ -664,7 +660,6 @@ SessionImpl::~SessionImpl()
|
||||
qDebug("Deleting libtorrent session...");
|
||||
delete nativeSessionProxy;
|
||||
});
|
||||
sessionTerminateThread->setObjectName("~SessionImpl sessionTerminateThread");
|
||||
connect(sessionTerminateThread, &QThread::finished, sessionTerminateThread, &QObject::deleteLater);
|
||||
sessionTerminateThread->start();
|
||||
if (sessionTerminateThread->wait(shutdownDeadlineTimer))
|
||||
@@ -1312,7 +1307,7 @@ void SessionImpl::prepareStartup()
|
||||
context->startupStorage = m_resumeDataStorage;
|
||||
|
||||
connect(context->startupStorage, &ResumeDataStorage::loadStarted, context
|
||||
, [this, context](const QList<TorrentID> &torrents)
|
||||
, [this, context](const QVector<TorrentID> &torrents)
|
||||
{
|
||||
context->totalResumeDataCount = torrents.size();
|
||||
#ifdef QBT_USES_LIBTORRENT2
|
||||
@@ -1602,24 +1597,20 @@ void SessionImpl::endStartup(ResumeSessionContext *context)
|
||||
m_resumeDataTimer->start();
|
||||
}
|
||||
|
||||
auto wakeupCheckTimer = new QTimer(this);
|
||||
connect(wakeupCheckTimer, &QTimer::timeout, this, [this]
|
||||
m_wakeupCheckTimer = new QTimer(this);
|
||||
connect(m_wakeupCheckTimer, &QTimer::timeout, this, [this]
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0))
|
||||
const bool hasSystemSlept = m_wakeupCheckTimestamp.durationElapsed() > 100s;
|
||||
#else
|
||||
const bool hasSystemSlept = m_wakeupCheckTimestamp.elapsed() > std::chrono::milliseconds(100s).count();
|
||||
#endif
|
||||
if (hasSystemSlept)
|
||||
const auto now = QDateTime::currentDateTime();
|
||||
if (m_wakeupCheckTimestamp.secsTo(now) > 100)
|
||||
{
|
||||
LogMsg(tr("System wake-up event detected. Re-announcing to all the trackers..."));
|
||||
reannounceToAllTrackers();
|
||||
}
|
||||
|
||||
m_wakeupCheckTimestamp.start();
|
||||
m_wakeupCheckTimestamp = now;
|
||||
});
|
||||
m_wakeupCheckTimestamp.start();
|
||||
wakeupCheckTimer->start(30s);
|
||||
m_wakeupCheckTimestamp = QDateTime::currentDateTime();
|
||||
m_wakeupCheckTimer->start(30s);
|
||||
|
||||
m_isRestored = true;
|
||||
emit startupProgressUpdated(100);
|
||||
@@ -2509,7 +2500,7 @@ bool SessionImpl::cancelDownloadMetadata(const TorrentID &id)
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionImpl::increaseTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
void SessionImpl::increaseTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType
|
||||
@@ -2536,7 +2527,7 @@ void SessionImpl::increaseTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
m_torrentsQueueChanged = true;
|
||||
}
|
||||
|
||||
void SessionImpl::decreaseTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
void SessionImpl::decreaseTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType> torrentQueue;
|
||||
@@ -2564,7 +2555,7 @@ void SessionImpl::decreaseTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
m_torrentsQueueChanged = true;
|
||||
}
|
||||
|
||||
void SessionImpl::topTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
void SessionImpl::topTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType> torrentQueue;
|
||||
@@ -2589,7 +2580,7 @@ void SessionImpl::topTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
m_torrentsQueueChanged = true;
|
||||
}
|
||||
|
||||
void SessionImpl::bottomTorrentsQueuePos(const QList<TorrentID> &ids)
|
||||
void SessionImpl::bottomTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType
|
||||
@@ -2625,9 +2616,9 @@ void SessionImpl::handleTorrentResumeDataRequested(const TorrentImpl *torrent)
|
||||
++m_numResumeData;
|
||||
}
|
||||
|
||||
QList<Torrent *> SessionImpl::torrents() const
|
||||
QVector<Torrent *> SessionImpl::torrents() const
|
||||
{
|
||||
QList<Torrent *> result;
|
||||
QVector<Torrent *> result;
|
||||
result.reserve(m_torrents.size());
|
||||
for (TorrentImpl *torrent : asConst(m_torrents))
|
||||
result << torrent;
|
||||
@@ -3021,6 +3012,11 @@ void SessionImpl::removeMappedPorts(const QSet<quint16> &ports)
|
||||
});
|
||||
}
|
||||
|
||||
void SessionImpl::invokeAsync(std::function<void ()> func)
|
||||
{
|
||||
m_asyncWorker->start(std::move(func));
|
||||
}
|
||||
|
||||
// Add a torrent to libtorrent session in hidden mode
|
||||
// and force it to download its metadata
|
||||
bool SessionImpl::downloadMetadata(const TorrentDescriptor &torrentDescr)
|
||||
@@ -3178,7 +3174,7 @@ void SessionImpl::saveResumeData()
|
||||
|
||||
void SessionImpl::saveTorrentsQueue()
|
||||
{
|
||||
QList<TorrentID> queue;
|
||||
QVector<TorrentID> queue;
|
||||
for (const TorrentImpl *torrent : asConst(m_torrents))
|
||||
{
|
||||
if (const int queuePos = torrent->queuePosition(); queuePos >= 0)
|
||||
@@ -3563,16 +3559,6 @@ void SessionImpl::setSaveResumeDataInterval(const int value)
|
||||
}
|
||||
}
|
||||
|
||||
std::chrono::minutes SessionImpl::saveStatisticsInterval() const
|
||||
{
|
||||
return std::chrono::minutes(m_saveStatisticsInterval);
|
||||
}
|
||||
|
||||
void SessionImpl::setSaveStatisticsInterval(const std::chrono::minutes timeInMinutes)
|
||||
{
|
||||
m_saveStatisticsInterval = timeInMinutes.count();
|
||||
}
|
||||
|
||||
int SessionImpl::shutdownTimeout() const
|
||||
{
|
||||
return m_shutdownTimeout;
|
||||
@@ -4974,16 +4960,6 @@ void SessionImpl::setTrackerFilteringEnabled(const bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
QString SessionImpl::lastExternalIPv4Address() const
|
||||
{
|
||||
return m_lastExternalIPv4Address;
|
||||
}
|
||||
|
||||
QString SessionImpl::lastExternalIPv6Address() const
|
||||
{
|
||||
return m_lastExternalIPv6Address;
|
||||
}
|
||||
|
||||
bool SessionImpl::isListening() const
|
||||
{
|
||||
return m_nativeSessionExtension->isSessionListening();
|
||||
@@ -5065,7 +5041,7 @@ void SessionImpl::handleTorrentSavingModeChanged(TorrentImpl *const torrent)
|
||||
emit torrentSavingModeChanged(torrent);
|
||||
}
|
||||
|
||||
void SessionImpl::handleTorrentTrackersAdded(TorrentImpl *const torrent, const QList<TrackerEntry> &newTrackers)
|
||||
void SessionImpl::handleTorrentTrackersAdded(TorrentImpl *const torrent, const QVector<TrackerEntry> &newTrackers)
|
||||
{
|
||||
for (const TrackerEntry &newTracker : newTrackers)
|
||||
LogMsg(tr("Added tracker to torrent. Torrent: \"%1\". Tracker: \"%2\"").arg(torrent->name(), newTracker.url));
|
||||
@@ -5084,13 +5060,13 @@ void SessionImpl::handleTorrentTrackersChanged(TorrentImpl *const torrent)
|
||||
emit trackersChanged(torrent);
|
||||
}
|
||||
|
||||
void SessionImpl::handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QList<QUrl> &newUrlSeeds)
|
||||
void SessionImpl::handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QVector<QUrl> &newUrlSeeds)
|
||||
{
|
||||
for (const QUrl &newUrlSeed : newUrlSeeds)
|
||||
LogMsg(tr("Added URL seed to torrent. Torrent: \"%1\". URL: \"%2\"").arg(torrent->name(), newUrlSeed.toString()));
|
||||
}
|
||||
|
||||
void SessionImpl::handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QList<QUrl> &urlSeeds)
|
||||
void SessionImpl::handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVector<QUrl> &urlSeeds)
|
||||
{
|
||||
for (const QUrl &urlSeed : urlSeeds)
|
||||
LogMsg(tr("Removed URL seed from torrent. Torrent: \"%1\". URL: \"%2\"").arg(torrent->name(), urlSeed.toString()));
|
||||
@@ -5108,7 +5084,7 @@ void SessionImpl::handleTorrentStopped(TorrentImpl *const torrent)
|
||||
{
|
||||
torrent->resetTrackerEntryStatuses();
|
||||
|
||||
const QList<TrackerEntryStatus> trackers = torrent->trackers();
|
||||
const QVector<TrackerEntryStatus> trackers = torrent->trackers();
|
||||
QHash<QString, TrackerEntryStatus> updatedTrackers;
|
||||
updatedTrackers.reserve(trackers.size());
|
||||
|
||||
@@ -5518,6 +5494,11 @@ void SessionImpl::setTorrentContentLayout(const TorrentContentLayout value)
|
||||
// Read alerts sent by libtorrent session
|
||||
void SessionImpl::readAlerts()
|
||||
{
|
||||
// cache current datetime of Qt and libtorrent clocks in order
|
||||
// to optimize conversion of time points from lt to Qt clocks
|
||||
m_ltNow = lt::clock_type::now();
|
||||
m_qNow = QDateTime::currentDateTime();
|
||||
|
||||
const std::vector<lt::alert *> alerts = getPendingAlerts();
|
||||
|
||||
Q_ASSERT(m_loadedTorrents.isEmpty());
|
||||
@@ -5831,7 +5812,7 @@ void SessionImpl::handleTorrentDeleteFailedAlert(const lt::torrent_delete_failed
|
||||
#else
|
||||
const auto torrentID = TorrentID::fromInfoHash(alert->info_hash);
|
||||
#endif
|
||||
const auto errorMessage = alert->error ? Utils::String::fromLocal8Bit(alert->error.message()) : QString();
|
||||
const auto errorMessage = alert->error ? QString::fromLocal8Bit(alert->error.message().c_str()) : QString();
|
||||
handleRemovedTorrent(torrentID, errorMessage);
|
||||
}
|
||||
|
||||
@@ -5989,7 +5970,7 @@ void SessionImpl::handleListenFailedAlert(const lt::listen_failed_alert *alert)
|
||||
const QString proto {toString(alert->socket_type)};
|
||||
LogMsg(tr("Failed to listen on IP. IP: \"%1\". Port: \"%2/%3\". Reason: \"%4\"")
|
||||
.arg(toString(alert->address), proto, QString::number(alert->port)
|
||||
, Utils::String::fromLocal8Bit(alert->error.message())), Log::CRITICAL);
|
||||
, QString::fromLocal8Bit(alert->error.message().c_str())), Log::CRITICAL);
|
||||
}
|
||||
|
||||
void SessionImpl::handleExternalIPAlert(const lt::external_ip_alert *alert)
|
||||
@@ -5998,19 +5979,11 @@ void SessionImpl::handleExternalIPAlert(const lt::external_ip_alert *alert)
|
||||
LogMsg(tr("Detected external IP. IP: \"%1\"")
|
||||
.arg(externalIP), Log::INFO);
|
||||
|
||||
const bool isIPv6 = alert->external_address.is_v6();
|
||||
const bool isIPv4 = alert->external_address.is_v4();
|
||||
if (isIPv6 && (externalIP != m_lastExternalIPv6Address))
|
||||
if (m_lastExternalIP != externalIP)
|
||||
{
|
||||
if (isReannounceWhenAddressChangedEnabled() && !m_lastExternalIPv6Address.isEmpty())
|
||||
if (isReannounceWhenAddressChangedEnabled() && !m_lastExternalIP.isEmpty())
|
||||
reannounceToAllTrackers();
|
||||
m_lastExternalIPv6Address = externalIP;
|
||||
}
|
||||
else if (isIPv4 && (externalIP != m_lastExternalIPv4Address))
|
||||
{
|
||||
if (isReannounceWhenAddressChangedEnabled() && !m_lastExternalIPv4Address.isEmpty())
|
||||
reannounceToAllTrackers();
|
||||
m_lastExternalIPv4Address = externalIP;
|
||||
m_lastExternalIP = externalIP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6096,14 +6069,8 @@ void SessionImpl::handleSessionStatsAlert(const lt::session_stats_alert *alert)
|
||||
m_status.allTimeDownload = m_previouslyDownloaded + m_status.totalDownload;
|
||||
m_status.allTimeUpload = m_previouslyUploaded + m_status.totalUpload;
|
||||
|
||||
if (m_saveStatisticsInterval > 0)
|
||||
{
|
||||
const auto saveInterval = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::minutes(m_saveStatisticsInterval));
|
||||
if (m_statisticsLastUpdateTimer.hasExpired(saveInterval.count()))
|
||||
{
|
||||
saveStatistics();
|
||||
}
|
||||
}
|
||||
if (m_statisticsLastUpdateTimer.hasExpired(STATISTICS_SAVE_INTERVAL))
|
||||
saveStatistics();
|
||||
|
||||
m_cacheStatus.totalUsedBuffers = stats[m_metricIndices.disk.diskBlocksInUse];
|
||||
m_cacheStatus.jobQueueLength = stats[m_metricIndices.disk.queuedDiskJobs];
|
||||
@@ -6177,7 +6144,7 @@ void SessionImpl::handleStorageMovedFailedAlert(const lt::storage_moved_failed_a
|
||||
|
||||
void SessionImpl::handleStateUpdateAlert(const lt::state_update_alert *alert)
|
||||
{
|
||||
QList<Torrent *> updatedTorrents;
|
||||
QVector<Torrent *> updatedTorrents;
|
||||
updatedTorrents.reserve(static_cast<decltype(updatedTorrents)::size_type>(alert->status.size()));
|
||||
|
||||
for (const lt::torrent_status &status : alert->status)
|
||||
@@ -6215,7 +6182,7 @@ void SessionImpl::handleSocks5Alert(const lt::socks5_alert *alert) const
|
||||
const QString endpoint = (addr.is_v6() ? u"[%1]:%2"_s : u"%1:%2"_s)
|
||||
.arg(QString::fromStdString(addr.to_string()), QString::number(alert->ip.port()));
|
||||
LogMsg(tr("SOCKS5 proxy error. Address: %1. Message: \"%2\".")
|
||||
.arg(endpoint, Utils::String::fromLocal8Bit(alert->error.message()))
|
||||
.arg(endpoint, QString::fromLocal8Bit(alert->error.message().c_str()))
|
||||
, Log::WARNING);
|
||||
}
|
||||
}
|
||||
@@ -6392,3 +6359,9 @@ void SessionImpl::handleRemovedTorrent(const TorrentID &torrentID, const QString
|
||||
|
||||
m_removingTorrents.erase(removingTorrentDataIter);
|
||||
}
|
||||
|
||||
QDateTime SessionImpl::fromLTTimePoint32(const lt::time_point32 &timePoint) const
|
||||
{
|
||||
const auto secsSinceNow = lt::duration_cast<lt::seconds>(timePoint - m_ltNow + lt::milliseconds(500)).count();
|
||||
return m_qNow.addSecs(secsSinceNow);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -38,14 +37,14 @@
|
||||
#include <libtorrent/torrent_handle.hpp>
|
||||
|
||||
#include <QtContainerFwd>
|
||||
#include <QDateTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
#include <QThreadPool>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/path.h"
|
||||
#include "base/settingvalue.h"
|
||||
@@ -56,8 +55,11 @@
|
||||
#include "session.h"
|
||||
#include "sessionstatus.h"
|
||||
#include "torrentinfo.h"
|
||||
#include "trackerentrystatus.h"
|
||||
|
||||
class QString;
|
||||
class QThread;
|
||||
class QThreadPool;
|
||||
class QTimer;
|
||||
class QUrl;
|
||||
|
||||
@@ -233,8 +235,6 @@ namespace BitTorrent
|
||||
void setPerformanceWarningEnabled(bool enable) override;
|
||||
int saveResumeDataInterval() const override;
|
||||
void setSaveResumeDataInterval(int value) override;
|
||||
std::chrono::minutes saveStatisticsInterval() const override;
|
||||
void setSaveStatisticsInterval(std::chrono::minutes value) override;
|
||||
int shutdownTimeout() const override;
|
||||
void setShutdownTimeout(int value) override;
|
||||
int port() const override;
|
||||
@@ -424,7 +424,7 @@ namespace BitTorrent
|
||||
|
||||
Torrent *getTorrent(const TorrentID &id) const override;
|
||||
Torrent *findTorrent(const InfoHash &infoHash) const override;
|
||||
QList<Torrent *> torrents() const override;
|
||||
QVector<Torrent *> torrents() const override;
|
||||
qsizetype torrentsCount() const override;
|
||||
const SessionStatus &status() const override;
|
||||
const CacheStatus &cacheStatus() const override;
|
||||
@@ -438,13 +438,10 @@ namespace BitTorrent
|
||||
bool downloadMetadata(const TorrentDescriptor &torrentDescr) override;
|
||||
bool cancelDownloadMetadata(const TorrentID &id) override;
|
||||
|
||||
void increaseTorrentsQueuePos(const QList<TorrentID> &ids) override;
|
||||
void decreaseTorrentsQueuePos(const QList<TorrentID> &ids) override;
|
||||
void topTorrentsQueuePos(const QList<TorrentID> &ids) override;
|
||||
void bottomTorrentsQueuePos(const QList<TorrentID> &ids) override;
|
||||
|
||||
QString lastExternalIPv4Address() const override;
|
||||
QString lastExternalIPv6Address() const override;
|
||||
void increaseTorrentsQueuePos(const QVector<TorrentID> &ids) override;
|
||||
void decreaseTorrentsQueuePos(const QVector<TorrentID> &ids) override;
|
||||
void topTorrentsQueuePos(const QVector<TorrentID> &ids) override;
|
||||
void bottomTorrentsQueuePos(const QVector<TorrentID> &ids) override;
|
||||
|
||||
// Torrent interface
|
||||
void handleTorrentResumeDataRequested(const TorrentImpl *torrent);
|
||||
@@ -460,11 +457,11 @@ namespace BitTorrent
|
||||
void handleTorrentStarted(TorrentImpl *torrent);
|
||||
void handleTorrentChecked(TorrentImpl *torrent);
|
||||
void handleTorrentFinished(TorrentImpl *torrent);
|
||||
void handleTorrentTrackersAdded(TorrentImpl *torrent, const QList<TrackerEntry> &newTrackers);
|
||||
void handleTorrentTrackersAdded(TorrentImpl *torrent, const QVector<TrackerEntry> &newTrackers);
|
||||
void handleTorrentTrackersRemoved(TorrentImpl *torrent, const QStringList &deletedTrackers);
|
||||
void handleTorrentTrackersChanged(TorrentImpl *torrent);
|
||||
void handleTorrentUrlSeedsAdded(TorrentImpl *torrent, const QList<QUrl> &newUrlSeeds);
|
||||
void handleTorrentUrlSeedsRemoved(TorrentImpl *torrent, const QList<QUrl> &urlSeeds);
|
||||
void handleTorrentUrlSeedsAdded(TorrentImpl *torrent, const QVector<QUrl> &newUrlSeeds);
|
||||
void handleTorrentUrlSeedsRemoved(TorrentImpl *torrent, const QVector<QUrl> &urlSeeds);
|
||||
void handleTorrentResumeDataReady(TorrentImpl *torrent, const LoadTorrentParams &data);
|
||||
void handleTorrentInfoHashChanged(TorrentImpl *torrent, const InfoHash &prevInfoHash);
|
||||
void handleTorrentStorageMovingStateChanged(TorrentImpl *torrent);
|
||||
@@ -479,17 +476,15 @@ namespace BitTorrent
|
||||
void addMappedPorts(const QSet<quint16> &ports);
|
||||
void removeMappedPorts(const QSet<quint16> &ports);
|
||||
|
||||
QDateTime fromLTTimePoint32(const lt::time_point32 &timePoint) const;
|
||||
|
||||
template <typename Func>
|
||||
void invoke(Func &&func)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, std::forward<Func>(func), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void invokeAsync(Func &&func)
|
||||
{
|
||||
m_asyncWorker->start(std::forward<Func>(func));
|
||||
}
|
||||
void invokeAsync(std::function<void ()> func);
|
||||
|
||||
signals:
|
||||
void addTorrentAlertsReceived(qsizetype count);
|
||||
@@ -697,7 +692,6 @@ namespace BitTorrent
|
||||
CachedSettingValue<bool> m_isBandwidthSchedulerEnabled;
|
||||
CachedSettingValue<bool> m_isPerformanceWarningEnabled;
|
||||
CachedSettingValue<int> m_saveResumeDataInterval;
|
||||
CachedSettingValue<int> m_saveStatisticsInterval;
|
||||
CachedSettingValue<int> m_shutdownTimeout;
|
||||
CachedSettingValue<int> m_port;
|
||||
CachedSettingValue<bool> m_sslEnabled;
|
||||
@@ -758,8 +752,8 @@ namespace BitTorrent
|
||||
const bool m_wasPexEnabled = m_isPeXEnabled;
|
||||
|
||||
int m_numResumeData = 0;
|
||||
QList<TrackerEntry> m_additionalTrackerEntries;
|
||||
QList<QRegularExpression> m_excludedFileNamesRegExpList;
|
||||
QVector<TrackerEntry> m_additionalTrackerEntries;
|
||||
QVector<QRegularExpression> m_excludedFileNamesRegExpList;
|
||||
|
||||
// Statistics
|
||||
mutable QElapsedTimer m_statisticsLastUpdateTimer;
|
||||
@@ -814,8 +808,7 @@ namespace BitTorrent
|
||||
|
||||
QList<MoveStorageJob> m_moveStorageQueue;
|
||||
|
||||
QString m_lastExternalIPv4Address;
|
||||
QString m_lastExternalIPv6Address;
|
||||
QString m_lastExternalIP;
|
||||
|
||||
bool m_needUpgradeDownloadPath = false;
|
||||
|
||||
@@ -825,10 +818,14 @@ namespace BitTorrent
|
||||
bool m_isPortMappingEnabled = false;
|
||||
QHash<quint16, std::vector<lt::port_mapping_t>> m_mappedPorts;
|
||||
|
||||
QElapsedTimer m_wakeupCheckTimestamp;
|
||||
QTimer *m_wakeupCheckTimer = nullptr;
|
||||
QDateTime m_wakeupCheckTimestamp;
|
||||
|
||||
QList<TorrentImpl *> m_pendingFinishedTorrents;
|
||||
|
||||
QDateTime m_qNow;
|
||||
lt::clock_type::time_point m_ltNow;
|
||||
|
||||
friend void Session::initInstance();
|
||||
friend void Session::freeInstance();
|
||||
friend Session *Session::instance();
|
||||
|
||||
@@ -257,8 +257,8 @@ namespace BitTorrent
|
||||
virtual bool hasMissingFiles() const = 0;
|
||||
virtual bool hasError() const = 0;
|
||||
virtual int queuePosition() const = 0;
|
||||
virtual QList<TrackerEntryStatus> trackers() const = 0;
|
||||
virtual QList<QUrl> urlSeeds() const = 0;
|
||||
virtual QVector<TrackerEntryStatus> trackers() const = 0;
|
||||
virtual QVector<QUrl> urlSeeds() const = 0;
|
||||
virtual QString error() const = 0;
|
||||
virtual qlonglong totalDownload() const = 0;
|
||||
virtual qlonglong totalUpload() const = 0;
|
||||
@@ -275,10 +275,10 @@ namespace BitTorrent
|
||||
virtual bool isDHTDisabled() const = 0;
|
||||
virtual bool isPEXDisabled() const = 0;
|
||||
virtual bool isLSDDisabled() const = 0;
|
||||
virtual QList<PeerInfo> peers() const = 0;
|
||||
virtual QVector<PeerInfo> peers() const = 0;
|
||||
virtual QBitArray pieces() const = 0;
|
||||
virtual QBitArray downloadingPieces() const = 0;
|
||||
virtual QList<int> pieceAvailability() const = 0;
|
||||
virtual QVector<int> pieceAvailability() const = 0;
|
||||
virtual qreal distributedCopies() const = 0;
|
||||
virtual qreal maxRatio() const = 0;
|
||||
virtual int maxSeedingTime() const = 0;
|
||||
@@ -307,11 +307,11 @@ namespace BitTorrent
|
||||
virtual void setDHTDisabled(bool disable) = 0;
|
||||
virtual void setPEXDisabled(bool disable) = 0;
|
||||
virtual void setLSDDisabled(bool disable) = 0;
|
||||
virtual void addTrackers(QList<TrackerEntry> trackers) = 0;
|
||||
virtual void addTrackers(QVector<TrackerEntry> trackers) = 0;
|
||||
virtual void removeTrackers(const QStringList &trackers) = 0;
|
||||
virtual void replaceTrackers(QList<TrackerEntry> trackers) = 0;
|
||||
virtual void addUrlSeeds(const QList<QUrl> &urlSeeds) = 0;
|
||||
virtual void removeUrlSeeds(const QList<QUrl> &urlSeeds) = 0;
|
||||
virtual void replaceTrackers(QVector<TrackerEntry> trackers) = 0;
|
||||
virtual void addUrlSeeds(const QVector<QUrl> &urlSeeds) = 0;
|
||||
virtual void removeUrlSeeds(const QVector<QUrl> &urlSeeds) = 0;
|
||||
virtual bool connectPeer(const PeerAddress &peerAddress) = 0;
|
||||
virtual void clearPeers() = 0;
|
||||
virtual void setMetadata(const TorrentInfo &torrentInfo) = 0;
|
||||
@@ -325,9 +325,9 @@ namespace BitTorrent
|
||||
virtual nonstd::expected<QByteArray, QString> exportToBuffer() const = 0;
|
||||
virtual nonstd::expected<void, QString> exportToFile(const Path &path) const = 0;
|
||||
|
||||
virtual void fetchPeerInfo(std::function<void (QList<PeerInfo>)> resultHandler) const = 0;
|
||||
virtual void fetchURLSeeds(std::function<void (QList<QUrl>)> resultHandler) const = 0;
|
||||
virtual void fetchPieceAvailability(std::function<void (QList<int>)> resultHandler) const = 0;
|
||||
virtual void fetchPeerInfo(std::function<void (QVector<PeerInfo>)> resultHandler) const = 0;
|
||||
virtual void fetchURLSeeds(std::function<void (QVector<QUrl>)> resultHandler) const = 0;
|
||||
virtual void fetchPieceAvailability(std::function<void (QVector<int>)> resultHandler) const = 0;
|
||||
virtual void fetchDownloadingPieces(std::function<void (QBitArray)> resultHandler) const = 0;
|
||||
|
||||
TorrentID id() const;
|
||||
|
||||
@@ -44,18 +44,18 @@ namespace BitTorrent
|
||||
virtual bool hasMetadata() const = 0;
|
||||
virtual Path actualStorageLocation() const = 0;
|
||||
virtual Path actualFilePath(int fileIndex) const = 0;
|
||||
virtual QList<DownloadPriority> filePriorities() const = 0;
|
||||
virtual QList<qreal> filesProgress() const = 0;
|
||||
virtual QVector<DownloadPriority> filePriorities() const = 0;
|
||||
virtual QVector<qreal> filesProgress() const = 0;
|
||||
/**
|
||||
* @brief fraction of file pieces that are available at least from one peer
|
||||
*
|
||||
* This is not the same as torrrent availability, it is just a fraction of pieces
|
||||
* that can be downloaded right now. It varies between 0 to 1.
|
||||
*/
|
||||
virtual QList<qreal> availableFileFractions() const = 0;
|
||||
virtual void fetchAvailableFileFractions(std::function<void (QList<qreal>)> resultHandler) const = 0;
|
||||
virtual QVector<qreal> availableFileFractions() const = 0;
|
||||
virtual void fetchAvailableFileFractions(std::function<void (QVector<qreal>)> resultHandler) const = 0;
|
||||
|
||||
virtual void prioritizeFiles(const QList<DownloadPriority> &priorities) = 0;
|
||||
virtual void prioritizeFiles(const QVector<DownloadPriority> &priorities) = 0;
|
||||
virtual void flushCache() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,10 +62,7 @@ BitTorrent::TorrentCreationManager::TorrentCreationManager(IApplication *app, QO
|
||||
, m_maxTasks {SETTINGS_KEY(u"MaxTasks"_s), 256}
|
||||
, m_numThreads {SETTINGS_KEY(u"NumThreads"_s), 1}
|
||||
, m_tasks {std::make_unique<TaskSet>()}
|
||||
, m_threadPool(this)
|
||||
{
|
||||
m_threadPool.setObjectName("TorrentCreationManager m_threadPool");
|
||||
|
||||
if (m_numThreads > 0)
|
||||
m_threadPool.setMaxThreadCount(m_numThreads);
|
||||
}
|
||||
|
||||
@@ -207,9 +207,9 @@ void BitTorrent::TorrentDescriptor::setTorrentInfo(TorrentInfo torrentInfo)
|
||||
}
|
||||
}
|
||||
|
||||
QList<BitTorrent::TrackerEntry> BitTorrent::TorrentDescriptor::trackers() const
|
||||
QVector<BitTorrent::TrackerEntry> BitTorrent::TorrentDescriptor::trackers() const
|
||||
{
|
||||
QList<TrackerEntry> ret;
|
||||
QVector<TrackerEntry> ret;
|
||||
ret.reserve(static_cast<decltype(ret)::size_type>(m_ltAddTorrentParams.trackers.size()));
|
||||
std::size_t i = 0;
|
||||
for (const std::string &tracker : m_ltAddTorrentParams.trackers)
|
||||
@@ -218,9 +218,9 @@ QList<BitTorrent::TrackerEntry> BitTorrent::TorrentDescriptor::trackers() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<QUrl> BitTorrent::TorrentDescriptor::urlSeeds() const
|
||||
QVector<QUrl> BitTorrent::TorrentDescriptor::urlSeeds() const
|
||||
{
|
||||
QList<QUrl> urlSeeds;
|
||||
QVector<QUrl> urlSeeds;
|
||||
urlSeeds.reserve(static_cast<decltype(urlSeeds)::size_type>(m_ltAddTorrentParams.url_seeds.size()));
|
||||
|
||||
for (const std::string &nativeURLSeed : m_ltAddTorrentParams.url_seeds)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "base/3rdparty/expected.hpp"
|
||||
#include "base/path.h"
|
||||
#include "torrentdescriptor.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
class QByteArray;
|
||||
@@ -59,8 +60,8 @@ namespace BitTorrent
|
||||
QDateTime creationDate() const;
|
||||
QString creator() const;
|
||||
QString comment() const;
|
||||
QList<TrackerEntry> trackers() const;
|
||||
QList<QUrl> urlSeeds() const;
|
||||
QVector<TrackerEntry> trackers() const;
|
||||
QVector<QUrl> urlSeeds() const;
|
||||
const std::optional<TorrentInfo> &info() const;
|
||||
|
||||
void setTorrentInfo(TorrentInfo torrentInfo);
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
#include "base/types.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/io.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "common.h"
|
||||
#include "downloadpriority.h"
|
||||
#include "extensiondata.h"
|
||||
@@ -101,13 +100,16 @@ namespace
|
||||
if (const QString *endpointName = cache.object(ltTCPEndpoint))
|
||||
return *endpointName;
|
||||
|
||||
const auto endpointName = Utils::String::fromLatin1((std::ostringstream() << ltTCPEndpoint).str());
|
||||
const std::string tmp = (std::ostringstream() << ltTCPEndpoint).str();
|
||||
const auto endpointName = QString::fromLatin1(tmp.c_str(), tmp.size());
|
||||
cache.insert(ltTCPEndpoint, new QString(endpointName));
|
||||
return endpointName;
|
||||
}
|
||||
|
||||
template <typename FromLTTimePoint32Func>
|
||||
void updateTrackerEntryStatus(TrackerEntryStatus &trackerEntryStatus, const lt::announce_entry &nativeEntry
|
||||
, const QSet<int> &btProtocols, const QHash<lt::tcp::endpoint, QMap<int, int>> &updateInfo)
|
||||
, const QSet<int> &btProtocols, const QHash<lt::tcp::endpoint, QMap<int, int>> &updateInfo
|
||||
, const FromLTTimePoint32Func &fromLTTimePoint32)
|
||||
{
|
||||
Q_ASSERT(trackerEntryStatus.url == QString::fromStdString(nativeEntry.url));
|
||||
|
||||
@@ -144,8 +146,8 @@ namespace
|
||||
trackerEndpointStatus.numSeeds = ltAnnounceInfo.scrape_complete;
|
||||
trackerEndpointStatus.numLeeches = ltAnnounceInfo.scrape_incomplete;
|
||||
trackerEndpointStatus.numDownloaded = ltAnnounceInfo.scrape_downloaded;
|
||||
trackerEndpointStatus.nextAnnounceTime = ltAnnounceInfo.next_announce;
|
||||
trackerEndpointStatus.minAnnounceTime = ltAnnounceInfo.min_announce;
|
||||
trackerEndpointStatus.nextAnnounceTime = fromLTTimePoint32(ltAnnounceInfo.next_announce);
|
||||
trackerEndpointStatus.minAnnounceTime = fromLTTimePoint32(ltAnnounceInfo.min_announce);
|
||||
|
||||
if (ltAnnounceInfo.updating)
|
||||
{
|
||||
@@ -236,8 +238,8 @@ namespace
|
||||
trackerEntryStatus.numSeeds = -1;
|
||||
trackerEntryStatus.numLeeches = -1;
|
||||
trackerEntryStatus.numDownloaded = -1;
|
||||
trackerEntryStatus.nextAnnounceTime = {};
|
||||
trackerEntryStatus.minAnnounceTime = {};
|
||||
trackerEntryStatus.nextAnnounceTime = QDateTime();
|
||||
trackerEntryStatus.minAnnounceTime = QDateTime();
|
||||
trackerEntryStatus.message.clear();
|
||||
|
||||
for (const TrackerEndpointStatus &endpointStatus : asConst(trackerEntryStatus.endpoints))
|
||||
@@ -249,7 +251,7 @@ namespace
|
||||
|
||||
if (endpointStatus.state == trackerEntryStatus.state)
|
||||
{
|
||||
if ((trackerEntryStatus.nextAnnounceTime == AnnounceTimePoint()) || (trackerEntryStatus.nextAnnounceTime > endpointStatus.nextAnnounceTime))
|
||||
if (!trackerEntryStatus.nextAnnounceTime.isValid() || (trackerEntryStatus.nextAnnounceTime > endpointStatus.nextAnnounceTime))
|
||||
{
|
||||
trackerEntryStatus.nextAnnounceTime = endpointStatus.nextAnnounceTime;
|
||||
trackerEntryStatus.minAnnounceTime = endpointStatus.minAnnounceTime;
|
||||
@@ -624,12 +626,12 @@ Path TorrentImpl::makeUserPath(const Path &path) const
|
||||
return userPath;
|
||||
}
|
||||
|
||||
QList<TrackerEntryStatus> TorrentImpl::trackers() const
|
||||
QVector<TrackerEntryStatus> TorrentImpl::trackers() const
|
||||
{
|
||||
return m_trackerEntryStatuses;
|
||||
}
|
||||
|
||||
void TorrentImpl::addTrackers(QList<TrackerEntry> trackers)
|
||||
void TorrentImpl::addTrackers(QVector<TrackerEntry> trackers)
|
||||
{
|
||||
trackers.removeIf([](const TrackerEntry &trackerEntry) { return trackerEntry.url.isEmpty(); });
|
||||
|
||||
@@ -642,7 +644,7 @@ void TorrentImpl::addTrackers(QList<TrackerEntry> trackers)
|
||||
if (newTrackerSet.isEmpty())
|
||||
return;
|
||||
|
||||
trackers = QList<TrackerEntry>(newTrackerSet.cbegin(), newTrackerSet.cend());
|
||||
trackers = QVector<TrackerEntry>(newTrackerSet.cbegin(), newTrackerSet.cend());
|
||||
for (const TrackerEntry &tracker : asConst(trackers))
|
||||
{
|
||||
m_nativeHandle.add_tracker(makeNativeAnnounceEntry(tracker.url, tracker.tier));
|
||||
@@ -678,13 +680,13 @@ void TorrentImpl::removeTrackers(const QStringList &trackers)
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::replaceTrackers(QList<TrackerEntry> trackers)
|
||||
void TorrentImpl::replaceTrackers(QVector<TrackerEntry> trackers)
|
||||
{
|
||||
trackers.removeIf([](const TrackerEntry &trackerEntry) { return trackerEntry.url.isEmpty(); });
|
||||
|
||||
// Filter out duplicate trackers
|
||||
const auto uniqueTrackers = QSet<TrackerEntry>(trackers.cbegin(), trackers.cend());
|
||||
trackers = QList<TrackerEntry>(uniqueTrackers.cbegin(), uniqueTrackers.cend());
|
||||
trackers = QVector<TrackerEntry>(uniqueTrackers.cbegin(), uniqueTrackers.cend());
|
||||
std::sort(trackers.begin(), trackers.end()
|
||||
, [](const TrackerEntry &left, const TrackerEntry &right) { return left.tier < right.tier; });
|
||||
|
||||
@@ -709,12 +711,12 @@ void TorrentImpl::replaceTrackers(QList<TrackerEntry> trackers)
|
||||
m_session->handleTorrentTrackersChanged(this);
|
||||
}
|
||||
|
||||
QList<QUrl> TorrentImpl::urlSeeds() const
|
||||
QVector<QUrl> TorrentImpl::urlSeeds() const
|
||||
{
|
||||
return m_urlSeeds;
|
||||
}
|
||||
|
||||
void TorrentImpl::addUrlSeeds(const QList<QUrl> &urlSeeds)
|
||||
void TorrentImpl::addUrlSeeds(const QVector<QUrl> &urlSeeds)
|
||||
{
|
||||
m_session->invokeAsync([urlSeeds, session = m_session
|
||||
, nativeHandle = m_nativeHandle
|
||||
@@ -723,12 +725,12 @@ void TorrentImpl::addUrlSeeds(const QList<QUrl> &urlSeeds)
|
||||
try
|
||||
{
|
||||
const std::set<std::string> nativeSeeds = nativeHandle.url_seeds();
|
||||
QList<QUrl> currentSeeds;
|
||||
QVector<QUrl> currentSeeds;
|
||||
currentSeeds.reserve(static_cast<decltype(currentSeeds)::size_type>(nativeSeeds.size()));
|
||||
for (const std::string &urlSeed : nativeSeeds)
|
||||
currentSeeds.append(QString::fromStdString(urlSeed));
|
||||
|
||||
QList<QUrl> addedUrlSeeds;
|
||||
QVector<QUrl> addedUrlSeeds;
|
||||
addedUrlSeeds.reserve(urlSeeds.size());
|
||||
|
||||
for (const QUrl &url : urlSeeds)
|
||||
@@ -758,7 +760,7 @@ void TorrentImpl::addUrlSeeds(const QList<QUrl> &urlSeeds)
|
||||
});
|
||||
}
|
||||
|
||||
void TorrentImpl::removeUrlSeeds(const QList<QUrl> &urlSeeds)
|
||||
void TorrentImpl::removeUrlSeeds(const QVector<QUrl> &urlSeeds)
|
||||
{
|
||||
m_session->invokeAsync([urlSeeds, session = m_session
|
||||
, nativeHandle = m_nativeHandle
|
||||
@@ -767,12 +769,12 @@ void TorrentImpl::removeUrlSeeds(const QList<QUrl> &urlSeeds)
|
||||
try
|
||||
{
|
||||
const std::set<std::string> nativeSeeds = nativeHandle.url_seeds();
|
||||
QList<QUrl> currentSeeds;
|
||||
QVector<QUrl> currentSeeds;
|
||||
currentSeeds.reserve(static_cast<decltype(currentSeeds)::size_type>(nativeSeeds.size()));
|
||||
for (const std::string &urlSeed : nativeSeeds)
|
||||
currentSeeds.append(QString::fromStdString(urlSeed));
|
||||
|
||||
QList<QUrl> removedUrlSeeds;
|
||||
QVector<QUrl> removedUrlSeeds;
|
||||
removedUrlSeeds.reserve(urlSeeds.size());
|
||||
|
||||
for (const QUrl &url : urlSeeds)
|
||||
@@ -1029,7 +1031,7 @@ Path TorrentImpl::filePath(const int index) const
|
||||
|
||||
Path TorrentImpl::actualFilePath(const int index) const
|
||||
{
|
||||
const QList<lt::file_index_t> nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||
const QVector<lt::file_index_t> nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||
|
||||
Q_ASSERT(index >= 0);
|
||||
Q_ASSERT(index < nativeIndexes.size());
|
||||
@@ -1064,7 +1066,7 @@ PathList TorrentImpl::actualFilePaths() const
|
||||
return paths;
|
||||
}
|
||||
|
||||
QList<DownloadPriority> TorrentImpl::filePriorities() const
|
||||
QVector<DownloadPriority> TorrentImpl::filePriorities() const
|
||||
{
|
||||
return m_filePriorities;
|
||||
}
|
||||
@@ -1299,12 +1301,12 @@ int TorrentImpl::queuePosition() const
|
||||
QString TorrentImpl::error() const
|
||||
{
|
||||
if (m_nativeStatus.errc)
|
||||
return Utils::String::fromLocal8Bit(m_nativeStatus.errc.message());
|
||||
return QString::fromLocal8Bit(m_nativeStatus.errc.message().c_str());
|
||||
|
||||
if (m_nativeStatus.flags & lt::torrent_flags::upload_mode)
|
||||
{
|
||||
return tr("Couldn't write to file. Reason: \"%1\". Torrent is now in \"upload only\" mode.")
|
||||
.arg(Utils::String::fromLocal8Bit(m_lastFileError.error.message()));
|
||||
.arg(QString::fromLocal8Bit(m_lastFileError.error.message().c_str()));
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -1370,7 +1372,7 @@ qlonglong TorrentImpl::eta() const
|
||||
return (wantedSize() - completedSize()) / speedAverage.download;
|
||||
}
|
||||
|
||||
QList<qreal> TorrentImpl::filesProgress() const
|
||||
QVector<qreal> TorrentImpl::filesProgress() const
|
||||
{
|
||||
if (!hasMetadata())
|
||||
return {};
|
||||
@@ -1381,9 +1383,9 @@ QList<qreal> TorrentImpl::filesProgress() const
|
||||
return {};
|
||||
|
||||
if (m_completedFiles.count(true) == count)
|
||||
return QList<qreal>(count, 1);
|
||||
return QVector<qreal>(count, 1);
|
||||
|
||||
QList<qreal> result;
|
||||
QVector<qreal> result;
|
||||
result.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
@@ -1459,12 +1461,12 @@ bool TorrentImpl::isLSDDisabled() const
|
||||
return static_cast<bool>(m_nativeStatus.flags & lt::torrent_flags::disable_lsd);
|
||||
}
|
||||
|
||||
QList<PeerInfo> TorrentImpl::peers() const
|
||||
QVector<PeerInfo> TorrentImpl::peers() const
|
||||
{
|
||||
std::vector<lt::peer_info> nativePeers;
|
||||
m_nativeHandle.get_peer_info(nativePeers);
|
||||
|
||||
QList<PeerInfo> peers;
|
||||
QVector<PeerInfo> peers;
|
||||
peers.reserve(static_cast<decltype(peers)::size_type>(nativePeers.size()));
|
||||
|
||||
for (const lt::peer_info &peer : nativePeers)
|
||||
@@ -1493,7 +1495,7 @@ QBitArray TorrentImpl::downloadingPieces() const
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<int> TorrentImpl::pieceAvailability() const
|
||||
QVector<int> TorrentImpl::pieceAvailability() const
|
||||
{
|
||||
std::vector<int> avail;
|
||||
m_nativeHandle.piece_availability(avail);
|
||||
@@ -1772,7 +1774,11 @@ TrackerEntryStatus TorrentImpl::updateTrackerEntryStatus(const lt::announce_entr
|
||||
const QSet<int> btProtocols {1};
|
||||
#endif
|
||||
|
||||
::updateTrackerEntryStatus(*it, announceEntry, btProtocols, updateInfo);
|
||||
const auto fromLTTimePoint32 = [this](const lt::time_point32 &timePoint)
|
||||
{
|
||||
return m_session->fromLTTimePoint32(timePoint);
|
||||
};
|
||||
::updateTrackerEntryStatus(*it, announceEntry, btProtocols, updateInfo, fromLTTimePoint32);
|
||||
|
||||
return *it;
|
||||
}
|
||||
@@ -2142,7 +2148,7 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
|
||||
// URL seed list have been changed by libtorrent for some reason, so we need to update cached one.
|
||||
// Unfortunately, URL seed list containing in "resume data" is generated according to different rules
|
||||
// than the list we usually cache, so we have to request it from the appropriate source.
|
||||
fetchURLSeeds([this](const QList<QUrl> &urlSeeds) { m_urlSeeds = urlSeeds; });
|
||||
fetchURLSeeds([this](const QVector<QUrl> &urlSeeds) { m_urlSeeds = urlSeeds; });
|
||||
}
|
||||
|
||||
if ((m_maintenanceJob == MaintenanceJob::HandleMetadata) && p->params.ti)
|
||||
@@ -2268,7 +2274,7 @@ void TorrentImpl::handleSaveResumeDataFailedAlert(const lt::save_resume_data_fai
|
||||
if (p->error != lt::errors::resume_data_not_modified)
|
||||
{
|
||||
LogMsg(tr("Generate resume data failed. Torrent: \"%1\". Reason: \"%2\"")
|
||||
.arg(name(), Utils::String::fromLocal8Bit(p->error.message())), Log::CRITICAL);
|
||||
.arg(name(), QString::fromLocal8Bit(p->error.message().c_str())), Log::CRITICAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2356,7 +2362,7 @@ void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert
|
||||
Q_ASSERT(fileIndex >= 0);
|
||||
|
||||
LogMsg(tr("File rename failed. Torrent: \"%1\", file: \"%2\", reason: \"%3\"")
|
||||
.arg(name(), filePath(fileIndex).toString(), Utils::String::fromLocal8Bit(p->error.message())), Log::WARNING);
|
||||
.arg(name(), filePath(fileIndex).toString(), QString::fromLocal8Bit(p->error.message().c_str())), Log::WARNING);
|
||||
|
||||
--m_renameCount;
|
||||
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
||||
@@ -2535,7 +2541,7 @@ void TorrentImpl::adjustStorageLocation()
|
||||
|
||||
void TorrentImpl::doRenameFile(const int index, const Path &path)
|
||||
{
|
||||
const QList<lt::file_index_t> nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||
const QVector<lt::file_index_t> nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||
|
||||
Q_ASSERT(index >= 0);
|
||||
Q_ASSERT(index < nativeIndexes.size());
|
||||
@@ -2863,11 +2869,6 @@ QString TorrentImpl::createMagnetURI() const
|
||||
ret += u"&dn=" + QString::fromLatin1(QUrl::toPercentEncoding(displayName));
|
||||
}
|
||||
|
||||
if (hasMetadata())
|
||||
{
|
||||
ret += u"&xl=" + QString::number(totalSize());
|
||||
}
|
||||
|
||||
for (const TrackerEntryStatus &tracker : asConst(trackers()))
|
||||
{
|
||||
ret += u"&tr=" + QString::fromLatin1(QUrl::toPercentEncoding(tracker.url));
|
||||
@@ -2934,15 +2935,15 @@ nonstd::expected<void, QString> TorrentImpl::exportToFile(const Path &path) cons
|
||||
return {};
|
||||
}
|
||||
|
||||
void TorrentImpl::fetchPeerInfo(std::function<void (QList<PeerInfo>)> resultHandler) const
|
||||
void TorrentImpl::fetchPeerInfo(std::function<void (QVector<PeerInfo>)> resultHandler) const
|
||||
{
|
||||
invokeAsync([nativeHandle = m_nativeHandle, allPieces = pieces()]() -> QList<PeerInfo>
|
||||
invokeAsync([nativeHandle = m_nativeHandle, allPieces = pieces()]() -> QVector<PeerInfo>
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<lt::peer_info> nativePeers;
|
||||
nativeHandle.get_peer_info(nativePeers);
|
||||
QList<PeerInfo> peers;
|
||||
QVector<PeerInfo> peers;
|
||||
peers.reserve(static_cast<decltype(peers)::size_type>(nativePeers.size()));
|
||||
for (const lt::peer_info &peer : nativePeers)
|
||||
peers.append(PeerInfo(peer, allPieces));
|
||||
@@ -2955,14 +2956,14 @@ void TorrentImpl::fetchPeerInfo(std::function<void (QList<PeerInfo>)> resultHand
|
||||
, std::move(resultHandler));
|
||||
}
|
||||
|
||||
void TorrentImpl::fetchURLSeeds(std::function<void (QList<QUrl>)> resultHandler) const
|
||||
void TorrentImpl::fetchURLSeeds(std::function<void (QVector<QUrl>)> resultHandler) const
|
||||
{
|
||||
invokeAsync([nativeHandle = m_nativeHandle]() -> QList<QUrl>
|
||||
invokeAsync([nativeHandle = m_nativeHandle]() -> QVector<QUrl>
|
||||
{
|
||||
try
|
||||
{
|
||||
const std::set<std::string> currentSeeds = nativeHandle.url_seeds();
|
||||
QList<QUrl> urlSeeds;
|
||||
QVector<QUrl> urlSeeds;
|
||||
urlSeeds.reserve(static_cast<decltype(urlSeeds)::size_type>(currentSeeds.size()));
|
||||
for (const std::string &urlSeed : currentSeeds)
|
||||
urlSeeds.append(QString::fromStdString(urlSeed));
|
||||
@@ -2975,15 +2976,15 @@ void TorrentImpl::fetchURLSeeds(std::function<void (QList<QUrl>)> resultHandler)
|
||||
, std::move(resultHandler));
|
||||
}
|
||||
|
||||
void TorrentImpl::fetchPieceAvailability(std::function<void (QList<int>)> resultHandler) const
|
||||
void TorrentImpl::fetchPieceAvailability(std::function<void (QVector<int>)> resultHandler) const
|
||||
{
|
||||
invokeAsync([nativeHandle = m_nativeHandle]() -> QList<int>
|
||||
invokeAsync([nativeHandle = m_nativeHandle]() -> QVector<int>
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<int> piecesAvailability;
|
||||
nativeHandle.piece_availability(piecesAvailability);
|
||||
return QList<int>(piecesAvailability.cbegin(), piecesAvailability.cend());
|
||||
return QVector<int>(piecesAvailability.cbegin(), piecesAvailability.cend());
|
||||
}
|
||||
catch (const std::exception &) {}
|
||||
|
||||
@@ -3017,9 +3018,9 @@ void TorrentImpl::fetchDownloadingPieces(std::function<void (QBitArray)> resultH
|
||||
, std::move(resultHandler));
|
||||
}
|
||||
|
||||
void TorrentImpl::fetchAvailableFileFractions(std::function<void (QList<qreal>)> resultHandler) const
|
||||
void TorrentImpl::fetchAvailableFileFractions(std::function<void (QVector<qreal>)> resultHandler) const
|
||||
{
|
||||
invokeAsync([nativeHandle = m_nativeHandle, torrentInfo = m_torrentInfo]() -> QList<qreal>
|
||||
invokeAsync([nativeHandle = m_nativeHandle, torrentInfo = m_torrentInfo]() -> QVector<qreal>
|
||||
{
|
||||
if (!torrentInfo.isValid() || (torrentInfo.filesCount() <= 0))
|
||||
return {};
|
||||
@@ -3031,9 +3032,9 @@ void TorrentImpl::fetchAvailableFileFractions(std::function<void (QList<qreal>)>
|
||||
const int filesCount = torrentInfo.filesCount();
|
||||
// libtorrent returns empty array for seeding only torrents
|
||||
if (piecesAvailability.empty())
|
||||
return QList<qreal>(filesCount, -1);
|
||||
return QVector<qreal>(filesCount, -1);
|
||||
|
||||
QList<qreal> result;
|
||||
QVector<qreal> result;
|
||||
result.reserve(filesCount);
|
||||
for (int i = 0; i < filesCount; ++i)
|
||||
{
|
||||
@@ -3057,7 +3058,7 @@ void TorrentImpl::fetchAvailableFileFractions(std::function<void (QList<qreal>)>
|
||||
, std::move(resultHandler));
|
||||
}
|
||||
|
||||
void TorrentImpl::prioritizeFiles(const QList<DownloadPriority> &priorities)
|
||||
void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
||||
{
|
||||
if (!hasMetadata())
|
||||
return;
|
||||
@@ -3066,7 +3067,7 @@ void TorrentImpl::prioritizeFiles(const QList<DownloadPriority> &priorities)
|
||||
|
||||
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
||||
// 'torrent_finished_alert' and eg show tray notifications
|
||||
const QList<DownloadPriority> oldPriorities = filePriorities();
|
||||
const QVector<DownloadPriority> oldPriorities = filePriorities();
|
||||
for (int i = 0; i < oldPriorities.size(); ++i)
|
||||
{
|
||||
if ((oldPriorities[i] == DownloadPriority::Ignored)
|
||||
@@ -3094,18 +3095,18 @@ void TorrentImpl::prioritizeFiles(const QList<DownloadPriority> &priorities)
|
||||
manageActualFilePaths();
|
||||
}
|
||||
|
||||
QList<qreal> TorrentImpl::availableFileFractions() const
|
||||
QVector<qreal> TorrentImpl::availableFileFractions() const
|
||||
{
|
||||
Q_ASSERT(hasMetadata());
|
||||
|
||||
const int filesCount = this->filesCount();
|
||||
if (filesCount <= 0) return {};
|
||||
|
||||
const QList<int> piecesAvailability = pieceAvailability();
|
||||
const QVector<int> piecesAvailability = pieceAvailability();
|
||||
// libtorrent returns empty array for seeding only torrents
|
||||
if (piecesAvailability.empty()) return QList<qreal>(filesCount, -1);
|
||||
if (piecesAvailability.empty()) return QVector<qreal>(filesCount, -1);
|
||||
|
||||
QList<qreal> res;
|
||||
QVector<qreal> res;
|
||||
res.reserve(filesCount);
|
||||
for (int i = 0; i < filesCount; ++i)
|
||||
{
|
||||
|
||||
@@ -41,11 +41,11 @@
|
||||
#include <QBitArray>
|
||||
#include <QDateTime>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/path.h"
|
||||
#include "base/tagset.h"
|
||||
@@ -162,7 +162,7 @@ namespace BitTorrent
|
||||
qlonglong fileSize(int index) const override;
|
||||
PathList filePaths() const override;
|
||||
PathList actualFilePaths() const override;
|
||||
QList<DownloadPriority> filePriorities() const override;
|
||||
QVector<DownloadPriority> filePriorities() const override;
|
||||
|
||||
TorrentInfo info() const override;
|
||||
bool isFinished() const override;
|
||||
@@ -184,13 +184,13 @@ namespace BitTorrent
|
||||
bool hasMissingFiles() const override;
|
||||
bool hasError() const override;
|
||||
int queuePosition() const override;
|
||||
QList<TrackerEntryStatus> trackers() const override;
|
||||
QList<QUrl> urlSeeds() const override;
|
||||
QVector<TrackerEntryStatus> trackers() const override;
|
||||
QVector<QUrl> urlSeeds() const override;
|
||||
QString error() const override;
|
||||
qlonglong totalDownload() const override;
|
||||
qlonglong totalUpload() const override;
|
||||
qlonglong eta() const override;
|
||||
QList<qreal> filesProgress() const override;
|
||||
QVector<qreal> filesProgress() const override;
|
||||
int seedsCount() const override;
|
||||
int peersCount() const override;
|
||||
int leechsCount() const override;
|
||||
@@ -203,10 +203,10 @@ namespace BitTorrent
|
||||
bool isDHTDisabled() const override;
|
||||
bool isPEXDisabled() const override;
|
||||
bool isLSDDisabled() const override;
|
||||
QList<PeerInfo> peers() const override;
|
||||
QVector<PeerInfo> peers() const override;
|
||||
QBitArray pieces() const override;
|
||||
QBitArray downloadingPieces() const override;
|
||||
QList<int> pieceAvailability() const override;
|
||||
QVector<int> pieceAvailability() const override;
|
||||
qreal distributedCopies() const override;
|
||||
qreal maxRatio() const override;
|
||||
int maxSeedingTime() const override;
|
||||
@@ -220,7 +220,7 @@ namespace BitTorrent
|
||||
int connectionsCount() const override;
|
||||
int connectionsLimit() const override;
|
||||
qlonglong nextAnnounce() const override;
|
||||
QList<qreal> availableFileFractions() const override;
|
||||
QVector<qreal> availableFileFractions() const override;
|
||||
|
||||
void setName(const QString &name) override;
|
||||
void setSequentialDownload(bool enable) override;
|
||||
@@ -231,7 +231,7 @@ namespace BitTorrent
|
||||
void forceDHTAnnounce() override;
|
||||
void forceRecheck() override;
|
||||
void renameFile(int index, const Path &path) override;
|
||||
void prioritizeFiles(const QList<DownloadPriority> &priorities) override;
|
||||
void prioritizeFiles(const QVector<DownloadPriority> &priorities) override;
|
||||
void setUploadLimit(int limit) override;
|
||||
void setDownloadLimit(int limit) override;
|
||||
void setSuperSeeding(bool enable) override;
|
||||
@@ -239,11 +239,11 @@ namespace BitTorrent
|
||||
void setPEXDisabled(bool disable) override;
|
||||
void setLSDDisabled(bool disable) override;
|
||||
void flushCache() const override;
|
||||
void addTrackers(QList<TrackerEntry> trackers) override;
|
||||
void addTrackers(QVector<TrackerEntry> trackers) override;
|
||||
void removeTrackers(const QStringList &trackers) override;
|
||||
void replaceTrackers(QList<TrackerEntry> trackers) override;
|
||||
void addUrlSeeds(const QList<QUrl> &urlSeeds) override;
|
||||
void removeUrlSeeds(const QList<QUrl> &urlSeeds) override;
|
||||
void replaceTrackers(QVector<TrackerEntry> trackers) override;
|
||||
void addUrlSeeds(const QVector<QUrl> &urlSeeds) override;
|
||||
void removeUrlSeeds(const QVector<QUrl> &urlSeeds) override;
|
||||
bool connectPeer(const PeerAddress &peerAddress) override;
|
||||
void clearPeers() override;
|
||||
void setMetadata(const TorrentInfo &torrentInfo) override;
|
||||
@@ -258,11 +258,11 @@ namespace BitTorrent
|
||||
nonstd::expected<QByteArray, QString> exportToBuffer() const override;
|
||||
nonstd::expected<void, QString> exportToFile(const Path &path) const override;
|
||||
|
||||
void fetchPeerInfo(std::function<void (QList<PeerInfo>)> resultHandler) const override;
|
||||
void fetchURLSeeds(std::function<void (QList<QUrl>)> resultHandler) const override;
|
||||
void fetchPieceAvailability(std::function<void (QList<int>)> resultHandler) const override;
|
||||
void fetchPeerInfo(std::function<void (QVector<PeerInfo>)> resultHandler) const override;
|
||||
void fetchURLSeeds(std::function<void (QVector<QUrl>)> resultHandler) const override;
|
||||
void fetchPieceAvailability(std::function<void (QVector<int>)> resultHandler) const override;
|
||||
void fetchDownloadingPieces(std::function<void (QBitArray)> resultHandler) const override;
|
||||
void fetchAvailableFileFractions(std::function<void (QList<qreal>)> resultHandler) const override;
|
||||
void fetchAvailableFileFractions(std::function<void (QVector<qreal>)> resultHandler) const override;
|
||||
|
||||
bool needSaveResumeData() const;
|
||||
|
||||
@@ -337,7 +337,7 @@ namespace BitTorrent
|
||||
TorrentInfo m_torrentInfo;
|
||||
PathList m_filePaths;
|
||||
QHash<lt::file_index_t, int> m_indexMap;
|
||||
QList<DownloadPriority> m_filePriorities;
|
||||
QVector<DownloadPriority> m_filePriorities;
|
||||
QBitArray m_completedFiles;
|
||||
SpeedMonitor m_payloadRateMonitor;
|
||||
|
||||
@@ -361,8 +361,8 @@ namespace BitTorrent
|
||||
|
||||
MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
|
||||
|
||||
QList<TrackerEntryStatus> m_trackerEntryStatuses;
|
||||
QList<QUrl> m_urlSeeds;
|
||||
QVector<TrackerEntryStatus> m_trackerEntryStatuses;
|
||||
QVector<QUrl> m_urlSeeds;
|
||||
FileErrorInfo m_lastFileError;
|
||||
|
||||
// Persistent data
|
||||
@@ -393,7 +393,7 @@ namespace BitTorrent
|
||||
int m_uploadLimit = 0;
|
||||
|
||||
QBitArray m_pieces;
|
||||
QList<std::int64_t> m_filesProgress;
|
||||
QVector<std::int64_t> m_filesProgress;
|
||||
|
||||
bool m_deferredRequestResumeDataInvoked = false;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -28,15 +28,24 @@
|
||||
|
||||
#include "torrentinfo.h"
|
||||
|
||||
#include <libtorrent/create_torrent.hpp>
|
||||
#include <libtorrent/error_code.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/path.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/io.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "infohash.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
@@ -73,6 +82,66 @@ bool TorrentInfo::isValid() const
|
||||
return (m_nativeInfo != nullptr);
|
||||
}
|
||||
|
||||
nonstd::expected<TorrentInfo, QString> TorrentInfo::load(const QByteArray &data) noexcept
|
||||
{
|
||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||
// used in `torrent_info()` constructor
|
||||
const auto *pref = Preferences::instance();
|
||||
|
||||
lt::error_code ec;
|
||||
const lt::bdecode_node node = lt::bdecode(data, ec
|
||||
, nullptr, pref->getBdecodeDepthLimit(), pref->getBdecodeTokenLimit());
|
||||
if (ec)
|
||||
return nonstd::make_unexpected(QString::fromStdString(ec.message()));
|
||||
|
||||
const lt::torrent_info nativeInfo {node, ec};
|
||||
if (ec)
|
||||
return nonstd::make_unexpected(QString::fromStdString(ec.message()));
|
||||
|
||||
return TorrentInfo(nativeInfo);
|
||||
}
|
||||
|
||||
nonstd::expected<TorrentInfo, QString> TorrentInfo::loadFromFile(const Path &path) noexcept
|
||||
{
|
||||
QByteArray data;
|
||||
try
|
||||
{
|
||||
const qint64 torrentSizeLimit = Preferences::instance()->getTorrentFileSizeLimit();
|
||||
const auto readResult = Utils::IO::readFile(path, torrentSizeLimit);
|
||||
if (!readResult)
|
||||
return nonstd::make_unexpected(readResult.error().message);
|
||||
data = readResult.value();
|
||||
}
|
||||
catch (const std::bad_alloc &e)
|
||||
{
|
||||
return nonstd::make_unexpected(tr("Failed to allocate memory when reading file. File: \"%1\". Error: \"%2\"")
|
||||
.arg(path.toString(), QString::fromLocal8Bit(e.what())));
|
||||
}
|
||||
|
||||
return load(data);
|
||||
}
|
||||
|
||||
nonstd::expected<void, QString> TorrentInfo::saveToFile(const Path &path) const
|
||||
{
|
||||
if (!isValid())
|
||||
return nonstd::make_unexpected(tr("Invalid metadata"));
|
||||
|
||||
try
|
||||
{
|
||||
const auto torrentCreator = lt::create_torrent(*m_nativeInfo);
|
||||
const lt::entry torrentEntry = torrentCreator.generate();
|
||||
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, torrentEntry);
|
||||
if (!result)
|
||||
return result.get_unexpected();
|
||||
}
|
||||
catch (const lt::system_error &err)
|
||||
{
|
||||
return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
InfoHash TorrentInfo::infoHash() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
@@ -91,6 +160,28 @@ QString TorrentInfo::name() const
|
||||
return QString::fromStdString(m_nativeInfo->orig_files().name());
|
||||
}
|
||||
|
||||
QDateTime TorrentInfo::creationDate() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
|
||||
const std::time_t date = m_nativeInfo->creation_date();
|
||||
return ((date != 0) ? QDateTime::fromSecsSinceEpoch(date) : QDateTime());
|
||||
}
|
||||
|
||||
QString TorrentInfo::creator() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
|
||||
return QString::fromStdString(m_nativeInfo->creator());
|
||||
}
|
||||
|
||||
QString TorrentInfo::comment() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
|
||||
return QString::fromStdString(m_nativeInfo->comment());
|
||||
}
|
||||
|
||||
bool TorrentInfo::isPrivate() const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
@@ -179,7 +270,43 @@ qlonglong TorrentInfo::fileOffset(const int index) const
|
||||
return m_nativeInfo->orig_files().file_offset(m_nativeIndexes[index]);
|
||||
}
|
||||
|
||||
QByteArray TorrentInfo::rawData() const
|
||||
QVector<TrackerEntry> TorrentInfo::trackers() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
|
||||
const std::vector<lt::announce_entry> trackers = m_nativeInfo->trackers();
|
||||
|
||||
QVector<TrackerEntry> ret;
|
||||
ret.reserve(static_cast<decltype(ret)::size_type>(trackers.size()));
|
||||
for (const lt::announce_entry &tracker : trackers)
|
||||
ret.append({.url = QString::fromStdString(tracker.url), .tier = tracker.tier});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVector<QUrl> TorrentInfo::urlSeeds() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
|
||||
const std::vector<lt::web_seed_entry> &nativeWebSeeds = m_nativeInfo->web_seeds();
|
||||
|
||||
QVector<QUrl> urlSeeds;
|
||||
urlSeeds.reserve(static_cast<decltype(urlSeeds)::size_type>(nativeWebSeeds.size()));
|
||||
|
||||
for (const lt::web_seed_entry &webSeed : nativeWebSeeds)
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 20100
|
||||
if (webSeed.type == lt::web_seed_entry::url_seed)
|
||||
urlSeeds.append(QUrl(QString::fromStdString(webSeed.url)));
|
||||
#else
|
||||
urlSeeds.append(QUrl(QString::fromStdString(webSeed.url)));
|
||||
#endif
|
||||
}
|
||||
|
||||
return urlSeeds;
|
||||
}
|
||||
|
||||
QByteArray TorrentInfo::metadata() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
#ifdef QBT_USES_LIBTORRENT2
|
||||
@@ -193,7 +320,7 @@ QByteArray TorrentInfo::rawData() const
|
||||
PathList TorrentInfo::filesForPiece(const int pieceIndex) const
|
||||
{
|
||||
// no checks here because fileIndicesForPiece() will return an empty list
|
||||
const QList<int> fileIndices = fileIndicesForPiece(pieceIndex);
|
||||
const QVector<int> fileIndices = fileIndicesForPiece(pieceIndex);
|
||||
|
||||
PathList res;
|
||||
res.reserve(fileIndices.size());
|
||||
@@ -203,14 +330,14 @@ PathList TorrentInfo::filesForPiece(const int pieceIndex) const
|
||||
return res;
|
||||
}
|
||||
|
||||
QList<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
|
||||
QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
|
||||
{
|
||||
if (!isValid() || (pieceIndex < 0) || (pieceIndex >= piecesCount()))
|
||||
return {};
|
||||
|
||||
const std::vector<lt::file_slice> files = m_nativeInfo->map_block(
|
||||
lt::piece_index_t {pieceIndex}, 0, m_nativeInfo->piece_size(lt::piece_index_t {pieceIndex}));
|
||||
QList<int> res;
|
||||
QVector<int> res;
|
||||
res.reserve(static_cast<decltype(res)::size_type>(files.size()));
|
||||
for (const lt::file_slice &fileSlice : files)
|
||||
{
|
||||
@@ -222,13 +349,13 @@ QList<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
|
||||
return res;
|
||||
}
|
||||
|
||||
QList<QByteArray> TorrentInfo::pieceHashes() const
|
||||
QVector<QByteArray> TorrentInfo::pieceHashes() const
|
||||
{
|
||||
if (!isValid())
|
||||
return {};
|
||||
|
||||
const int count = piecesCount();
|
||||
QList<QByteArray> hashes;
|
||||
QVector<QByteArray> hashes;
|
||||
hashes.reserve(count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
@@ -239,7 +366,16 @@ QList<QByteArray> TorrentInfo::pieceHashes() const
|
||||
|
||||
TorrentInfo::PieceRange TorrentInfo::filePieces(const Path &filePath) const
|
||||
{
|
||||
return filePieces(fileIndex(filePath));
|
||||
if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct
|
||||
return {};
|
||||
|
||||
const int index = fileIndex(filePath);
|
||||
if (index == -1)
|
||||
{
|
||||
qDebug() << "Filename" << filePath.toString() << "was not found in torrent" << name();
|
||||
return {};
|
||||
}
|
||||
return filePieces(index);
|
||||
}
|
||||
|
||||
TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
|
||||
@@ -248,7 +384,10 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
|
||||
return {};
|
||||
|
||||
if ((fileIndex < 0) || (fileIndex >= filesCount()))
|
||||
{
|
||||
qDebug() << "File index (" << fileIndex << ") is out of range for torrent" << name();
|
||||
return {};
|
||||
}
|
||||
|
||||
const lt::file_storage &files = m_nativeInfo->orig_files();
|
||||
const auto fileSize = files.file_size(m_nativeIndexes[fileIndex]);
|
||||
@@ -311,7 +450,7 @@ std::shared_ptr<lt::torrent_info> TorrentInfo::nativeInfo() const
|
||||
return std::make_shared<lt::torrent_info>(*m_nativeInfo);
|
||||
}
|
||||
|
||||
QList<lt::file_index_t> TorrentInfo::nativeIndexes() const
|
||||
QVector<lt::file_index_t> TorrentInfo::nativeIndexes() const
|
||||
{
|
||||
return m_nativeIndexes;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -32,8 +32,9 @@
|
||||
|
||||
#include <QtContainerFwd>
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/3rdparty/expected.hpp"
|
||||
#include "base/indexrange.h"
|
||||
#include "base/pathfwd.h"
|
||||
|
||||
@@ -49,17 +50,26 @@ namespace BitTorrent
|
||||
|
||||
class TorrentInfo
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
|
||||
|
||||
public:
|
||||
TorrentInfo() = default;
|
||||
TorrentInfo(const TorrentInfo &other) = default;
|
||||
|
||||
explicit TorrentInfo(const lt::torrent_info &nativeInfo);
|
||||
|
||||
static nonstd::expected<TorrentInfo, QString> load(const QByteArray &data) noexcept;
|
||||
static nonstd::expected<TorrentInfo, QString> loadFromFile(const Path &path) noexcept;
|
||||
nonstd::expected<void, QString> saveToFile(const Path &path) const;
|
||||
|
||||
TorrentInfo &operator=(const TorrentInfo &other);
|
||||
|
||||
bool isValid() const;
|
||||
InfoHash infoHash() const;
|
||||
QString name() const;
|
||||
QDateTime creationDate() const;
|
||||
QString creator() const;
|
||||
QString comment() const;
|
||||
bool isPrivate() const;
|
||||
qlonglong totalSize() const;
|
||||
int filesCount() const;
|
||||
@@ -70,9 +80,12 @@ namespace BitTorrent
|
||||
PathList filePaths() const;
|
||||
qlonglong fileSize(int index) const;
|
||||
qlonglong fileOffset(int index) const;
|
||||
QVector<TrackerEntry> trackers() const;
|
||||
QVector<QUrl> urlSeeds() const;
|
||||
QByteArray metadata() const;
|
||||
PathList filesForPiece(int pieceIndex) const;
|
||||
QList<int> fileIndicesForPiece(int pieceIndex) const;
|
||||
QList<QByteArray> pieceHashes() const;
|
||||
QVector<int> fileIndicesForPiece(int pieceIndex) const;
|
||||
QVector<QByteArray> pieceHashes() const;
|
||||
|
||||
using PieceRange = IndexRange<int>;
|
||||
// returns pair of the first and the last pieces into which
|
||||
@@ -80,12 +93,10 @@ namespace BitTorrent
|
||||
PieceRange filePieces(const Path &filePath) const;
|
||||
PieceRange filePieces(int fileIndex) const;
|
||||
|
||||
QByteArray rawData() const;
|
||||
|
||||
bool matchesInfoHash(const InfoHash &otherInfoHash) const;
|
||||
|
||||
std::shared_ptr<lt::torrent_info> nativeInfo() const;
|
||||
QList<lt::file_index_t> nativeIndexes() const;
|
||||
QVector<lt::file_index_t> nativeIndexes() const;
|
||||
|
||||
private:
|
||||
// returns file index or -1 if fileName is not found
|
||||
@@ -95,7 +106,7 @@ namespace BitTorrent
|
||||
|
||||
// internal indexes of files (payload only, excluding any .pad files)
|
||||
// by which they are addressed in libtorrent
|
||||
QList<lt::file_index_t> m_nativeIndexes;
|
||||
QVector<lt::file_index_t> m_nativeIndexes;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -28,11 +28,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
#include "announcetimepoint.h"
|
||||
|
||||
class QStringView;
|
||||
|
||||
namespace BitTorrent
|
||||
@@ -60,8 +59,8 @@ namespace BitTorrent
|
||||
int numLeeches = -1;
|
||||
int numDownloaded = -1;
|
||||
|
||||
AnnounceTimePoint nextAnnounceTime {};
|
||||
AnnounceTimePoint minAnnounceTime {};
|
||||
QDateTime nextAnnounceTime {};
|
||||
QDateTime minAnnounceTime {};
|
||||
};
|
||||
|
||||
struct TrackerEntryStatus
|
||||
@@ -77,8 +76,8 @@ namespace BitTorrent
|
||||
int numLeeches = -1;
|
||||
int numDownloaded = -1;
|
||||
|
||||
AnnounceTimePoint nextAnnounceTime {};
|
||||
AnnounceTimePoint minAnnounceTime {};
|
||||
QDateTime nextAnnounceTime {};
|
||||
QDateTime minAnnounceTime {};
|
||||
|
||||
QHash<std::pair<QString, int>, TrackerEndpointStatus> endpoints {};
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ void Connection::read()
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ using QStringPair = std::pair<QString, QString>;
|
||||
|
||||
namespace
|
||||
{
|
||||
const QByteArray EOH = CRLF.repeated(2);
|
||||
const QByteArray EOH = QByteArray(CRLF).repeated(2);
|
||||
|
||||
const QByteArrayView viewWithoutEndingWith(const QByteArrayView in, const QByteArrayView str)
|
||||
{
|
||||
|
||||
@@ -37,9 +37,8 @@
|
||||
|
||||
#include <QtLogging>
|
||||
#include <QNetworkProxy>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslCipher>
|
||||
#include <QSslKey>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslSocket>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
@@ -101,12 +100,13 @@ using namespace Http;
|
||||
Server::Server(IRequestHandler *requestHandler, QObject *parent)
|
||||
: QTcpServer(parent)
|
||||
, m_requestHandler(requestHandler)
|
||||
, m_sslConfig {QSslConfiguration::defaultConfiguration()}
|
||||
{
|
||||
setProxy(QNetworkProxy::NoProxy);
|
||||
|
||||
m_sslConfig.setCiphers(safeCipherList());
|
||||
m_sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
QSslConfiguration sslConf {QSslConfiguration::defaultConfiguration()};
|
||||
sslConf.setProtocol(QSsl::TlsV1_2OrLater);
|
||||
sslConf.setCiphers(safeCipherList());
|
||||
QSslConfiguration::setDefaultConfiguration(sslConf);
|
||||
|
||||
auto *dropConnectionTimer = new QTimer(this);
|
||||
connect(dropConnectionTimer, &QTimer::timeout, this, &Server::dropTimedOutConnection);
|
||||
@@ -115,7 +115,7 @@ Server::Server(IRequestHandler *requestHandler, QObject *parent)
|
||||
|
||||
void Server::incomingConnection(const qintptr socketDescriptor)
|
||||
{
|
||||
std::unique_ptr<QTcpSocket> serverSocket = isHttps() ? std::make_unique<QSslSocket>(this) : std::make_unique<QTcpSocket>(this);
|
||||
std::unique_ptr<QTcpSocket> serverSocket = m_https ? std::make_unique<QSslSocket>(this) : std::make_unique<QTcpSocket>(this);
|
||||
if (!serverSocket->setSocketDescriptor(socketDescriptor))
|
||||
return;
|
||||
|
||||
@@ -127,10 +127,13 @@ void Server::incomingConnection(const qintptr socketDescriptor)
|
||||
|
||||
try
|
||||
{
|
||||
if (isHttps())
|
||||
if (m_https)
|
||||
{
|
||||
auto *sslSocket = static_cast<QSslSocket *>(serverSocket.get());
|
||||
sslSocket->setSslConfiguration(m_sslConfig);
|
||||
sslSocket->setProtocol(QSsl::SecureProtocols);
|
||||
sslSocket->setPrivateKey(m_key);
|
||||
sslSocket->setLocalCertificateChain(m_certificates);
|
||||
sslSocket->setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
sslSocket->startServerEncryption();
|
||||
}
|
||||
|
||||
@@ -175,17 +178,17 @@ bool Server::setupHttps(const QByteArray &certificates, const QByteArray &privat
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sslConfig.setLocalCertificateChain(certs);
|
||||
m_sslConfig.setPrivateKey(key);
|
||||
m_key = key;
|
||||
m_certificates = certs;
|
||||
m_https = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::disableHttps()
|
||||
{
|
||||
m_sslConfig.setLocalCertificateChain({});
|
||||
m_sslConfig.setPrivateKey({});
|
||||
m_https = false;
|
||||
m_certificates.clear();
|
||||
m_key.clear();
|
||||
}
|
||||
|
||||
bool Server::isHttps() const
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSet>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#include <QTcpServer>
|
||||
|
||||
namespace Http
|
||||
@@ -62,6 +63,7 @@ namespace Http
|
||||
QSet<Connection *> m_connections; // for tracking persistent connections
|
||||
|
||||
bool m_https = false;
|
||||
QSslConfiguration m_sslConfig;
|
||||
QList<QSslCertificate> m_certificates;
|
||||
QSslKey m_key;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,10 +29,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHostAddress>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/global.h"
|
||||
|
||||
@@ -58,7 +57,6 @@ namespace Http
|
||||
inline const QString HEADER_X_CONTENT_TYPE_OPTIONS = u"x-content-type-options"_s;
|
||||
inline const QString HEADER_X_FORWARDED_FOR = u"x-forwarded-for"_s;
|
||||
inline const QString HEADER_X_FORWARDED_HOST = u"x-forwarded-host"_s;
|
||||
inline const QString HEADER_X_FORWARDED_PROTO = u"X-forwarded-proto"_s;
|
||||
inline const QString HEADER_X_FRAME_OPTIONS = u"x-frame-options"_s;
|
||||
inline const QString HEADER_X_XSS_PROTECTION = u"x-xss-protection"_s;
|
||||
|
||||
@@ -77,7 +75,7 @@ namespace Http
|
||||
inline const QString CONTENT_TYPE_FORM_DATA = u"multipart/form-data"_s;
|
||||
|
||||
// portability: "\r\n" doesn't guarantee mapping to the correct symbol
|
||||
inline const QByteArray CRLF = QByteArrayLiteral("\x0D\x0A");
|
||||
inline const char CRLF[] = {0x0D, 0x0A, '\0'};
|
||||
|
||||
struct Environment
|
||||
{
|
||||
@@ -111,7 +109,7 @@ namespace Http
|
||||
HeaderMap headers;
|
||||
QHash<QString, QByteArray> query;
|
||||
QHash<QString, QString> posts;
|
||||
QList<UploadedFile> files;
|
||||
QVector<UploadedFile> files;
|
||||
};
|
||||
|
||||
struct ResponseStatus
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
QList<T> loadFromBuffer(const boost::circular_buffer_space_optimized<T> &src, const int offset = 0)
|
||||
QVector<T> loadFromBuffer(const boost::circular_buffer_space_optimized<T> &src, const int offset = 0)
|
||||
{
|
||||
QList<T> ret;
|
||||
QVector<T> ret;
|
||||
ret.reserve(static_cast<typename decltype(ret)::size_type>(src.size()) - offset);
|
||||
std::copy((src.begin() + offset), src.end(), std::back_inserter(ret));
|
||||
return ret;
|
||||
@@ -90,7 +90,7 @@ void Logger::addPeer(const QString &ip, const bool blocked, const QString &reaso
|
||||
emit newLogPeer(msg);
|
||||
}
|
||||
|
||||
QList<Log::Msg> Logger::getMessages(const int lastKnownId) const
|
||||
QVector<Log::Msg> Logger::getMessages(const int lastKnownId) const
|
||||
{
|
||||
const QReadLocker locker(&m_lock);
|
||||
|
||||
@@ -106,7 +106,7 @@ QList<Log::Msg> Logger::getMessages(const int lastKnownId) const
|
||||
return loadFromBuffer(m_messages, (size - diff));
|
||||
}
|
||||
|
||||
QList<Log::Peer> Logger::getPeers(const int lastKnownId) const
|
||||
QVector<Log::Peer> Logger::getPeers(const int lastKnownId) const
|
||||
{
|
||||
const QReadLocker locker(&m_lock);
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ public:
|
||||
|
||||
void addMessage(const QString &message, const Log::MsgType &type = Log::NORMAL);
|
||||
void addPeer(const QString &ip, bool blocked, const QString &reason = {});
|
||||
QList<Log::Msg> getMessages(int lastKnownId = -1) const;
|
||||
QList<Log::Peer> getPeers(int lastKnownId = -1) const;
|
||||
QVector<Log::Msg> getMessages(int lastKnownId = -1) const;
|
||||
QVector<Log::Peer> getPeers(int lastKnownId = -1) const;
|
||||
|
||||
signals:
|
||||
void newLogMessage(const Log::Msg &message);
|
||||
|
||||
@@ -153,7 +153,7 @@ QString DNSUpdater::getUpdateUrl() const
|
||||
break;
|
||||
default:
|
||||
qWarning() << "Unrecognized Dynamic DNS service!";
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
url.setPath(u"/nic/update"_s);
|
||||
@@ -305,7 +305,7 @@ QUrl DNSUpdater::getRegistrationUrl(const DNS::Service service)
|
||||
case DNS::Service::NoIP:
|
||||
return {u"https://www.noip.com/remote-access"_s};
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -320,11 +320,14 @@ void Net::DownloadManager::processRequest(DownloadHandlerImpl *downloadHandler)
|
||||
|
||||
const DownloadRequest downloadRequest = downloadHandler->downloadRequest();
|
||||
QNetworkRequest request {downloadRequest.url()};
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, (downloadRequest.userAgent().isEmpty()
|
||||
? getBrowserUserAgent() : downloadRequest.userAgent().toUtf8()));
|
||||
|
||||
if (downloadRequest.userAgent().isEmpty())
|
||||
request.setRawHeader("User-Agent", getBrowserUserAgent());
|
||||
else
|
||||
request.setRawHeader("User-Agent", downloadRequest.userAgent().toUtf8());
|
||||
|
||||
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
|
||||
request.setRawHeader("Referer", request.url().toEncoded());
|
||||
request.setRawHeader("Referer", request.url().toEncoded().data());
|
||||
#ifdef QT_NO_COMPRESS
|
||||
// The macro "QT_NO_COMPRESS" defined in QT will disable the zlib related features
|
||||
// and reply data auto-decompression in QT will also be disabled. But we can support
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "geoipdatabase.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
@@ -42,7 +41,7 @@ namespace
|
||||
{
|
||||
const qint32 MAX_FILE_SIZE = 67108864; // 64MB
|
||||
const quint32 MAX_METADATA_SIZE = 131072; // 128KB
|
||||
const QByteArray METADATA_BEGIN_MARK = QByteArrayLiteral("\xab\xcd\xefMaxMind.com");
|
||||
const char METADATA_BEGIN_MARK[] = "\xab\xcd\xefMaxMind.com";
|
||||
const char DATA_SECTION_SEPARATOR[16] = {0};
|
||||
|
||||
enum class DataType
|
||||
@@ -310,7 +309,7 @@ QVariantHash GeoIPDatabase::readMetadata() const
|
||||
{
|
||||
if (m_size > MAX_METADATA_SIZE)
|
||||
index += (m_size - MAX_METADATA_SIZE); // from begin of all data
|
||||
auto offset = static_cast<quint32>(index + METADATA_BEGIN_MARK.size());
|
||||
auto offset = static_cast<quint32>(index + strlen(METADATA_BEGIN_MARK));
|
||||
const QVariant metadata = readDataField(offset);
|
||||
if (metadata.userType() == QMetaType::QVariantHash)
|
||||
return metadata.toHash();
|
||||
|
||||
@@ -456,15 +456,15 @@ void GeoIPManager::downloadFinished(const DownloadResult &result)
|
||||
Utils::Fs::mkpath(targetPath);
|
||||
|
||||
const auto path = targetPath / Path(GEODB_FILENAME);
|
||||
const nonstd::expected<void, QString> saveResult = Utils::IO::saveToFile(path, data);
|
||||
if (saveResult)
|
||||
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, data);
|
||||
if (result)
|
||||
{
|
||||
LogMsg(tr("Successfully updated IP geolocation database."), Log::INFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMsg(tr("Couldn't save downloaded IP geolocation database file. Reason: %1")
|
||||
.arg(saveResult.error()), Log::WARNING);
|
||||
.arg(result.error()), Log::WARNING);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -565,11 +565,29 @@ void Smtp::logError(const QString &msg)
|
||||
|
||||
QString Smtp::getCurrentDateTime() const
|
||||
{
|
||||
// [rfc2822] 3.3. Date and Time Specification
|
||||
const auto now = QDateTime::currentDateTime();
|
||||
const QLocale eng {QLocale::English};
|
||||
const QString weekday = eng.dayName(now.date().dayOfWeek(), QLocale::ShortFormat);
|
||||
return (weekday + u", " + now.toString(Qt::RFC2822Date));
|
||||
// return date & time in the format specified in RFC 2822, section 3.3
|
||||
const QDateTime nowDateTime = QDateTime::currentDateTime();
|
||||
const QDate nowDate = nowDateTime.date();
|
||||
const QLocale eng(QLocale::English);
|
||||
|
||||
const QString timeStr = nowDateTime.time().toString(u"HH:mm:ss");
|
||||
const QString weekDayStr = eng.dayName(nowDate.dayOfWeek(), QLocale::ShortFormat);
|
||||
const QString dayStr = QString::number(nowDate.day());
|
||||
const QString monthStr = eng.monthName(nowDate.month(), QLocale::ShortFormat);
|
||||
const QString yearStr = QString::number(nowDate.year());
|
||||
|
||||
QDateTime tmp = nowDateTime;
|
||||
tmp.setTimeSpec(Qt::UTC);
|
||||
const int timeOffsetHour = nowDateTime.secsTo(tmp) / 3600;
|
||||
const int timeOffsetMin = nowDateTime.secsTo(tmp) / 60 - (60 * timeOffsetHour);
|
||||
const int timeOffset = timeOffsetHour * 100 + timeOffsetMin;
|
||||
// buf size = 11 to avoid format truncation warnings from snprintf
|
||||
char buf[11] = {0};
|
||||
std::snprintf(buf, sizeof(buf), "%+05d", timeOffset);
|
||||
const auto timeOffsetStr = QString::fromUtf8(buf);
|
||||
|
||||
const QString ret = weekDayStr + u", " + dayStr + u' ' + monthStr + u' ' + yearStr + u' ' + timeStr + u' ' + timeOffsetStr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Smtp::error(QAbstractSocket::SocketError socketError)
|
||||
|
||||
@@ -359,19 +359,6 @@ void Preferences::setStatusbarDisplayed(const bool displayed)
|
||||
setValue(u"Preferences/General/StatusbarDisplayed"_s, displayed);
|
||||
}
|
||||
|
||||
bool Preferences::isStatusbarExternalIPDisplayed() const
|
||||
{
|
||||
return value(u"Preferences/General/StatusbarExternalIPDisplayed"_s, false);
|
||||
}
|
||||
|
||||
void Preferences::setStatusbarExternalIPDisplayed(const bool displayed)
|
||||
{
|
||||
if (displayed == isStatusbarExternalIPDisplayed())
|
||||
return;
|
||||
|
||||
setValue(u"Preferences/General/StatusbarExternalIPDisplayed"_s, displayed);
|
||||
}
|
||||
|
||||
bool Preferences::isSplashScreenDisabled() const
|
||||
{
|
||||
return value(u"Preferences/General/NoSplashScreen"_s, true);
|
||||
@@ -699,11 +686,11 @@ void Preferences::setWebUIAuthSubnetWhitelistEnabled(const bool enabled)
|
||||
setValue(u"Preferences/WebUI/AuthSubnetWhitelistEnabled"_s, enabled);
|
||||
}
|
||||
|
||||
QList<Utils::Net::Subnet> Preferences::getWebUIAuthSubnetWhitelist() const
|
||||
QVector<Utils::Net::Subnet> Preferences::getWebUIAuthSubnetWhitelist() const
|
||||
{
|
||||
const auto subnets = value<QStringList>(u"Preferences/WebUI/AuthSubnetWhitelist"_s);
|
||||
|
||||
QList<Utils::Net::Subnet> ret;
|
||||
QVector<Utils::Net::Subnet> ret;
|
||||
ret.reserve(subnets.size());
|
||||
|
||||
for (const QString &rawSubnet : subnets)
|
||||
|
||||
@@ -119,8 +119,6 @@ public:
|
||||
void setHideZeroComboValues(int n);
|
||||
bool isStatusbarDisplayed() const;
|
||||
void setStatusbarDisplayed(bool displayed);
|
||||
bool isStatusbarExternalIPDisplayed() const;
|
||||
void setStatusbarExternalIPDisplayed(bool displayed);
|
||||
bool isToolbarDisplayed() const;
|
||||
void setToolbarDisplayed(bool displayed);
|
||||
bool isSplashScreenDisabled() const;
|
||||
@@ -189,7 +187,7 @@ public:
|
||||
void setWebUILocalAuthEnabled(bool enabled);
|
||||
bool isWebUIAuthSubnetWhitelistEnabled() const;
|
||||
void setWebUIAuthSubnetWhitelistEnabled(bool enabled);
|
||||
QList<Utils::Net::Subnet> getWebUIAuthSubnetWhitelist() const;
|
||||
QVector<Utils::Net::Subnet> getWebUIAuthSubnetWhitelist() const;
|
||||
void setWebUIAuthSubnetWhitelist(QStringList subnets);
|
||||
QString getWebUIUsername() const;
|
||||
void setWebUIUsername(const QString &username);
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/path.h"
|
||||
#include "base/utils/io.h"
|
||||
#include "rss_article.h"
|
||||
|
||||
const int ARTICLEDATALIST_TYPEID = qRegisterMetaType<QList<QVariantHash>>();
|
||||
const int ARTICLEDATALIST_TYPEID = qRegisterMetaType<QVector<QVariantHash>>();
|
||||
|
||||
void RSS::Private::FeedSerializer::load(const Path &dataFileName, const QString &url)
|
||||
{
|
||||
@@ -61,7 +61,7 @@ void RSS::Private::FeedSerializer::load(const Path &dataFileName, const QString
|
||||
emit loadingFinished(loadArticles(readResult.value(), url));
|
||||
}
|
||||
|
||||
void RSS::Private::FeedSerializer::store(const Path &dataFileName, const QList<QVariantHash> &articlesData)
|
||||
void RSS::Private::FeedSerializer::store(const Path &dataFileName, const QVector<QVariantHash> &articlesData)
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (const QVariantHash &data : articlesData)
|
||||
@@ -81,7 +81,7 @@ void RSS::Private::FeedSerializer::store(const Path &dataFileName, const QList<Q
|
||||
}
|
||||
}
|
||||
|
||||
QList<QVariantHash> RSS::Private::FeedSerializer::loadArticles(const QByteArray &data, const QString &url)
|
||||
QVector<QVariantHash> RSS::Private::FeedSerializer::loadArticles(const QByteArray &data, const QString &url)
|
||||
{
|
||||
QJsonParseError jsonError;
|
||||
const QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
||||
@@ -98,7 +98,7 @@ QList<QVariantHash> RSS::Private::FeedSerializer::loadArticles(const QByteArray
|
||||
return {};
|
||||
}
|
||||
|
||||
QList<QVariantHash> result;
|
||||
QVector<QVariantHash> result;
|
||||
const QJsonArray jsonArr = jsonDoc.array();
|
||||
result.reserve(jsonArr.size());
|
||||
for (int i = 0; i < jsonArr.size(); ++i)
|
||||
|
||||
@@ -49,12 +49,12 @@ namespace RSS::Private
|
||||
using QObject::QObject;
|
||||
|
||||
void load(const Path &dataFileName, const QString &url);
|
||||
void store(const Path &dataFileName, const QList<QVariantHash> &articlesData);
|
||||
void store(const Path &dataFileName, const QVector<QVariantHash> &articlesData);
|
||||
|
||||
signals:
|
||||
void loadingFinished(const QList<QVariantHash> &articles);
|
||||
void loadingFinished(const QVector<QVariantHash> &articles);
|
||||
|
||||
private:
|
||||
QList<QVariantHash> loadArticles(const QByteArray &data, const QString &url);
|
||||
QVector<QVariantHash> loadArticles(const QByteArray &data, const QString &url);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QList>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/addtorrentmanager.h"
|
||||
#include "base/asyncfilestorage.h"
|
||||
@@ -68,7 +68,7 @@ const QString RULES_FILE_NAME = u"download_rules.json"_s;
|
||||
|
||||
namespace
|
||||
{
|
||||
QList<RSS::AutoDownloadRule> rulesFromJSON(const QByteArray &jsonData)
|
||||
QVector<RSS::AutoDownloadRule> rulesFromJSON(const QByteArray &jsonData)
|
||||
{
|
||||
QJsonParseError jsonError;
|
||||
const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &jsonError);
|
||||
@@ -79,7 +79,7 @@ namespace
|
||||
throw RSS::ParsingError(RSS::AutoDownloader::tr("Invalid data format."));
|
||||
|
||||
const QJsonObject jsonObj {jsonDoc.object()};
|
||||
QList<RSS::AutoDownloadRule> rules;
|
||||
QVector<RSS::AutoDownloadRule> rules;
|
||||
for (auto it = jsonObj.begin(); it != jsonObj.end(); ++it)
|
||||
{
|
||||
const QJsonValue jsonVal {it.value()};
|
||||
@@ -123,7 +123,6 @@ AutoDownloader::AutoDownloader(IApplication *app)
|
||||
.arg(fileName.toString(), errorString), Log::CRITICAL);
|
||||
});
|
||||
|
||||
m_ioThread->setObjectName("RSS::AutoDownloader m_ioThread");
|
||||
m_ioThread->start();
|
||||
|
||||
connect(app->addTorrentManager(), &AddTorrentManager::torrentAdded
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "base/settingvalue.h"
|
||||
#include "base/utils/thread.h"
|
||||
|
||||
class QThread;
|
||||
class QTimer;
|
||||
|
||||
class Application;
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/asyncfilestorage.h"
|
||||
#include "base/global.h"
|
||||
@@ -301,7 +301,7 @@ void Feed::store()
|
||||
m_dirty = false;
|
||||
m_savingTimer.stop();
|
||||
|
||||
QList<QVariantHash> articlesData;
|
||||
QVector<QVariantHash> articlesData;
|
||||
articlesData.reserve(m_articles.size());
|
||||
|
||||
for (Article *article :asConst(m_articles))
|
||||
@@ -395,7 +395,7 @@ int Feed::updateArticles(const QList<QVariantHash> &loadedArticles)
|
||||
return 0;
|
||||
|
||||
QDateTime dummyPubDate {QDateTime::currentDateTime()};
|
||||
QList<QVariantHash> newArticles;
|
||||
QVector<QVariantHash> newArticles;
|
||||
newArticles.reserve(loadedArticles.size());
|
||||
for (QVariantHash article : loadedArticles)
|
||||
{
|
||||
@@ -516,7 +516,7 @@ void Feed::handleArticleRead(Article *article)
|
||||
storeDeferred();
|
||||
}
|
||||
|
||||
void Feed::handleArticleLoadFinished(QList<QVariantHash> articles)
|
||||
void Feed::handleArticleLoadFinished(QVector<QVariantHash> articles)
|
||||
{
|
||||
Q_ASSERT(m_articles.isEmpty());
|
||||
Q_ASSERT(m_unreadCount == 0);
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace RSS
|
||||
void handleDownloadFinished(const Net::DownloadResult &result);
|
||||
void handleParsingFinished(const Private::ParsingResult &result);
|
||||
void handleArticleRead(Article *article);
|
||||
void handleArticleLoadFinished(QList<QVariantHash> articles);
|
||||
void handleArticleLoadFinished(QVector<QVariantHash> articles);
|
||||
|
||||
private:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <QHash>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
#include <QTimeZone>
|
||||
#include <QVariant>
|
||||
#include <QXmlStreamEntityResolver>
|
||||
#include <QXmlStreamReader>
|
||||
@@ -519,7 +518,7 @@ namespace
|
||||
return fallbackDate;
|
||||
|
||||
const QTime qTime(hour, minute, second);
|
||||
QDateTime result(qDate, qTime, QTimeZone::UTC);
|
||||
QDateTime result(qDate, qTime, Qt::UTC);
|
||||
if (offset)
|
||||
result = result.addSecs(-offset);
|
||||
if (!result.isValid())
|
||||
|
||||
@@ -90,7 +90,6 @@ Session::Session()
|
||||
|
||||
m_itemsByPath.insert(u""_s, new Folder); // root folder
|
||||
|
||||
m_workingThread->setObjectName("RSS::Session m_workingThread");
|
||||
m_workingThread->start();
|
||||
load();
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaObject>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/path.h"
|
||||
@@ -145,7 +145,7 @@ void SearchHandler::readSearchOutput()
|
||||
lines.prepend(m_searchResultLineTruncated + lines.takeFirst());
|
||||
m_searchResultLineTruncated = lines.takeLast().trimmed();
|
||||
|
||||
QList<SearchResult> searchResultList;
|
||||
QVector<SearchResult> searchResultList;
|
||||
searchResultList.reserve(lines.size());
|
||||
|
||||
for (const QByteArray &line : asConst(lines))
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
signals:
|
||||
void searchFinished(bool cancelled = false);
|
||||
void searchFailed();
|
||||
void newSearchResults(const QList<SearchResult> &results);
|
||||
void newSearchResults(const QVector<SearchResult> &results);
|
||||
|
||||
private:
|
||||
void readSearchOutput();
|
||||
|
||||
@@ -367,14 +367,14 @@ QString SearchPluginManager::categoryFullName(const QString &categoryName)
|
||||
const QHash<QString, QString> categoryTable
|
||||
{
|
||||
{u"all"_s, tr("All categories")},
|
||||
{u"anime"_s, tr("Anime")},
|
||||
{u"books"_s, tr("Books")},
|
||||
{u"games"_s, tr("Games")},
|
||||
{u"movies"_s, tr("Movies")},
|
||||
{u"tv"_s, tr("TV shows")},
|
||||
{u"music"_s, tr("Music")},
|
||||
{u"pictures"_s, tr("Pictures")},
|
||||
{u"games"_s, tr("Games")},
|
||||
{u"anime"_s, tr("Anime")},
|
||||
{u"software"_s, tr("Software")},
|
||||
{u"tv"_s, tr("TV shows")}
|
||||
{u"pictures"_s, tr("Pictures")},
|
||||
{u"books"_s, tr("Books")}
|
||||
};
|
||||
return categoryTable.value(categoryName);
|
||||
}
|
||||
|
||||
@@ -146,7 +146,6 @@ TorrentFilesWatcher::TorrentFilesWatcher(QObject *parent)
|
||||
|
||||
m_asyncWorker->moveToThread(m_ioThread.get());
|
||||
connect(m_ioThread.get(), &QThread::finished, m_asyncWorker, &QObject::deleteLater);
|
||||
m_ioThread->setObjectName("TorrentFilesWatcher m_ioThread");
|
||||
m_ioThread->start();
|
||||
|
||||
load();
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "base/path.h"
|
||||
#include "base/utils/thread.h"
|
||||
|
||||
class QThread;
|
||||
|
||||
/*
|
||||
* Watches the configured directories for new .torrent files in order
|
||||
* to add torrents to BitTorrent session. Supports Network File System
|
||||
|
||||
@@ -205,11 +205,9 @@ bool TorrentFilter::matchState(const BitTorrent::Torrent *const torrent) const
|
||||
case Errored:
|
||||
return torrent->isErrored();
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TorrentFilter::matchHash(const BitTorrent::Torrent *const torrent) const
|
||||
|
||||
@@ -252,7 +252,7 @@ bool Utils::ForeignApps::PythonInfo::isValid() const
|
||||
|
||||
bool Utils::ForeignApps::PythonInfo::isSupportedVersion() const
|
||||
{
|
||||
return (version >= Version {3, 9, 0});
|
||||
return (version >= Version {3, 7, 0});
|
||||
}
|
||||
|
||||
PythonInfo Utils::ForeignApps::pythonInfo()
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QStorageInfo>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/path.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#include <QStringView>
|
||||
#include <QSysInfo>
|
||||
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/path.h"
|
||||
#include "base/unicodestrings.h"
|
||||
#include "base/utils/string.h"
|
||||
@@ -213,14 +212,6 @@ bool Utils::Misc::isPreviewable(const Path &filePath)
|
||||
return multimediaExtensions.contains(filePath.extension().toUpper());
|
||||
}
|
||||
|
||||
bool Utils::Misc::isTorrentLink(const QString &str)
|
||||
{
|
||||
return str.startsWith(u"magnet:", Qt::CaseInsensitive)
|
||||
|| str.endsWith(TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)
|
||||
|| (!str.startsWith(u"file:", Qt::CaseInsensitive)
|
||||
&& Net::DownloadManager::hasSupportedScheme(str));
|
||||
}
|
||||
|
||||
QString Utils::Misc::userFriendlyDuration(const qlonglong seconds, const qlonglong maxCap, const TimeResolution resolution)
|
||||
{
|
||||
if (seconds < 0)
|
||||
|
||||
@@ -78,7 +78,6 @@ namespace Utils::Misc
|
||||
qint64 sizeInBytes(qreal size, SizeUnit unit);
|
||||
|
||||
bool isPreviewable(const Path &filePath);
|
||||
bool isTorrentLink(const QString &str);
|
||||
|
||||
// Take a number of seconds and return a user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/global.h"
|
||||
|
||||
@@ -54,7 +55,14 @@ namespace Utils
|
||||
return subnet;
|
||||
}
|
||||
|
||||
bool isIPInSubnets(const QHostAddress &addr, const QList<Subnet> &subnets)
|
||||
bool isLoopbackAddress(const QHostAddress &addr)
|
||||
{
|
||||
return (addr == QHostAddress::LocalHost)
|
||||
|| (addr == QHostAddress::LocalHostIPv6)
|
||||
|| (addr == QHostAddress(u"::ffff:127.0.0.1"_s));
|
||||
}
|
||||
|
||||
bool isIPInSubnets(const QHostAddress &addr, const QVector<Subnet> &subnets)
|
||||
{
|
||||
QHostAddress protocolEquivalentAddress;
|
||||
bool addrConversionOk = false;
|
||||
|
||||
@@ -45,7 +45,8 @@ namespace Utils::Net
|
||||
|
||||
bool isValidIP(const QString &ip);
|
||||
std::optional<Subnet> parseSubnet(const QString &subnetStr);
|
||||
bool isIPInSubnets(const QHostAddress &addr, const QList<Subnet> &subnets);
|
||||
bool isLoopbackAddress(const QHostAddress &addr);
|
||||
bool isIPInSubnets(const QHostAddress &addr, const QVector<Subnet> &subnets);
|
||||
QString subnetToString(const Subnet &subnet);
|
||||
QHostAddress canonicalIPv6Addr(const QHostAddress &addr);
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "bytearray.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2017-2024 Mike Tzou (Chocobo1)
|
||||
* Copyright (C) 2017 Mike Tzou
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -32,14 +32,107 @@
|
||||
|
||||
#include <QtSystemDetection>
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
#include "randomlayer_linux.cpp"
|
||||
#elif defined(Q_OS_WIN)
|
||||
#include "randomlayer_win.cpp"
|
||||
#else
|
||||
#include "randomlayer_other.cpp"
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <ntsecapi.h>
|
||||
#else // Q_OS_WIN
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "base/global.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "base/utils/os.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
class RandomLayer
|
||||
{
|
||||
// need to satisfy UniformRandomBitGenerator requirements
|
||||
public:
|
||||
using result_type = uint32_t;
|
||||
|
||||
RandomLayer()
|
||||
: m_rtlGenRandom {Utils::OS::loadWinAPI<PRTLGENRANDOM>(u"Advapi32.dll"_s, "SystemFunction036")}
|
||||
{
|
||||
if (!m_rtlGenRandom)
|
||||
qFatal("Failed to load RtlGenRandom()");
|
||||
}
|
||||
|
||||
static constexpr result_type min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static constexpr result_type max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
result_type buf = 0;
|
||||
const bool result = m_rtlGenRandom(&buf, sizeof(buf));
|
||||
if (!result)
|
||||
qFatal("RtlGenRandom() failed");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private:
|
||||
using PRTLGENRANDOM = BOOLEAN (WINAPI *)(PVOID, ULONG);
|
||||
const PRTLGENRANDOM m_rtlGenRandom;
|
||||
};
|
||||
#else // Q_OS_WIN
|
||||
class RandomLayer
|
||||
{
|
||||
// need to satisfy UniformRandomBitGenerator requirements
|
||||
public:
|
||||
using result_type = uint32_t;
|
||||
|
||||
RandomLayer()
|
||||
: m_randDev {fopen("/dev/urandom", "rb")}
|
||||
{
|
||||
if (!m_randDev)
|
||||
qFatal("Failed to open /dev/urandom. Reason: %s. Error code: %d.\n", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
~RandomLayer()
|
||||
{
|
||||
fclose(m_randDev);
|
||||
}
|
||||
|
||||
static constexpr result_type min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static constexpr result_type max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()() const
|
||||
{
|
||||
result_type buf = 0;
|
||||
if (fread(&buf, sizeof(buf), 1, m_randDev) != 1)
|
||||
qFatal("Read /dev/urandom error. Reason: %s. Error code: %d.\n", std::strerror(errno), errno);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *m_randDev = nullptr;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t Utils::Random::rand(const uint32_t min, const uint32_t max)
|
||||
{
|
||||
static RandomLayer layer;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2017-2024 Mike Tzou (Chocobo1)
|
||||
* Copyright (C) 2017 Mike Tzou
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
#include <sys/random.h>
|
||||
|
||||
#include <QtLogging>
|
||||
|
||||
namespace
|
||||
{
|
||||
class RandomLayer
|
||||
{
|
||||
// need to satisfy UniformRandomBitGenerator requirements
|
||||
public:
|
||||
using result_type = uint32_t;
|
||||
|
||||
RandomLayer()
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr result_type min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static constexpr result_type max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
const int RETRY_MAX = 3;
|
||||
|
||||
for (int i = 0; i < RETRY_MAX; ++i)
|
||||
{
|
||||
result_type buf = 0;
|
||||
const ssize_t result = ::getrandom(&buf, sizeof(buf), 0);
|
||||
if (result == sizeof(buf)) // success
|
||||
return buf;
|
||||
|
||||
if (result < 0)
|
||||
qFatal("getrandom() error. Reason: %s. Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
qFatal("getrandom() failed. Reason: too many retries.");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <QtLogging>
|
||||
|
||||
namespace
|
||||
{
|
||||
class RandomLayer
|
||||
{
|
||||
// need to satisfy UniformRandomBitGenerator requirements
|
||||
public:
|
||||
using result_type = uint32_t;
|
||||
|
||||
RandomLayer()
|
||||
: m_randDev {fopen("/dev/urandom", "rb")}
|
||||
{
|
||||
if (!m_randDev)
|
||||
qFatal("Failed to open /dev/urandom. Reason: %s. Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
~RandomLayer()
|
||||
{
|
||||
fclose(m_randDev);
|
||||
}
|
||||
|
||||
static constexpr result_type min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static constexpr result_type max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()() const
|
||||
{
|
||||
result_type buf = 0;
|
||||
if (fread(&buf, sizeof(buf), 1, m_randDev) != 1)
|
||||
qFatal("Read /dev/urandom error. Reason: %s. Error code: %d.", std::strerror(errno), errno);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *m_randDev = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <QtLogging>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/utils/os.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class RandomLayer
|
||||
{
|
||||
// need to satisfy UniformRandomBitGenerator requirements
|
||||
public:
|
||||
using result_type = uint32_t;
|
||||
|
||||
RandomLayer()
|
||||
: m_processPrng {Utils::OS::loadWinAPI<PPROCESSPRNG>(u"BCryptPrimitives.dll"_s, "ProcessPrng")}
|
||||
{
|
||||
if (!m_processPrng)
|
||||
qFatal("Failed to load ProcessPrng().");
|
||||
}
|
||||
|
||||
static constexpr result_type min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static constexpr result_type max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
result_type buf = 0;
|
||||
const bool result = m_processPrng(reinterpret_cast<PBYTE>(&buf), sizeof(buf));
|
||||
if (!result)
|
||||
qFatal("ProcessPrng() failed.");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private:
|
||||
using PPROCESSPRNG = BOOL (WINAPI *)(PBYTE, SIZE_T);
|
||||
const PPROCESSPRNG m_processPrng = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -31,10 +31,10 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QList>
|
||||
#include <QLocale>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
// to send numbers instead of strings with suffixes
|
||||
QString Utils::String::fromDouble(const double n, const int precision)
|
||||
@@ -49,16 +49,6 @@ QString Utils::String::fromDouble(const double n, const int precision)
|
||||
return QLocale::system().toString(std::floor(n * prec) / prec, 'f', precision);
|
||||
}
|
||||
|
||||
QString Utils::String::fromLatin1(const std::string_view string)
|
||||
{
|
||||
return QString::fromLatin1(string.data(), string.size());
|
||||
}
|
||||
|
||||
QString Utils::String::fromLocal8Bit(const std::string_view string)
|
||||
{
|
||||
return QString::fromLocal8Bit(string.data(), string.size());
|
||||
}
|
||||
|
||||
QString Utils::String::wildcardToRegexPattern(const QString &pattern)
|
||||
{
|
||||
return QRegularExpression::wildcardToRegularExpression(pattern, QRegularExpression::UnanchoredWildcardConversion);
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
#include <QChar>
|
||||
#include <QMetaEnum>
|
||||
@@ -67,8 +66,6 @@ namespace Utils::String
|
||||
QStringList splitCommand(const QString &command);
|
||||
|
||||
QString fromDouble(double n, int precision);
|
||||
QString fromLatin1(std::string_view string);
|
||||
QString fromLocal8Bit(std::string_view string);
|
||||
|
||||
template <typename Container>
|
||||
QString joinIntoString(const Container &container, const QString &separator)
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
#pragma once
|
||||
|
||||
#define QBT_VERSION_MAJOR 5
|
||||
#define QBT_VERSION_MINOR 1
|
||||
#define QBT_VERSION_BUGFIX 0
|
||||
#define QBT_VERSION_MINOR 0
|
||||
#define QBT_VERSION_BUGFIX 3
|
||||
#define QBT_VERSION_BUILD 0
|
||||
#define QBT_VERSION_STATUS "beta1" // Should be empty for stable releases!
|
||||
#define QBT_VERSION_STATUS "" // Should be empty for stable releases!
|
||||
|
||||
#define QBT__STRINGIFY(x) #x
|
||||
#define QBT_STRINGIFY(x) QBT__STRINGIFY(x)
|
||||
|
||||
@@ -46,7 +46,6 @@ add_library(qbt_gui STATIC
|
||||
autoexpandabledialog.h
|
||||
banlistoptionsdialog.h
|
||||
color.h
|
||||
colorscheme.h
|
||||
cookiesdialog.h
|
||||
cookiesmodel.h
|
||||
deletionconfirmationdialog.h
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
<string notr="true">qBittorrent</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -67,7 +67,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::TextFormat::RichText</enum>
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -106,7 +106,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -141,7 +141,7 @@
|
||||
<item row="2" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -183,7 +183,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -211,7 +211,7 @@
|
||||
<item row="2" column="2">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -227,7 +227,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -285,7 +285,7 @@
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowserTranslation">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::LineWrapMode::NoWrap</enum>
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
@@ -337,7 +337,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -359,7 +359,7 @@
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -368,14 +368,14 @@
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="labelBoostVer">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -391,10 +391,10 @@
|
||||
<string notr="true">Qt:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -404,10 +404,10 @@
|
||||
<string notr="true">Libtorrent:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -417,31 +417,31 @@
|
||||
<string notr="true">Boost:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelQtVer">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelLibtVer">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -457,17 +457,17 @@
|
||||
<string notr="true">OpenSSL:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="labelOpensslVer">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -477,17 +477,17 @@
|
||||
<string notr="true">zlib:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="labelZlibVer">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -496,7 +496,7 @@
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -512,14 +512,14 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse</set>
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QList>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
@@ -47,6 +46,7 @@
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/bittorrent/addtorrentparams.h"
|
||||
#include "base/bittorrent/downloadpriority.h"
|
||||
@@ -143,7 +143,7 @@ class AddNewTorrentDialog::TorrentContentAdaptor final
|
||||
{
|
||||
public:
|
||||
TorrentContentAdaptor(const BitTorrent::TorrentInfo &torrentInfo, PathList &filePaths
|
||||
, QList<BitTorrent::DownloadPriority> &filePriorities, std::function<void ()> onFilePrioritiesChanged)
|
||||
, QVector<BitTorrent::DownloadPriority> &filePriorities, std::function<void ()> onFilePrioritiesChanged)
|
||||
: m_torrentInfo {torrentInfo}
|
||||
, m_filePaths {filePaths}
|
||||
, m_filePriorities {filePriorities}
|
||||
@@ -227,29 +227,29 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
QList<BitTorrent::DownloadPriority> filePriorities() const override
|
||||
QVector<BitTorrent::DownloadPriority> filePriorities() const override
|
||||
{
|
||||
return m_filePriorities.isEmpty()
|
||||
? QList<BitTorrent::DownloadPriority>(filesCount(), BitTorrent::DownloadPriority::Normal)
|
||||
? QVector<BitTorrent::DownloadPriority>(filesCount(), BitTorrent::DownloadPriority::Normal)
|
||||
: m_filePriorities;
|
||||
}
|
||||
|
||||
QList<qreal> filesProgress() const override
|
||||
QVector<qreal> filesProgress() const override
|
||||
{
|
||||
return QList<qreal>(filesCount(), 0);
|
||||
return QVector<qreal>(filesCount(), 0);
|
||||
}
|
||||
|
||||
QList<qreal> availableFileFractions() const override
|
||||
QVector<qreal> availableFileFractions() const override
|
||||
{
|
||||
return QList<qreal>(filesCount(), 0);
|
||||
return QVector<qreal>(filesCount(), 0);
|
||||
}
|
||||
|
||||
void fetchAvailableFileFractions(std::function<void (QList<qreal>)> resultHandler) const override
|
||||
void fetchAvailableFileFractions(std::function<void (QVector<qreal>)> resultHandler) const override
|
||||
{
|
||||
resultHandler(availableFileFractions());
|
||||
}
|
||||
|
||||
void prioritizeFiles(const QList<BitTorrent::DownloadPriority> &priorities) override
|
||||
void prioritizeFiles(const QVector<BitTorrent::DownloadPriority> &priorities) override
|
||||
{
|
||||
Q_ASSERT(priorities.size() == filesCount());
|
||||
m_filePriorities = priorities;
|
||||
@@ -274,7 +274,7 @@ public:
|
||||
private:
|
||||
const BitTorrent::TorrentInfo &m_torrentInfo;
|
||||
PathList &m_filePaths;
|
||||
QList<BitTorrent::DownloadPriority> &m_filePriorities;
|
||||
QVector<BitTorrent::DownloadPriority> &m_filePriorities;
|
||||
std::function<void ()> m_onFilePrioritiesChanged;
|
||||
Path m_originalRootFolder;
|
||||
BitTorrent::TorrentContentLayout m_currentContentLayout;
|
||||
@@ -594,7 +594,7 @@ void AddNewTorrentDialog::updateDiskSpaceLabel()
|
||||
if (hasMetadata)
|
||||
{
|
||||
const auto torrentInfo = *torrentDescr.info();
|
||||
const QList<BitTorrent::DownloadPriority> &priorities = m_contentAdaptor->filePriorities();
|
||||
const QVector<BitTorrent::DownloadPriority> &priorities = m_contentAdaptor->filePriorities();
|
||||
Q_ASSERT(priorities.size() == torrentInfo.filesCount());
|
||||
for (int i = 0; i < priorities.size(); ++i)
|
||||
{
|
||||
@@ -899,12 +899,12 @@ void AddNewTorrentDialog::setupTreeview()
|
||||
// Set dialog title
|
||||
setWindowTitle(torrentDescr.name());
|
||||
|
||||
// Set torrent information
|
||||
m_ui->labelCommentData->setText(Utils::Misc::parseHtmlLinks(torrentDescr.comment().toHtmlEscaped()));
|
||||
m_ui->labelDateData->setText(!torrentDescr.creationDate().isNull() ? QLocale().toString(torrentDescr.creationDate(), QLocale::ShortFormat) : tr("Not available"));
|
||||
|
||||
const auto &torrentInfo = *torrentDescr.info();
|
||||
|
||||
// Set torrent information
|
||||
m_ui->labelCommentData->setText(Utils::Misc::parseHtmlLinks(torrentInfo.comment().toHtmlEscaped()));
|
||||
m_ui->labelDateData->setText(!torrentInfo.creationDate().isNull() ? QLocale().toString(torrentInfo.creationDate(), QLocale::ShortFormat) : tr("Not available"));
|
||||
|
||||
BitTorrent::AddTorrentParams &addTorrentParams = m_currentContext->torrentParams;
|
||||
if (addTorrentParams.filePaths.isEmpty())
|
||||
addTorrentParams.filePaths = torrentInfo.filePaths();
|
||||
@@ -918,7 +918,7 @@ void AddNewTorrentDialog::setupTreeview()
|
||||
if (BitTorrent::Session::instance()->isExcludedFileNamesEnabled())
|
||||
{
|
||||
// Check file name blacklist for torrents that are manually added
|
||||
QList<BitTorrent::DownloadPriority> priorities = m_contentAdaptor->filePriorities();
|
||||
QVector<BitTorrent::DownloadPriority> priorities = m_contentAdaptor->filePriorities();
|
||||
BitTorrent::Session::instance()->applyFilenameFilter(m_contentAdaptor->filePaths(), priorities);
|
||||
m_contentAdaptor->prioritizeFiles(priorities);
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
@@ -47,7 +47,7 @@
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
@@ -95,7 +95,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -139,7 +139,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -164,7 +164,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSettings">
|
||||
<property name="title">
|
||||
<string>Torrent options</string>
|
||||
<string>Torrent settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
@@ -188,13 +188,13 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::InsertAtTop</enum>
|
||||
<enum>QComboBox::InsertAtTop</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignRight">
|
||||
<item alignment="Qt::AlignRight">
|
||||
<widget class="QCheckBox" name="defaultCategoryCheckbox">
|
||||
<property name="text">
|
||||
<string>Set as default category</string>
|
||||
@@ -260,14 +260,15 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="stopConditionComboBox"/>
|
||||
<widget class="QComboBox" name="stopConditionComboBox">
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -351,7 +352,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -394,10 +395,10 @@
|
||||
<item row="4" column="1">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
@@ -427,10 +428,10 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="labelCommentData">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::TextFormat::RichText</enum>
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -439,7 +440,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -453,7 +454,7 @@
|
||||
<string>Comment:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -467,7 +468,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelInfohash1Data">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -488,7 +489,7 @@
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="labelInfohash2Data">
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
<set>Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -518,7 +519,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -539,10 +540,10 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ContextMenuPolicy::CustomContextMenu</enum>
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SelectionMode::ExtendedSelection</enum>
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -569,7 +570,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -623,7 +624,7 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -81,7 +81,7 @@
|
||||
<item>
|
||||
<spacer name="downloadPathSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -120,14 +120,14 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::InsertAtTop</enum>
|
||||
<enum>QComboBox::InsertAtTop</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="categorySpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user