Compare commits

..

85 Commits

Author SHA1 Message Date
sledgehammer999
3f0e0a319a Bump to 4.1.5 2018-12-24 19:24:16 +02:00
sledgehammer999
0b4d9c72a7 Update Changelog 2018-12-24 19:20:07 +02:00
sledgehammer999
ff71f6bcd9 Sync translations from Transifex and run lupdate 2018-12-24 18:52:35 +02:00
sledgehammer999
7a5c5baad1 Update transifex config file 2018-12-24 18:52:34 +02:00
thalieht
a18976d0b5 Fix regression on resuming torrents without metadata 2018-12-24 18:19:30 +02:00
Chocobo1
6d836ea49c Change qbt exit message to HTML5 2018-12-24 18:19:29 +02:00
Chocobo1
2e97311147 Unify translation files loading action
Since it is possible alternative WebUI could be coded in languages other than English,
WebUI must be able to load user-provided webui_en.qm.
At least one translated string must exist in order to generate an usable .qm file.
2018-12-24 18:19:28 +02:00
sledgehammer999
57bc564b2c Use configured locale only for translating
Don't use other aspects of it eg for date formatting. We should depend
on the system locale for all these. The user probably likes it that way,
otherwise he would have changed it.
2018-12-24 18:19:27 +02:00
Stephen Dawkins
1295f1e31f Keep track of REPACK/PROPER downloads
When using the smart episode filter, if the episode contains REPACK and/or
PROPER, these should be stored to prevent it from redownloading a duplicate
episodes.

Closes #9898.
2018-12-24 18:19:26 +02:00
sledgehammer999
4916ed0efb Update transifex config file 2018-12-24 18:19:25 +02:00
sledgehammer999
f15f99cb27 Sync translations from Transifex and run lupdate 2018-12-24 18:19:22 +02:00
sledgehammer999
93365d3b20 Update WebUI .ts files 2018-12-24 18:19:11 +02:00
Chocobo1
c756ab021d Upgrade TravisCI to xenial
* Remove cmake installation, it is already pre-installed by TravisCI.
* Limit ccache cache size to 512 MB. Previously the size was 5 GB for
macOS and it took 1~3 mins just for packing & uploading the cache,
limiting the size should shorten total build time.
2018-12-17 00:49:09 +02:00
Nick Korotysh
34528dd544 Make file icon look like other macOS icons 2018-12-17 00:49:08 +02:00
Chocobo1
9380209afb Revise CSP header
The majority of the CSP is tuned for built-in WebUI, it may not be
suitable for alternative UI.

Also add QLatin1String to strings. This code path is called repeatedly,
it is worth adding QLatin1String to squeeze out the last bit of
performance.
2018-12-17 00:49:07 +02:00
Chocobo1
be2895ac6f Enforce referrer-policy in WebUI
This stops leaking private data to other websites via Referrer header.
2018-12-17 00:49:06 +02:00
Thomas Piccirello
e26d4642b8 Add torrent name filtering to WebUI
Closes #721
2018-12-17 00:49:05 +02:00
Thomas Piccirello
f470972bd4 Send numeric status without translation 2018-12-17 00:49:04 +02:00
Thomas Piccirello
443378c041 Remove condition for unsupported libtorrent version 2018-12-17 00:49:02 +02:00
Thomas Piccirello
e20dbe34a4 Simplify map initialization 2018-12-17 00:49:01 +02:00
Thomas Piccirello
86bde47a06 Add WebUI Trackers context menu 2018-12-17 00:49:00 +02:00
Thomas Piccirello
e273c777c7 Add DHT, PeX, and LSD to WebUI Tracker list 2018-12-17 00:48:59 +02:00
Thomas Piccirello
17845c6b25 Add additional Tracker columns to WebUI 2018-12-17 00:48:58 +02:00
Thomas Piccirello
27827ce16a Use const where appropriate 2018-12-17 00:48:57 +02:00
Thomas Piccirello
b444ecc6af Reorder and rename Tracker list context menu option
Adds an ellipses to indicate that the Edit option opens a dialog. Also moves Edit to top of the list to convey action's prominence.
2018-12-17 00:48:56 +02:00
Thomas Piccirello
34995350ee Rename Tracker List columns
"Received" renamed to "Peers", "Peers" renamed to "Leeches".
2018-12-17 00:48:55 +02:00
sledgehammer999
73ceee52f8 Bump Web API version 2018-12-17 00:48:54 +02:00
Thomas Piccirello
85a3ba0eed Update Copyright email address 2018-12-17 00:48:53 +02:00
Thomas Piccirello
86cce76e9d Fix display bugs in WebUI Files tab. Remove <IE9 support
Priority select boxes would frequently go blank due to an unexpected priority value. On first load, the torrent-scoped file checkbox's state was inconsistent with the state of the torrent's files.
2018-12-17 00:48:52 +02:00
Thomas Piccirello
3358fd8e91 Fix incorrect priority value sent from WebUI
Closes #9070.
2018-12-17 00:48:51 +02:00
Thomas Piccirello
120965f823 Set priority for multiple files in one WebAPI request
Closes #6259.
2018-12-17 00:48:50 +02:00
Thomas Piccirello
e70ee9a5b6 Replace prio namespace with FilePriority enum class 2018-12-17 00:48:48 +02:00
Thomas Piccirello
a2d8e84e83 Match WebUI Peers table column order to GUI 2018-12-17 00:48:47 +02:00
Chocobo1
4a3648a693 Use gcc-5 for TravisCI linux builds
Remove workarounds for CXXFLAGS.
Using 3 compilation jobs should cause process trashing, tune it down to 2.
TravisCI container builds is deprecated, so remove the `sudo: false` command.
2018-12-17 00:48:43 +02:00
Chocobo1
baad45e638 Use CC, CXX from environment when available 2018-12-17 00:47:01 +02:00
Chocobo1
d9cb00aab2 Use correct locale to display date 2018-12-17 00:46:54 +02:00
Vladimir Golovnev (Glassez)
d703d98836 Show error message when Session failed to start 2018-12-17 00:41:30 +02:00
Thomas Piccirello
2f0646e7f0 Fetch data less frequently when torrents tab isn't visible 2018-12-17 00:41:28 +02:00
Thomas Piccirello
1a8a6dcef7 Add Search tab to WebUI
Closes #859, #8107.
2018-12-17 00:41:27 +02:00
Thomas Piccirello
990f961126 Allow tables to be added without a parent panel 2018-12-17 00:41:26 +02:00
Thomas Piccirello
06f04dea19 Simplify implementation 2018-12-17 00:41:25 +02:00
Thomas Piccirello
8eced2ef1f Add ability to pass urls to the webui download page 2018-12-17 00:41:24 +02:00
Tom Piccirello
1e486ea92e Fix JavaScript error
Fixes a JavaScript error caused by the element lookup returning null
2018-12-17 00:41:22 +02:00
Thomas Piccirello
b47f38675e Disallow setting a blank alternative WebUI location 2018-12-17 00:41:21 +02:00
Thomas Piccirello
864f3393a0 Add slow torrent options 2018-12-17 00:41:20 +02:00
Thomas Piccirello
cebef74326 Add "Use alternative Web UI" option 2018-12-17 00:41:19 +02:00
Thomas Piccirello
e257b35cac Add "Apply rate limit to peers on LAN" option 2018-12-17 00:41:17 +02:00
Thomas Piccirello
1f33991e4b Add email "From" option 2018-12-17 00:41:16 +02:00
Thomas Piccirello
794053f212 Set WebUI download options using set preferences
"Start torrent" and "Create subfolder" are now set depending on the user's set preferences, which matches the behavior exhibited by the GUI.
2018-12-17 00:41:14 +02:00
Thomas Piccirello
3a130e1f74 Show list of categories on WebUI download page 2018-12-17 00:41:13 +02:00
Thomas Piccirello
3423f93230 Hide WebUI text input for custom monitor save locations 2018-12-17 00:41:12 +02:00
Thomas Piccirello
2219167253 Add "When adding a torrent" options 2018-12-17 00:41:10 +02:00
Thomas Piccirello
a0a32b89a6 Add WebUI Auto TMM options 2018-12-17 00:41:08 +02:00
Thomas Piccirello
59162bf426 Replace all line breaks and fix legend code style. 2018-12-17 00:41:07 +02:00
Thomas Piccirello
dfd148f55f Add speed limit icons to WebUI Speed options 2018-12-17 00:41:05 +02:00
Thomas Piccirello
3af720b3bc Add WebUI Random port button and proxy unencrypted password notice 2018-12-17 00:41:04 +02:00
Thomas Piccirello
11240d0837 Replace WebUI Options fixed-width labels
This allows the labels to auto-expand based on the language used, and also removes unnecessary whitespace. Additionally, this results in a look more consistent with the GUI which right-aligns labels.
2018-12-17 00:40:53 +02:00
Thomas Piccirello
e64fd9c544 Reorder WebUI options to match GUI 2018-12-17 00:28:35 +02:00
FranciscoPombal
50ef812427 Add checking_mem_usage option to AdvancedSettings 2018-12-17 00:28:34 +02:00
thalieht
bd4d2fa424 Combine qAsConst() with copyAsConst() to asConst() 2018-12-17 00:28:33 +02:00
thalieht
e2ee928017 Convert all foreach() to range-based for() 2018-12-17 00:28:32 +02:00
thalieht
62e71a15a4 Fix coding style for various things 2018-12-17 00:28:31 +02:00
thalieht
c62127e9f1 Save option to start minimized in Mac 2018-12-17 00:28:29 +02:00
Chocobo1
2171d579ee Fix typo 2018-12-17 00:28:28 +02:00
Chocobo1
6e5a969e2d Use ip parameter from tracker request if provided
Closes #9949.
2018-12-17 00:28:28 +02:00
Chocobo1
bfbc7ef28a Use QHostAddress for storing IP 2018-12-17 00:28:26 +02:00
sledgehammer999
b1cefbf9b5 Autotools: Replace CPPFLAGS with CXXFLAGS 2018-12-17 00:28:25 +02:00
sledgehammer999
201638854e Autotools: Print Boost LDFLAGS nicer 2018-12-17 00:28:24 +02:00
sledgehammer999
847ecdeedb Autotools: Improve handling of C++ mode 2018-12-17 00:28:23 +02:00
Chocobo1
acc159fa60 Fix wrong locale used in log message 2018-12-17 00:28:22 +02:00
Chocobo1
bb7e80a8a6 Fix weekday names translations
Closes #9933.
2018-12-17 00:28:21 +02:00
Chocobo1
39973f1bb1 Fix strings not translated
Closes #9934.
2018-12-17 00:28:21 +02:00
Chocobo1
1e9151364a Clean up code 2018-12-17 00:28:20 +02:00
Vladimir Golovnev (Glassez)
fd50d6e9af Save torrents queue in separate file 2018-12-17 00:28:19 +02:00
Vladimir Golovnev (Glassez)
427acf0c46 Fix signed/unsigned integers comparison warning 2018-12-17 00:28:18 +02:00
Thomas Piccirello
f0a50424be Allow WebUI sidebar to be collapsed 2018-12-17 00:28:18 +02:00
Thomas Piccirello
aded9afc0e Show ellipsis when WebUI sidebar is too narrow 2018-12-17 00:28:17 +02:00
Thomas Piccirello
060b7480db Only instantiate SearchPluginManager as needed 2018-12-17 00:28:16 +02:00
Tom Piccirello
7f2a01dcd6 Fix WebUI bug on override of Start Download option
Disabled form values aren't submitted, causing the add_paused value not to be sent when Start Torrent was checked. qBittorrent would then fall back to the global Start Download preference.

Closes #9855.
2018-12-17 00:28:15 +02:00
Chocobo1
fef0e70c9f Fix missing words in WebUI
This is because Qt translator returns empty string when the translation
is not provided, now we fallback to the original string from source code.

Closes #9868.
2018-12-17 00:28:14 +02:00
Thomas Piccirello
9cc112aa4e Add SameSite attribute to WebUI session cookie
This attribute prevents the cookie from being submitted on any cross-site request, strongly limiting CSRF.

Closes #9877.
2018-12-17 00:28:14 +02:00
Chocobo1
44d4d41365 Put WebUI security related options into a groupbox 2018-12-17 00:28:13 +02:00
Chocobo1
a21c386dbf Add option for WebUI Host header validation
Closes #9743.
2018-12-17 00:28:12 +02:00
Thomas Piccirello
1c4139906a Show icon in WebUI sorted column 2018-12-17 00:28:11 +02:00
Chocobo1
1a21f45c75 Implement proper C++11 mode detection
Newer compilers have C++14 mode as default and package maintainers tend
to not specifying a C++ version when building a package, this causes
compatibility issues when (for example) qbt is compiled in C++11 and
dependency lib is in C++14. See issue #9485.

What this commit does:
1. Checks if compiler supports at least C++11
2. Checks if compiler is set in at least C++11 mode
2018-12-17 00:28:04 +02:00
244 changed files with 75848 additions and 57485 deletions

View File

@@ -4,6 +4,8 @@ os:
- linux - linux
- osx - osx
dist: xenial
env: env:
matrix: matrix:
# Uncomment when Travis upgraded "Ubuntu 12.04 LTS" to a newer version whose repo will have a more up-to-date libtorrent package # Uncomment when Travis upgraded "Ubuntu 12.04 LTS" to a newer version whose repo will have a more up-to-date libtorrent package
@@ -37,11 +39,6 @@ cache:
directories: directories:
- $HOME/hombebrew_cache - $HOME/hombebrew_cache
# opt-in Ubuntu Trusty
dist: trusty
# container-based builds
sudo: false
addons: addons:
coverity_scan: coverity_scan:
project: project:
@@ -53,34 +50,30 @@ addons:
notification_email: sledgehammer999@qbittorrent.org notification_email: sledgehammer999@qbittorrent.org
apt: apt:
sources: sources:
# sources list: https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json # sources list: https://github.com/travis-ci/apt-source-safelist/blob/master/ubuntu.json
- ubuntu-toolchain-r-test
#- boost-latest
- sourceline: 'ppa:qbittorrent-team/qbittorrent-stable' - sourceline: 'ppa:qbittorrent-team/qbittorrent-stable'
- sourceline: 'ppa:beineri/opt-qt551-trusty'
- sourceline: 'ppa:adrozdoff/cmake'
packages: packages:
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise # packages list: https://github.com/travis-ci/apt-package-safelist/blob/master/ubuntu-trusty
- [autoconf, automake, colormake] - [autoconf, automake, colormake]
- [cmake, ninja-build] - [ninja-build]
- libssl-dev - libssl-dev
- [libboost-dev, libboost-system-dev] - [libboost-dev, libboost-system-dev]
- libtorrent-rasterbar-dev - libtorrent-rasterbar-dev
- [qt55base, qt55svg, qt55tools] - [qtbase5-dev, qttools5-dev-tools, libqt5svg5-dev]
- [gcc-6, g++-6]
before_install: before_install:
# only allow specific build for coverity scan, others will stop # only allow specific build for coverity scan, others will stop
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" = "RC_1_0" -a "$gui" = true -a "$build_system" = "qmake" ]; then exit ; fi - if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" = "RC_1_0" -a "$gui" = true -a "$build_system" = "qmake" ]; then exit ; fi
- shopt -s expand_aliases - shopt -s expand_aliases
- alias make="colormake -j3" # Using nprocs/2 sometimes may fail (gcc is killed by system) - alias make="colormake -j2" # Using nprocs/2 sometimes may fail (gcc is killed by system)
- qbt_path="$HOME/qbt_install" - qbt_path="$HOME/qbt_install"
- | - |
if [ "$TRAVIS_OS_NAME" = "linux" ]; then if [ "$TRAVIS_OS_NAME" = "linux" ]; then
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH" qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
else else
qbtconf="$qbtconf --prefix="$qbt_path"" qbtconf="$qbtconf --prefix="$qbt_path""
CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedefs -Wno-inconsistent-missing-override"
fi fi
# options for specific branches # options for specific branches
@@ -89,14 +82,6 @@ before_install:
if [ "$TRAVIS_OS_NAME" = "linux" ]; then if [ "$TRAVIS_OS_NAME" = "linux" ]; then
# setup virtual display for after_success target # setup virtual display for after_success target
if [ "$gui" = true ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi ; if [ "$gui" = true ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi ;
# Qt 5
PATH=/opt/qt55/bin:${PATH}
if [ "$build_system" = "cmake" ]; then
COMPILER_VERSION=6
export CXX="${CXX}-${COMPILER_VERSION}" CC="${CC}-${COMPILER_VERSION}"
fi
fi fi
# print settings # print settings
@@ -137,6 +122,7 @@ install:
- | - |
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
export use_ccache=true export use_ccache=true
ccache -M 512M
ccache -V && ccache --show-stats && ccache --zero-stats ccache -V && ccache --show-stats && ccache --zero-stats
fi fi
@@ -155,16 +141,7 @@ script:
BUILD_TOOL="ninja" BUILD_TOOL="ninja"
fi fi
if [ "$build_system" = "qmake" ]; then if [ "$build_system" = "qmake" ]; then
if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$CXXFLAGS"
# For some reason for RC_1_1 we need to also specify the OpenSSL compiler/linker flags
# Homebrew doesn't symlink OpenSSL for security reasons
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --cflags openssl)" LDFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --libs openssl)"
sed -i "" -e "s/^\(CC.*&&\).*$/\1 $CC/" src/Makefile # workaround for Qt & ccache: https://bugreports.qt.io/browse/QTBUG-31034
sed -i "" -e "s/^\(CXX.*&&\).*$/\1 $CXX/" src/Makefile
sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs -Wno-inconsistent-missing-override/' src/Makefile
else
./bootstrap.sh && ./configure $qbtconf
fi
BUILD_TOOL="make" BUILD_TOOL="make"
fi fi
- $BUILD_TOOL && $BUILD_TOOL install - $BUILD_TOOL && $BUILD_TOOL install

View File

@@ -10,10 +10,18 @@ type = QT
minimum_perc = 23 minimum_perc = 23
mode = developer mode = developer
[qbittorrent.qbittorrentdesktop_master] [qbittorrent.qbittorrentdesktop_master]
source_file = dist/unix/qbittorrent.desktop source_file = dist/unix/qbittorrent.desktop
source_lang = en source_lang = en
type = DESKTOP type = DESKTOP
minimum_perc = 23 minimum_perc = 23
mode = developer mode = developer
[qbittorrent.qbittorrent_webui]
file_filter = src/webui/www/translations/webui_<lang>.ts
lang_map = pt: pt_PT
source_file = src/webui/www/translations/webui_en.ts
source_lang = en
type = QT
minimum_perc = 23
mode = developer

View File

@@ -1,3 +1,57 @@
* Mon Dec 24 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.5
- FEATURE: Add checking_mem_usage option to AdvancedSettings (FranciscoPombal)
- FEATURE: Save torrents queue in separate file. Now a new file named 'queue' is created, saving on each line the infohash of each queued torrent in sorted order. (glassez)
- BUGFIX: Fix regression on resuming torrents without metadata (thalieht)
- BUGFIX: Reorder and rename Tracker list context menu option (Thomas Piccirello)
- BUGFIX: Rename Tracker List columns (Thomas Piccirello)
- BUGFIX: Show error message when Session failed to start (glassez)
- BUGFIX: Embedded tracker: Use ip parameter from tracker request if provided (Chocobo1)
- BUGFIX: Fix weekday names translations (Chocobo1)
- BUGFIX: Fix strings not translated (Chocobo1)
- WEBUI: Change qBittorrent exit message to HTML5 (Chocobo1)
- WEBUI: Revise CSP header (Chocobo1)
- WEBUI: Enforce referrer-policy in WebUI (Chocobo1)
- WEBUI: Add torrent name filtering to WebUI (Thomas Piccirello)
- WEBUI: Send numeric status without translation (Thomas Piccirello)
- WEBUI: Add WebUI Trackers context menu (Thomas Piccirello)
- WEBUI: Add DHT, PeX, and LSD to WebUI Tracker list (Thomas Piccirello)
- WEBUI: Add additional Tracker columns to WebUI (Thomas Piccirello)
- WEBUI: Bump Web API version
- WEBUI: Fix display bugs in WebUI Files tab. Remove <IE9 support (Thomas Piccirello)
- WEBUI: Fix incorrect priority value sent from WebUI (Thomas Piccirello)
- WEBUI: Set priority for multiple files in one WebAPI request (Thomas Piccirello)
- WEBUI: Match WebUI Peers table column order to GUI (Thomas Piccirello)
- WEBUI: Fetch data less frequently when torrents tab isn't visible (Thomas Piccirello)
- WEBUI: Add Search tab to WebUI (Thomas Piccirello)
- WEBUI: Add ability to pass urls to the webui download page (Thomas Piccirello)
- WEBUI: Fix JavaScript error (Tom Piccirello)
- WEBUI: Disallow setting a blank alternative WebUI location (Thomas Piccirello)
- WEBUI: Add slow torrent options (Thomas Piccirello)
- WEBUI: Add "Use alternative Web UI" option (Thomas Piccirello)
- WEBUI: Add "Apply rate limit to peers on LAN" option (Thomas Piccirello)
- WEBUI: Add email "From" option (Thomas Piccirello)
- WEBUI: Set WebUI download options using set preferences (Thomas Piccirello)
- WEBUI: Show list of categories on WebUI download page (Thomas Piccirello)
- WEBUI: Hide WebUI text input for custom monitor save locations (Thomas Piccirello)
- WEBUI: Add "When adding a torrent" options (Thomas Piccirello)
- WEBUI: Add WebUI Auto TMM options (Thomas Piccirello)
- WEBUI: Add speed limit icons to WebUI Speed options (Thomas Piccirello)
- WEBUI: Add WebUI Random port button and proxy unencrypted password notice (Thomas Piccirello)
- WEBUI: Replace WebUI Options fixed-width labels (Thomas Piccirello)
- WEBUI: Reorder WebUI options to match GUI (Thomas Piccirello)
- WEBUI: Allow WebUI sidebar to be collapsed (Thomas Piccirello)
- WEBUI: Show ellipsis when WebUI sidebar is too narrow (Thomas Piccirello)
- WEBUI: Fix WebUI bug on override of Start Download option.Closes #9855. (Tom Piccirello)
- WEBUI: Fix missing words in WebUI (Chocobo1)
- WEBUI: Add SameSite attribute to WebUI session cookie (Thomas Piccirello)
- WEBUI: Put WebUI security related options into a groupbox (Chocobo1)
- WEBUI: Add option for WebUI Host header validation (Chocobo1)
- WEBUI: Show icon in WebUI sorted column (Thomas Piccirello)
- RSS: Keep track of REPACK/PROPER downloads. Closes #9898. (Stephen Dawkins)
- SEARCH: Only instantiate SearchPluginManager as needed (Thomas Piccirello)
- MACOS: Make file icon look like other macOS icons (Nick Korotysh)
- MACOS: Save option to start minimized in Mac (thalieht)
* Mon Nov 19 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.4 * Mon Nov 19 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.4
- FEATURE: Recognize *.ts files as previewable (silver) - FEATURE: Recognize *.ts files as previewable (silver)
- FEATURE: Allow to disable speed graphs (dzmat) - FEATURE: Allow to disable speed graphs (dzmat)

View File

@@ -5,6 +5,8 @@ BINDIR = @EXPAND_BINDIR@
DATADIR = @EXPAND_DATADIR@ DATADIR = @EXPAND_DATADIR@
MANPREFIX = @EXPAND_MANDIR@ MANPREFIX = @EXPAND_MANDIR@
QMAKE_CC = @QBT_CC@
QMAKE_CXX = @QBT_CXX@
QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@ QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@
EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@ EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@

476
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for qbittorrent v4.1.4. # Generated by GNU Autoconf 2.69 for qbittorrent v4.1.5.
# #
# Report bugs to <bugs.qbittorrent.org>. # Report bugs to <bugs.qbittorrent.org>.
# #
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='qbittorrent' PACKAGE_NAME='qbittorrent'
PACKAGE_TARNAME='qbittorrent' PACKAGE_TARNAME='qbittorrent'
PACKAGE_VERSION='v4.1.4' PACKAGE_VERSION='v4.1.5'
PACKAGE_STRING='qbittorrent v4.1.4' PACKAGE_STRING='qbittorrent v4.1.5'
PACKAGE_BUGREPORT='bugs.qbittorrent.org' PACKAGE_BUGREPORT='bugs.qbittorrent.org'
PACKAGE_URL='https://www.qbittorrent.org/' PACKAGE_URL='https://www.qbittorrent.org/'
@@ -595,6 +595,8 @@ QBT_REMOVE_CONFIG
QBT_ADD_CONFIG QBT_ADD_CONFIG
QBT_CONF_EXTRA_CFLAGS QBT_CONF_EXTRA_CFLAGS
QBT_CONF_INCLUDES QBT_CONF_INCLUDES
QBT_CXX
QBT_CC
EXPAND_MANDIR EXPAND_MANDIR
EXPAND_DATADIR EXPAND_DATADIR
EXPAND_BINDIR EXPAND_BINDIR
@@ -626,7 +628,6 @@ am__nodep
AMDEPBACKSLASH AMDEPBACKSLASH
AMDEP_FALSE AMDEP_FALSE
AMDEP_TRUE AMDEP_TRUE
am__quote
am__include am__include
DEPDIR DEPDIR
am__untar am__untar
@@ -709,7 +710,8 @@ PACKAGE_VERSION
PACKAGE_TARNAME PACKAGE_TARNAME
PACKAGE_NAME PACKAGE_NAME
PATH_SEPARATOR PATH_SEPARATOR
SHELL' SHELL
am__quote'
ac_subst_files='' ac_subst_files=''
ac_user_opts=' ac_user_opts='
enable_option_checking enable_option_checking
@@ -1297,7 +1299,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures qbittorrent v4.1.4 to adapt to many kinds of systems. \`configure' configures qbittorrent v4.1.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1368,7 +1370,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of qbittorrent v4.1.4:";; short | recursive ) echo "Configuration of qbittorrent v4.1.5:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1503,7 +1505,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
qbittorrent configure v4.1.4 qbittorrent configure v4.1.5
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1642,7 +1644,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by qbittorrent $as_me v4.1.4, which was It was created by qbittorrent $as_me v4.1.5, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@@ -3274,7 +3276,7 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
am__api_version='1.15' am__api_version='1.16'
# Find a good install program. We prefer a C program (faster), # Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or # so one script is as good as another. But avoid the broken or
@@ -3700,45 +3702,45 @@ DEPDIR="${am__leading_dot}deps"
ac_config_commands="$ac_config_commands depfiles" ac_config_commands="$ac_config_commands depfiles"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
am_make=${MAKE-make} $as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
cat > confinc << 'END' cat > confinc.mk << 'END'
am__doit: am__doit:
@echo this is the am__doit target @echo this is the am__doit target >confinc.out
.PHONY: am__doit .PHONY: am__doit
END END
# If we don't find an include directive, just comment out the code.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
$as_echo_n "checking for style of include used by $am_make... " >&6; }
am__include="#" am__include="#"
am__quote= am__quote=
_am_result=none # BSD make does it like this.
# First try GNU make style include. echo '.include "confinc.mk" # ignored' > confmf.BSD
echo "include confinc" > confmf # Other make implementations (GNU, Solaris 10, AIX) do it like this.
# Ignore all kinds of additional output from 'make'. echo 'include confinc.mk # ignored' > confmf.GNU
case `$am_make -s -f confmf 2> /dev/null` in #( _am_result=no
*the\ am__doit\ target*) for s in GNU BSD; do
am__include=include { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
am__quote= (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
_am_result=GNU ac_status=$?
;; echo "$as_me:$LINENO: \$? = $ac_status" >&5
esac (exit $ac_status); }
# Now try BSD make style include. case $?:`cat confinc.out 2>/dev/null` in #(
if test "$am__include" = "#"; then '0:this is the am__doit target') :
echo '.include "confinc"' > confmf case $s in #(
case `$am_make -s -f confmf 2> /dev/null` in #( BSD) :
*the\ am__doit\ target*) am__include='.include' am__quote='"' ;; #(
am__include=.include *) :
am__quote="\"" am__include='include' am__quote='' ;;
_am_result=BSD esac ;; #(
*) :
;; ;;
esac esac
fi if test "$am__include" != "#"; then
_am_result="yes ($s style)"
break
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 fi
$as_echo "$_am_result" >&6; } done
rm -f confinc confmf rm -f confinc.* confmf.*
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
$as_echo "${_am_result}" >&6; }
# Check whether --enable-dependency-tracking was given. # Check whether --enable-dependency-tracking was given.
if test "${enable_dependency_tracking+set}" = set; then : if test "${enable_dependency_tracking+set}" = set; then :
@@ -3820,7 +3822,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='qbittorrent' PACKAGE='qbittorrent'
VERSION='v4.1.4' VERSION='v4.1.5'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@@ -3850,8 +3852,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# For better backward compatibility. To be removed once Automake 1.9.x # For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see: # dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
mkdir_p='$(MKDIR_P)' mkdir_p='$(MKDIR_P)'
# We need awk for the "check" target (and possibly the TAP driver). The # We need awk for the "check" target (and possibly the TAP driver). The
@@ -4158,7 +4160,7 @@ END
Aborting the configuration process, to ensure you take notice of the issue. Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>. that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@@ -4170,7 +4172,9 @@ END
fi fi
# use compiler from env variables if available
QBT_CC="$CC"
QBT_CXX="$CXX"
# Define --wth-* and --enable-* arguments # Define --wth-* and --enable-* arguments
@@ -4997,10 +5001,10 @@ $as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;}
$as_echo "#define HAVE_BOOST /**/" >>confdefs.h $as_echo "#define HAVE_BOOST /**/" >>confdefs.h
# execute ACTION-IF-FOUND (if present): # execute ACTION-IF-FOUND (if present):
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\" { $as_echo "$as_me:${as_lineno-$LINENO}: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&5
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5 $as_echo "$as_me: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&6;}
$as_echo "$as_me: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\" { $as_echo "$as_me:${as_lineno-$LINENO}: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;} $as_echo "$as_me: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
fi fi
CPPFLAGS="$CPPFLAGS_SAVED" CPPFLAGS="$CPPFLAGS_SAVED"
@@ -5011,16 +5015,10 @@ fi
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
# add workaround for problematic boost version # add workaround for problematic boost version
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# taken from ax_boost_base.m4 # taken from ax_boost_base.m4
@@ -5041,12 +5039,6 @@ else
QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES" QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
@@ -5400,7 +5392,7 @@ else
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; } $as_echo "yes" >&6; }
CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS" CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
LIBS="$libtorrent_LIBS $LIBS" LIBS="$libtorrent_LIBS $LIBS"
fi fi
@@ -5493,10 +5485,116 @@ else
zlib_LIBS=$pkg_cv_zlib_LIBS zlib_LIBS=$pkg_cv_zlib_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; } $as_echo "yes" >&6; }
CPPFLAGS="$zlib_CFLAGS $CPPFLAGS" CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
LIBS="$zlib_LIBS $LIBS" LIBS="$zlib_LIBS $LIBS"
fi fi
# Check if already in >= C++11 mode because of the flags returned by one of the above packages
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler is using C++11 or later mode" >&5
$as_echo_n "checking if compiler is using C++11 or later mode... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
QBT_CXX11_FOUND="yes"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
QBT_CXX11_FOUND="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# In case of no, check if the compiler can support at least C++11
# and if yes, enable it leaving a warning to the user
if test "x$QBT_CXX11_FOUND" = "xno"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports C++11" >&5
$as_echo_n "checking if compiler supports C++11... " >&6; }
TMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -std=c++11"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++11 is disabled by the set compiler flags" >&5
$as_echo_n "checking if C++11 is disabled by the set compiler flags... " >&6; }
# prepend the flag so it won't override conflicting user defined flags
CXXFLAGS="-std=c++11 $TMP_CXXFLAGS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CXXFLAGS="$TMP_CXXFLAGS -std=c++11"
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C++11 mode is now force enabled.
Make sure you use the same C++ mode for qBittorrent and its dependencies.
To explicitly set qBittorrent to a later mode use CXXFLAGS.
Example: \`CXXFLAGS=\"\$CXXFLAGS -std=c++14\" ./configure\`" >&5
$as_echo "$as_me: WARNING: C++11 mode is now force enabled.
Make sure you use the same C++ mode for qBittorrent and its dependencies.
To explicitly set qBittorrent to a later mode use CXXFLAGS.
Example: \`CXXFLAGS=\"\$CXXFLAGS -std=c++14\" ./configure\`" >&2;}
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
as_fn_error $? "The compiler supports C++11 but the user or a dependency has explicitly enabled a lower mode." "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "A compiler supporting C++11 is required." "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
# These are required because autoconf doesn't expand these **particular** # These are required because autoconf doesn't expand these **particular**
# vars automatically. And qmake cannot autoexpand them. # vars automatically. And qmake cannot autoexpand them.
@@ -5583,15 +5681,15 @@ extract() {
for i in $string; do for i in $string; do
case "$(echo "$i" | cut -c1)" in case "$(echo "$i" | cut -c1)" in
'') ;; '') ;;
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";; D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";; I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";; *) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
esac esac
done done
IFS=$SAVEIFS IFS=$SAVEIFS
} }
extract "$CFLAGS $CPPFLAGS $CXXFLAGS" extract "$CFLAGS $CXXFLAGS"
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES" QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
# Substitute the values of these vars in conf.pri.in # Substitute the values of these vars in conf.pri.in
@@ -5602,6 +5700,8 @@ QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
ac_config_files="$ac_config_files conf.pri" ac_config_files="$ac_config_files conf.pri"
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
@@ -6174,7 +6274,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by qbittorrent $as_me v4.1.4, which was This file was extended by qbittorrent $as_me v4.1.5, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -6232,7 +6332,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
qbittorrent config.status v4.1.4 qbittorrent config.status v4.1.5
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
@@ -6340,7 +6440,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# #
# INIT-COMMANDS # INIT-COMMANDS
# #
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
_ACEOF _ACEOF
@@ -6785,29 +6885,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
# Older Autoconf quotes --file arguments for eval, but not when files # Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval # are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting. # if we detect the quoting.
case $CONFIG_FILES in # TODO: see whether this extra hack can be removed once we start
*\'*) eval set x "$CONFIG_FILES" ;; # requiring Autoconf 2.70 or later.
*) set x $CONFIG_FILES ;; case $CONFIG_FILES in #(
esac *\'*) :
eval set x "$CONFIG_FILES" ;; #(
*) :
set x $CONFIG_FILES ;; #(
*) :
;;
esac
shift shift
for mf # Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do do
# Strip MF so we end up with the name of the file. # Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'` am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not. # Check whether this is an Automake generated Makefile which includes
# We used to match only the files named 'Makefile.in', but # dependency-tracking related rules and includes.
# some people rename them; so instead we look at the file content. # Grep'ing the whole file directly is not great: AIX grep has a line
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000. # limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
dirpart=`$as_dirname -- "$mf" || || continue
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ am_dirpart=`$as_dirname -- "$am_mf" ||
X"$mf" : 'X\(//\)[^/]' \| \ $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \
X"$mf" : 'X\(/\)' \| . 2>/dev/null || X"$am_mf" : 'X\(//\)$' \| \
$as_echo X"$mf" | X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$am_mf" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/ s//\1/
q q
@@ -6825,53 +6931,48 @@ $as_echo X"$mf" |
q q
} }
s/.*/./; q'` s/.*/./; q'`
else am_filepart=`$as_basename -- "$am_mf" ||
continue $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
fi X"$am_mf" : 'X\(//\)$' \| \
# Extract the definition of DEPDIR, am__include, and am__quote X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
# from the Makefile without running 'make'. $as_echo X/"$am_mf" |
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` sed '/^.*\/\([^/][^/]*\)\/*$/{
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`$as_dirname -- "$file" ||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$file" : 'X\(//\)[^/]' \| \
X"$file" : 'X\(//\)$' \| \
X"$file" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/ s//\1/
q q
} }
/^X\(\/\/\)[^/].*/{ /^X\/\(\/\/\)$/{
s//\1/ s//\1/
q q
} }
/^X\(\/\/\)$/{ /^X\/\(\/\).*/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/ s//\1/
q q
} }
s/.*/./; q'` s/.*/./; q'`
as_dir=$dirpart/$fdir; as_fn_mkdir_p { echo "$as_me:$LINENO: cd "$am_dirpart" \
# echo "creating $dirpart/$file" && sed -e '/# am--include-marker/d' "$am_filepart" \
echo '# dummy' > "$dirpart/$file" | $MAKE -f - am--depfiles" >&5
done (cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } || am_rc=$?
done done
if test $am_rc -ne 0; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. Try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).
See \`config.log' for more details" "$LINENO" 5; }
fi
{ am_dirpart=; unset am_dirpart;}
{ am_filepart=; unset am_filepart;}
{ am_mf=; unset am_mf;}
{ am_rc=; unset am_rc;}
rm -f conftest-deps.mk
} }
;; ;;
@@ -7489,7 +7590,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by qbittorrent $as_me v4.1.4, which was This file was extended by qbittorrent $as_me v4.1.5, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -7547,7 +7648,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
qbittorrent config.status v4.1.4 qbittorrent config.status v4.1.5
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
@@ -7655,7 +7756,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# #
# INIT-COMMANDS # INIT-COMMANDS
# #
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
_ACEOF _ACEOF
@@ -8101,29 +8202,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
# Older Autoconf quotes --file arguments for eval, but not when files # Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval # are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting. # if we detect the quoting.
case $CONFIG_FILES in # TODO: see whether this extra hack can be removed once we start
*\'*) eval set x "$CONFIG_FILES" ;; # requiring Autoconf 2.70 or later.
*) set x $CONFIG_FILES ;; case $CONFIG_FILES in #(
esac *\'*) :
eval set x "$CONFIG_FILES" ;; #(
*) :
set x $CONFIG_FILES ;; #(
*) :
;;
esac
shift shift
for mf # Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do do
# Strip MF so we end up with the name of the file. # Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'` am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not. # Check whether this is an Automake generated Makefile which includes
# We used to match only the files named 'Makefile.in', but # dependency-tracking related rules and includes.
# some people rename them; so instead we look at the file content. # Grep'ing the whole file directly is not great: AIX grep has a line
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000. # limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
dirpart=`$as_dirname -- "$mf" || || continue
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ am_dirpart=`$as_dirname -- "$am_mf" ||
X"$mf" : 'X\(//\)[^/]' \| \ $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \
X"$mf" : 'X\(/\)' \| . 2>/dev/null || X"$am_mf" : 'X\(//\)$' \| \
$as_echo X"$mf" | X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$am_mf" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/ s//\1/
q q
@@ -8141,53 +8248,48 @@ $as_echo X"$mf" |
q q
} }
s/.*/./; q'` s/.*/./; q'`
else am_filepart=`$as_basename -- "$am_mf" ||
continue $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
fi X"$am_mf" : 'X\(//\)$' \| \
# Extract the definition of DEPDIR, am__include, and am__quote X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
# from the Makefile without running 'make'. $as_echo X/"$am_mf" |
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` sed '/^.*\/\([^/][^/]*\)\/*$/{
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`$as_dirname -- "$file" ||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$file" : 'X\(//\)[^/]' \| \
X"$file" : 'X\(//\)$' \| \
X"$file" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/ s//\1/
q q
} }
/^X\(\/\/\)[^/].*/{ /^X\/\(\/\/\)$/{
s//\1/ s//\1/
q q
} }
/^X\(\/\/\)$/{ /^X\/\(\/\).*/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/ s//\1/
q q
} }
s/.*/./; q'` s/.*/./; q'`
as_dir=$dirpart/$fdir; as_fn_mkdir_p { echo "$as_me:$LINENO: cd "$am_dirpart" \
# echo "creating $dirpart/$file" && sed -e '/# am--include-marker/d' "$am_filepart" \
echo '# dummy' > "$dirpart/$file" | $MAKE -f - am--depfiles" >&5
done (cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } || am_rc=$?
done done
if test $am_rc -ne 0; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. Try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).
See \`config.log' for more details" "$LINENO" 5; }
fi
{ am_dirpart=; unset am_dirpart;}
{ am_filepart=; unset am_filepart;}
{ am_mf=; unset am_mf;}
{ am_rc=; unset am_rc;}
rm -f conftest-deps.mk
} }
;; ;;

View File

@@ -1,4 +1,4 @@
AC_INIT([qbittorrent], [v4.1.4], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/]) AC_INIT([qbittorrent], [v4.1.5], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC AC_PROG_CC
@@ -8,7 +8,9 @@ AC_LANG(C++)
AC_CANONICAL_HOST AC_CANONICAL_HOST
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
# use compiler from env variables if available
QBT_CC="$CC"
QBT_CXX="$CXX"
# Define --wth-* and --enable-* arguments # Define --wth-* and --enable-* arguments
@@ -162,14 +164,13 @@ AS_CASE(["x$enable_qt_dbus"],
AX_BOOST_BASE([1.35], AX_BOOST_BASE([1.35],
[AC_MSG_NOTICE([Boost CPPFLAGS: "$BOOST_CPPFLAGS" [AC_MSG_NOTICE([Boost CXXFLAGS: "$BOOST_CPPFLAGS"])
Boost LDFLAGS: "$BOOST_LDFLAGS"])], AC_MSG_NOTICE([Boost LDFLAGS: "$BOOST_LDFLAGS"])],
[AC_MSG_ERROR([Could not find Boost])]) [AC_MSG_ERROR([Could not find Boost])])
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
# add workaround for problematic boost version # add workaround for problematic boost version
AC_LANG_PUSH(C++)
# taken from ax_boost_base.m4 # taken from ax_boost_base.m4
m4_define([DETECT_BOOST_VERSION_PROGRAM], m4_define([DETECT_BOOST_VERSION_PROGRAM],
[AC_LANG_PROGRAM([[#include <boost/version.hpp>]], [AC_LANG_PROGRAM([[#include <boost/version.hpp>]],
@@ -177,7 +178,6 @@ m4_define([DETECT_BOOST_VERSION_PROGRAM],
AC_COMPILE_IFELSE([DETECT_BOOST_VERSION_PROGRAM(106000)], [], AC_COMPILE_IFELSE([DETECT_BOOST_VERSION_PROGRAM(106000)], [],
[QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"]) [QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"])
AC_LANG_POP([C++])
AX_BOOST_SYSTEM() AX_BOOST_SYSTEM()
AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"]) AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"])
@@ -196,14 +196,46 @@ AS_CASE(["x$with_qtsingleapplication"],
PKG_CHECK_MODULES(libtorrent, PKG_CHECK_MODULES(libtorrent,
[libtorrent-rasterbar >= 1.0.6], [libtorrent-rasterbar >= 1.0.6],
[CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS" [CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
LIBS="$libtorrent_LIBS $LIBS"]) LIBS="$libtorrent_LIBS $LIBS"])
PKG_CHECK_MODULES(zlib, PKG_CHECK_MODULES(zlib,
[zlib >= 1.2.5.2], [zlib >= 1.2.5.2],
[CPPFLAGS="$zlib_CFLAGS $CPPFLAGS" [CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
LIBS="$zlib_LIBS $LIBS"]) LIBS="$zlib_LIBS $LIBS"])
# Check if already in >= C++11 mode because of the flags returned by one of the above packages
AC_MSG_CHECKING([if compiler is using C++11 or later mode])
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
[AC_MSG_RESULT([yes])
QBT_CXX11_FOUND="yes"],
[AC_MSG_RESULT([no])
QBT_CXX11_FOUND="no"])
# In case of no, check if the compiler can support at least C++11
# and if yes, enable it leaving a warning to the user
AS_IF([test "x$QBT_CXX11_FOUND" = "xno"],
[AC_MSG_CHECKING([if compiler supports C++11])
TMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -std=c++11"
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
[AC_MSG_RESULT([yes])
AC_MSG_CHECKING([if C++11 is disabled by the set compiler flags])
# prepend the flag so it won't override conflicting user defined flags
CXXFLAGS="-std=c++11 $TMP_CXXFLAGS"
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
[AC_MSG_RESULT([no])
CXXFLAGS="$TMP_CXXFLAGS -std=c++11"
AC_MSG_WARN([C++11 mode is now force enabled.
Make sure you use the same C++ mode for qBittorrent and its dependencies.
To explicitly set qBittorrent to a later mode use CXXFLAGS.
Example: `CXXFLAGS="\$CXXFLAGS -std=c++14" ./configure`])],
[AC_MSG_RESULT([yes])
AC_MSG_ERROR([The compiler supports C++11 but the user or a dependency has explicitly enabled a lower mode.])])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([A compiler supporting C++11 is required.])])
])
# These are required because autoconf doesn't expand these **particular** # These are required because autoconf doesn't expand these **particular**
# vars automatically. And qmake cannot autoexpand them. # vars automatically. And qmake cannot autoexpand them.
AX_DEFINE_DIR([EXPAND_PREFIX], [prefix]) AX_DEFINE_DIR([EXPAND_PREFIX], [prefix])
@@ -230,18 +262,20 @@ extract() {
for i in $string; do for i in $string; do
case "$(echo "$i" | cut -c1)" in case "$(echo "$i" | cut -c1)" in
'') ;; '') ;;
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";; D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";; I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";; *) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
esac esac
done done
IFS=$SAVEIFS IFS=$SAVEIFS
} }
extract "$CFLAGS $CPPFLAGS $CXXFLAGS" extract "$CFLAGS $CXXFLAGS"
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES" QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
# Substitute the values of these vars in conf.pri.in # Substitute the values of these vars in conf.pri.in
AC_SUBST(QBT_CC)
AC_SUBST(QBT_CXX)
AC_SUBST(QBT_CONF_INCLUDES) AC_SUBST(QBT_CONF_INCLUDES)
AC_SUBST(QBT_CONF_EXTRA_CFLAGS) AC_SUBST(QBT_CONF_EXTRA_CFLAGS)
AC_SUBST(QBT_ADD_CONFIG) AC_SUBST(QBT_ADD_CONFIG)

2
dist/mac/Info.plist vendored
View File

@@ -45,7 +45,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>4.1.4</string> <string>4.1.5</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>qBit</string> <string>qBit</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>

Binary file not shown.

View File

@@ -27,7 +27,7 @@ XPStyle on
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path !define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
; Program specific ; Program specific
!define PROG_VERSION "4.1.4" !define PROG_VERSION "4.1.5"
!define MUI_FINISHPAGE_RUN !define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun !define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun

View File

@@ -36,3 +36,16 @@ AC_DEFUN([FIND_QTDBUS],
[AC_MSG_RESULT([not found]) [AC_MSG_RESULT([not found])
HAVE_QTDBUS=[false]]) HAVE_QTDBUS=[false]])
]) ])
# DETECT_CPP11_PROGRAM()
# Detects if at least C++11 mode is enabled.
# --------------------------------------
AC_DEFUN([DETECT_CPP11_PROGRAM],
[AC_LANG_PROGRAM([[
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#endif]],
[[]])
])

View File

@@ -44,6 +44,7 @@
#endif #endif
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
#include <QMessageBox>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QSessionManager> #include <QSessionManager>
#include <QSharedMemory> #include <QSharedMemory>
@@ -61,6 +62,7 @@
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/exceptions.h"
#include "base/iconprovider.h" #include "base/iconprovider.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
@@ -428,7 +430,7 @@ void Application::processParams(const QStringList &params)
BitTorrent::AddTorrentParams torrentParams; BitTorrent::AddTorrentParams torrentParams;
TriStateBool skipTorrentDialog; TriStateBool skipTorrentDialog;
foreach (QString param, params) { for (QString param : params) {
param = param.trimmed(); param = param.trimmed();
// Process strings indicating options specified by the user. // Process strings indicating options specified by the user.
@@ -495,27 +497,42 @@ int Application::exec(const QStringList &params)
GuiIconProvider::initInstance(); GuiIconProvider::initInstance();
#endif #endif
BitTorrent::Session::initInstance(); try {
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentFinished, this, &Application::torrentFinished); BitTorrent::Session::initInstance();
connect(BitTorrent::Session::instance(), &BitTorrent::Session::allTorrentsFinished, this, &Application::allTorrentsFinished, Qt::QueuedConnection); connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentFinished, this, &Application::torrentFinished);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::allTorrentsFinished, this, &Application::allTorrentsFinished, Qt::QueuedConnection);
#ifndef DISABLE_COUNTRIES_RESOLUTION #ifndef DISABLE_COUNTRIES_RESOLUTION
Net::GeoIPManager::initInstance(); Net::GeoIPManager::initInstance();
#endif #endif
ScanFoldersModel::initInstance(this); ScanFoldersModel::initInstance(this);
#ifndef DISABLE_WEBUI #ifndef DISABLE_WEBUI
m_webui = new WebUI; m_webui = new WebUI;
#ifdef DISABLE_GUI #ifdef DISABLE_GUI
if (m_webui->isErrored()) if (m_webui->isErrored())
return 1; return 1;
connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); }); connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); });
#endif // DISABLE_GUI #endif // DISABLE_GUI
#endif // DISABLE_WEBUI #endif // DISABLE_WEBUI
new RSS::Session; // create RSS::Session singleton new RSS::Session; // create RSS::Session singleton
new RSS::AutoDownloader; // create RSS::AutoDownloader singleton new RSS::AutoDownloader; // create RSS::AutoDownloader singleton
new SearchPluginManager; }
catch (const RuntimeError &err) {
#ifdef DISABLE_GUI
fprintf(stderr, "%s", err.what());
#else
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(tr("Application failed to start."));
msgBox.setInformativeText(err.message());
msgBox.show(); // Need to be shown or to moveToCenter does not work
msgBox.move(Utils::Misc::screenCenter(&msgBox));
msgBox.exec();
#endif
return 1;
}
#ifdef DISABLE_GUI #ifdef DISABLE_GUI
#ifndef DISABLE_WEBUI #ifndef DISABLE_WEBUI
@@ -710,7 +727,6 @@ void Application::cleanup()
delete m_webui; delete m_webui;
#endif #endif
delete SearchPluginManager::instance();
delete RSS::AutoDownloader::instance(); delete RSS::AutoDownloader::instance();
delete RSS::Session::instance(); delete RSS::Session::instance();
@@ -726,6 +742,7 @@ void Application::cleanup()
delete m_fileLogger; delete m_fileLogger;
Logger::freeInstance(); Logger::freeInstance();
IconProvider::freeInstance(); IconProvider::freeInstance();
SearchPluginManager::freeInstance();
Utils::Fs::removeDirRecursive(Utils::Fs::tempPath()); Utils::Fs::removeDirRecursive(Utils::Fs::tempPath());
#ifndef DISABLE_GUI #ifndef DISABLE_GUI

View File

@@ -41,6 +41,7 @@
#include <QMessageBox> #include <QMessageBox>
#endif #endif
#include "base/global.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/string.h" #include "base/utils/string.h"
@@ -486,7 +487,7 @@ CommandLineParameterError::CommandLineParameterError(const QString &messageForUs
{ {
} }
const QString& CommandLineParameterError::messageForUser() const const QString &CommandLineParameterError::messageForUser() const
{ {
return m_messageForUser; return m_messageForUser;
} }
@@ -497,7 +498,7 @@ QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN
QStringList lines = {words.first()}; QStringList lines = {words.first()};
int currentLineMaxLength = wrapAtColumn - initialIndentation; int currentLineMaxLength = wrapAtColumn - initialIndentation;
foreach (const QString &word, words.mid(1)) { for (const QString &word : asConst(words.mid(1))) {
if (lines.last().length() + word.length() + 1 < currentLineMaxLength) { if (lines.last().length() + word.length() + 1 < currentLineMaxLength) {
lines.last().append(' ' + word); lines.last().append(' ' + word);
} }

View File

@@ -33,6 +33,7 @@
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
@@ -50,7 +51,7 @@ FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize
this->deleteOld(age, ageType); this->deleteOld(age, ageType);
const Logger *const logger = Logger::instance(); const Logger *const logger = Logger::instance();
foreach (const Log::Msg &msg, logger->getMessages()) for (const Log::Msg &msg : asConst(logger->getMessages()))
addLogMessage(msg); addLogMessage(msg);
connect(logger, &Logger::newLogMessage, this, &FileLogger::addLogMessage); connect(logger, &Logger::newLogMessage, this, &FileLogger::addLogMessage);
@@ -87,7 +88,7 @@ void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
QDateTime date = QDateTime::currentDateTime(); QDateTime date = QDateTime::currentDateTime();
QDir dir(Utils::Fs::branchPath(m_path)); QDir dir(Utils::Fs::branchPath(m_path));
foreach (const QFileInfo file, dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed)) { for (const QFileInfo &file : asConst(dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed))) {
QDateTime modificationDate = file.lastModified(); QDateTime modificationDate = file.lastModified();
switch (ageType) { switch (ageType) {
case DAYS: case DAYS:

View File

@@ -202,7 +202,7 @@ int main(int argc, char *argv[])
// this is the default in Qt6 // this is the default in Qt6
app->setAttribute(Qt::AA_DisableWindowContextHelpButton); app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
#endif #endif
#endif #endif // Q_OS_WIN
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
// Since Apple made difficult for users to set PATH, we set here for convenience. // Since Apple made difficult for users to set PATH, we set here for convenience.

View File

@@ -83,7 +83,7 @@ bool userAcceptsUpgrade()
msgBox.move(Utils::Misc::screenCenter(&msgBox)); msgBox.move(Utils::Misc::screenCenter(&msgBox));
if (msgBox.exec() == QMessageBox::Ok) if (msgBox.exec() == QMessageBox::Ok)
return true; return true;
#endif #endif // DISABLE_GUI
return false; return false;
} }
@@ -179,9 +179,9 @@ bool upgrade(bool ask = true)
// **************************************************************************************** // ****************************************************************************************
// Silently converts old v3.3.x .fastresume files // Silently converts old v3.3.x .fastresume files
QStringList backupFiles_3_3 = backupFolderDir.entryList( const QStringList backupFiles_3_3 = backupFolderDir.entryList(
QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted); QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted);
foreach (const QString &backupFile, backupFiles_3_3) for (const QString &backupFile : backupFiles_3_3)
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile)); upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
// **************************************************************************************** // ****************************************************************************************
@@ -197,10 +197,10 @@ bool upgrade(bool ask = true)
if (ask && !userAcceptsUpgrade()) return false; if (ask && !userAcceptsUpgrade()) return false;
QStringList backupFiles = backupFolderDir.entryList( const QStringList backupFiles = backupFolderDir.entryList(
QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted); QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted);
const QRegularExpression rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); const QRegularExpression rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
foreach (QString backupFile, backupFiles) { for (const QString &backupFile : backupFiles) {
const QRegularExpressionMatch rxMatch = rx.match(backupFile); const QRegularExpressionMatch rxMatch = rx.match(backupFile);
if (rxMatch.hasMatch()) { if (rxMatch.hasMatch()) {
const QString hashStr = rxMatch.captured(1); const QString hashStr = rxMatch.captured(1);
@@ -265,7 +265,7 @@ void migratePlistToIni(const QString &application)
plistFile->setFallbacksEnabled(false); plistFile->setFallbacksEnabled(false);
const QStringList plist = plistFile->allKeys(); const QStringList plist = plistFile->allKeys();
if (!plist.isEmpty()) { if (!plist.isEmpty()) {
foreach (const QString &key, plist) for (const QString &key : plist)
iniFile.setValue(key, plistFile->value(key)); iniFile.setValue(key, plistFile->value(key));
plistFile->clear(); plistFile->clear();
} }

View File

@@ -4,6 +4,7 @@ add_library(qbt_base STATIC
# headers # headers
bittorrent/addtorrentparams.h bittorrent/addtorrentparams.h
bittorrent/cachestatus.h bittorrent/cachestatus.h
bittorrent/filepriority.h
bittorrent/infohash.h bittorrent/infohash.h
bittorrent/magneturi.h bittorrent/magneturi.h
bittorrent/peerinfo.h bittorrent/peerinfo.h
@@ -76,6 +77,7 @@ types.h
unicodestrings.h unicodestrings.h
# sources # sources
bittorrent/filepriority.cpp
bittorrent/infohash.cpp bittorrent/infohash.cpp
bittorrent/magneturi.cpp bittorrent/magneturi.cpp
bittorrent/peerinfo.cpp bittorrent/peerinfo.cpp

View File

@@ -38,12 +38,12 @@ AsyncFileStorage::AsyncFileStorage(const QString &storageFolderPath, QObject *pa
, m_lockFile(m_storageDir.absoluteFilePath(QStringLiteral("storage.lock"))) , m_lockFile(m_storageDir.absoluteFilePath(QStringLiteral("storage.lock")))
{ {
if (!m_storageDir.mkpath(m_storageDir.absolutePath())) if (!m_storageDir.mkpath(m_storageDir.absolutePath()))
throw AsyncFileStorageError( throw AsyncFileStorageError {tr("Could not create directory '%1'.")
QString("Could not create directory '%1'.").arg(m_storageDir.absolutePath())); .arg(m_storageDir.absolutePath())};
// TODO: This folder locking approach does not work for UNIX systems. Implement it. // TODO: This folder locking approach does not work for UNIX systems. Implement it.
if (!m_lockFile.open(QFile::WriteOnly)) if (!m_lockFile.open(QFile::WriteOnly))
throw AsyncFileStorageError(m_lockFile.errorString()); throw AsyncFileStorageError {m_lockFile.errorString()};
} }
AsyncFileStorage::~AsyncFileStorage() AsyncFileStorage::~AsyncFileStorage()
@@ -76,13 +76,3 @@ void AsyncFileStorage::store_impl(const QString &fileName, const QByteArray &dat
} }
} }
} }
AsyncFileStorageError::AsyncFileStorageError(const QString &message)
: std::runtime_error(message.toUtf8().data())
{
}
QString AsyncFileStorageError::message() const
{
return what();
}

View File

@@ -28,22 +28,22 @@
#pragma once #pragma once
#include <stdexcept>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QObject> #include <QObject>
class AsyncFileStorageError : public std::runtime_error #include "base/exceptions.h"
class AsyncFileStorageError : public RuntimeError
{ {
public: public:
explicit AsyncFileStorageError(const QString &message); using RuntimeError::RuntimeError;
QString message() const;
}; };
class AsyncFileStorage : public QObject class AsyncFileStorage : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(AsyncFileStorage)
public: public:
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr); explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);

View File

@@ -3,6 +3,7 @@ HEADERS += \
$$PWD/asyncfilestorage.h \ $$PWD/asyncfilestorage.h \
$$PWD/bittorrent/addtorrentparams.h \ $$PWD/bittorrent/addtorrentparams.h \
$$PWD/bittorrent/cachestatus.h \ $$PWD/bittorrent/cachestatus.h \
$$PWD/bittorrent/filepriority.h \
$$PWD/bittorrent/infohash.h \ $$PWD/bittorrent/infohash.h \
$$PWD/bittorrent/magneturi.h \ $$PWD/bittorrent/magneturi.h \
$$PWD/bittorrent/peerinfo.h \ $$PWD/bittorrent/peerinfo.h \
@@ -75,6 +76,7 @@ HEADERS += \
SOURCES += \ SOURCES += \
$$PWD/asyncfilestorage.cpp \ $$PWD/asyncfilestorage.cpp \
$$PWD/bittorrent/filepriority.cpp \
$$PWD/bittorrent/infohash.cpp \ $$PWD/bittorrent/infohash.cpp \
$$PWD/bittorrent/magneturi.cpp \ $$PWD/bittorrent/magneturi.cpp \
$$PWD/bittorrent/peerinfo.cpp \ $$PWD/bittorrent/peerinfo.cpp \

View File

@@ -0,0 +1,46 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#include "filepriority.h"
namespace BitTorrent
{
bool isValidFilePriority(const BitTorrent::FilePriority priority)
{
switch (priority) {
case BitTorrent::FilePriority::Ignored:
case BitTorrent::FilePriority::Normal:
case BitTorrent::FilePriority::High:
case BitTorrent::FilePriority::Maximum:
case BitTorrent::FilePriority::Mixed:
return true;
default:
return false;
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#pragma once
namespace BitTorrent
{
enum class FilePriority : int
{
Ignored = 0,
Normal = 1,
High = 6,
Maximum = 7,
Mixed = -1
};
bool isValidFilePriority(BitTorrent::FilePriority priority);
}

View File

@@ -83,10 +83,10 @@ MagnetUri::MagnetUri(const QString &source)
m_hash = m_addTorrentParams.info_hash; m_hash = m_addTorrentParams.info_hash;
m_name = QString::fromStdString(m_addTorrentParams.name); m_name = QString::fromStdString(m_addTorrentParams.name);
foreach (const std::string &tracker, m_addTorrentParams.trackers) for (const std::string &tracker : m_addTorrentParams.trackers)
m_trackers.append(QString::fromStdString(tracker)); m_trackers.append(QString::fromStdString(tracker));
foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds) for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
m_urlSeeds.append(QUrl(urlSeed.c_str())); m_urlSeeds.append(QUrl(urlSeed.c_str()));
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -39,18 +39,23 @@ ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath
{ {
} }
void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data) const void ResumeDataSavingManager::save(const QString &filename, const QByteArray &data) const
{ {
QString filename = QString("%1.fastresume").arg(infoHash); const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
QString filepath = m_resumeDataDir.absoluteFilePath(filename);
qDebug() << "Saving resume data in" << filepath; QSaveFile file {filepath};
QSaveFile resumeFile(filepath); if (file.open(QIODevice::WriteOnly)) {
if (resumeFile.open(QIODevice::WriteOnly)) { file.write(data);
resumeFile.write(data); if (!file.commit()) {
if (!resumeFile.commit()) { Logger::instance()->addMessage(QString("Couldn't save data in '%1'. Error: %2")
Logger::instance()->addMessage(QString("Couldn't save resume data in %1. Error: %2") .arg(filepath, file.errorString()), Log::WARNING);
.arg(filepath, resumeFile.errorString()), Log::WARNING);
} }
} }
} }
void ResumeDataSavingManager::remove(const QString &filename) const
{
const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
Utils::Fs::forceRemove(filepath);
}

View File

@@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -26,8 +26,7 @@
* exception statement from your version. * exception statement from your version.
*/ */
#ifndef RESUMEDATASAVINGMANAGER_H #pragma once
#define RESUMEDATASAVINGMANAGER_H
#include <QByteArray> #include <QByteArray>
#include <QDir> #include <QDir>
@@ -36,15 +35,15 @@
class ResumeDataSavingManager : public QObject class ResumeDataSavingManager : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(ResumeDataSavingManager)
public: public:
explicit ResumeDataSavingManager(const QString &resumeFolderPath); explicit ResumeDataSavingManager(const QString &resumeFolderPath);
public slots: public slots:
void saveResumeData(QString infoHash, QByteArray data) const; void save(const QString &filename, const QByteArray &data) const;
void remove(const QString &filename) const;
private: private:
QDir m_resumeDataDir; QDir m_resumeDataDir;
}; };
#endif // RESUMEDATASAVINGMANAGER_H

View File

@@ -69,6 +69,8 @@
#endif #endif
#include "base/algorithm.h" #include "base/algorithm.h"
#include "base/exceptions.h"
#include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadhandler.h" #include "base/net/downloadhandler.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
@@ -198,7 +200,7 @@ namespace
for (auto i = categories.cbegin(); i != categories.cend(); ++i) { for (auto i = categories.cbegin(); i != categories.cend(); ++i) {
const QString &category = i.key(); const QString &category = i.key();
foreach (const QString &subcat, Session::expandCategory(category)) { for (const QString &subcat : asConst(Session::expandCategory(category))) {
if (!expanded.contains(subcat)) if (!expanded.contains(subcat))
expanded[subcat] = ""; expanded[subcat] = "";
} }
@@ -275,6 +277,7 @@ Session::Session(QObject *parent)
, m_announceToAllTrackers(BITTORRENT_SESSION_KEY("AnnounceToAllTrackers"), false) , m_announceToAllTrackers(BITTORRENT_SESSION_KEY("AnnounceToAllTrackers"), false)
, m_announceToAllTiers(BITTORRENT_SESSION_KEY("AnnounceToAllTiers"), true) , m_announceToAllTiers(BITTORRENT_SESSION_KEY("AnnounceToAllTiers"), true)
, m_asyncIOThreads(BITTORRENT_SESSION_KEY("AsyncIOThreadsCount"), 4) , m_asyncIOThreads(BITTORRENT_SESSION_KEY("AsyncIOThreadsCount"), 4)
, m_checkingMemUsage(BITTORRENT_SESSION_KEY("CheckingMemUsageSize"), 16)
, m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), 64) , m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), 64)
, m_diskCacheTTL(BITTORRENT_SESSION_KEY("DiskCacheTTL"), 60) , m_diskCacheTTL(BITTORRENT_SESSION_KEY("DiskCacheTTL"), 60)
, m_useOSCache(BITTORRENT_SESSION_KEY("UseOSCache"), true) , m_useOSCache(BITTORRENT_SESSION_KEY("UseOSCache"), true)
@@ -468,7 +471,7 @@ Session::Session(QObject *parent)
}); });
configurePeerClasses(); configurePeerClasses();
#endif #endif // LIBTORRENT_VERSION_NUM < 10100
// Enabling plugins // Enabling plugins
//m_nativeSession->add_extension(&libt::create_metadata_plugin); //m_nativeSession->add_extension(&libt::create_metadata_plugin);
@@ -532,7 +535,7 @@ Session::Session(QObject *parent)
connect(&m_networkManager, &QNetworkConfigurationManager::configurationChanged, this, &Session::networkConfigurationChange); connect(&m_networkManager, &QNetworkConfigurationManager::configurationChanged, this, &Session::networkConfigurationChange);
m_ioThread = new QThread(this); m_ioThread = new QThread(this);
m_resumeDataSavingManager = new ResumeDataSavingManager(m_resumeFolderPath); m_resumeDataSavingManager = new ResumeDataSavingManager {m_resumeFolderPath};
m_resumeDataSavingManager->moveToThread(m_ioThread); m_resumeDataSavingManager->moveToThread(m_ioThread);
connect(m_ioThread, &QThread::finished, m_resumeDataSavingManager, &QObject::deleteLater); connect(m_ioThread, &QThread::finished, m_resumeDataSavingManager, &QObject::deleteLater);
m_ioThread->start(); m_ioThread->start();
@@ -609,7 +612,7 @@ void Session::setTempPathEnabled(bool enabled)
{ {
if (enabled != isTempPathEnabled()) { if (enabled != isTempPathEnabled()) {
m_isTempPathEnabled = enabled; m_isTempPathEnabled = enabled;
foreach (TorrentHandle *const torrent, m_torrents) for (TorrentHandle *const torrent : asConst(m_torrents))
torrent->handleTempPathChanged(); torrent->handleTempPathChanged();
} }
} }
@@ -623,7 +626,7 @@ void Session::setAppendExtensionEnabled(bool enabled)
{ {
if (isAppendExtensionEnabled() != enabled) { if (isAppendExtensionEnabled() != enabled) {
// append or remove .!qB extension for incomplete files // append or remove .!qB extension for incomplete files
foreach (TorrentHandle *const torrent, m_torrents) for (TorrentHandle *const torrent : asConst(m_torrents))
torrent->handleAppendExtensionToggled(); torrent->handleAppendExtensionToggled();
m_isAppendExtensionEnabled = enabled; m_isAppendExtensionEnabled = enabled;
@@ -751,7 +754,7 @@ bool Session::addCategory(const QString &name, const QString &savePath)
return false; return false;
if (isSubcategoriesEnabled()) { if (isSubcategoriesEnabled()) {
foreach (const QString &parent, expandCategory(name)) { for (const QString &parent : asConst(expandCategory(name))) {
if ((parent != name) && !m_categories.contains(parent)) { if ((parent != name) && !m_categories.contains(parent)) {
m_categories[parent] = ""; m_categories[parent] = "";
emit categoryAdded(parent); emit categoryAdded(parent);
@@ -774,12 +777,12 @@ bool Session::editCategory(const QString &name, const QString &savePath)
m_categories[name] = savePath; m_categories[name] = savePath;
m_storedCategories = map_cast(m_categories); m_storedCategories = map_cast(m_categories);
if (isDisableAutoTMMWhenCategorySavePathChanged()) { if (isDisableAutoTMMWhenCategorySavePathChanged()) {
foreach (TorrentHandle *const torrent, torrents()) for (TorrentHandle *const torrent : asConst(torrents()))
if (torrent->category() == name) if (torrent->category() == name)
torrent->setAutoTMMEnabled(false); torrent->setAutoTMMEnabled(false);
} }
else { else {
foreach (TorrentHandle *const torrent, torrents()) for (TorrentHandle *const torrent : asConst(torrents()))
if (torrent->category() == name) if (torrent->category() == name)
torrent->handleCategorySavePathChanged(); torrent->handleCategorySavePathChanged();
} }
@@ -789,7 +792,7 @@ bool Session::editCategory(const QString &name, const QString &savePath)
bool Session::removeCategory(const QString &name) bool Session::removeCategory(const QString &name)
{ {
foreach (TorrentHandle *const torrent, torrents()) for (TorrentHandle *const torrent : asConst(torrents()))
if (torrent->belongsToCategory(name)) if (torrent->belongsToCategory(name))
torrent->setCategory(""); torrent->setCategory("");
@@ -876,7 +879,7 @@ bool Session::addTag(const QString &tag)
bool Session::removeTag(const QString &tag) bool Session::removeTag(const QString &tag)
{ {
if (m_tags.remove(tag)) { if (m_tags.remove(tag)) {
foreach (TorrentHandle *const torrent, torrents()) for (TorrentHandle *const torrent : asConst(torrents()))
torrent->removeTag(tag); torrent->removeTag(tag);
m_storedTags = m_tags.toList(); m_storedTags = m_tags.toList();
emit tagRemoved(tag); emit tagRemoved(tag);
@@ -1084,7 +1087,7 @@ void Session::configure()
void Session::processBannedIPs(libt::ip_filter &filter) void Session::processBannedIPs(libt::ip_filter &filter)
{ {
// First, import current filter // First, import current filter
foreach (const QString &ip, m_bannedIPs.value()) { for (const QString &ip : asConst(m_bannedIPs.value())) {
boost::system::error_code ec; boost::system::error_code ec;
libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
Q_ASSERT(!ec); Q_ASSERT(!ec);
@@ -1203,7 +1206,7 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
const ushort port = this->port(); const ushort port = this->port();
std::pair<int, int> ports(port, port); std::pair<int, int> ports(port, port);
settingsPack.set_int(libt::settings_pack::max_retry_port_bind, ports.second - ports.first); settingsPack.set_int(libt::settings_pack::max_retry_port_bind, ports.second - ports.first);
foreach (QString ip, getListeningIPs()) { for (QString ip : getListeningIPs()) {
libt::error_code ec; libt::error_code ec;
std::string interfacesStr; std::string interfacesStr;
@@ -1252,7 +1255,7 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
} }
#else #else
settingsPack.set_str(libt::settings_pack::outgoing_interfaces, networkInterface().toStdString()); settingsPack.set_str(libt::settings_pack::outgoing_interfaces, networkInterface().toStdString());
#endif #endif // Q_OS_WIN
m_listenInterfaceChanged = false; m_listenInterfaceChanged = false;
} }
@@ -1317,6 +1320,9 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
settingsPack.set_int(libt::settings_pack::aio_threads, asyncIOThreads()); settingsPack.set_int(libt::settings_pack::aio_threads, asyncIOThreads());
const int checkingMemUsageSize = checkingMemUsage() * 64;
settingsPack.set_int(libt::settings_pack::checking_mem_usage, checkingMemUsageSize);
const int cacheSize = (diskCacheSize() > -1) ? (diskCacheSize() * 64) : -1; const int cacheSize = (diskCacheSize() > -1) ? (diskCacheSize() * 64) : -1;
settingsPack.set_int(libt::settings_pack::cache_size, cacheSize); settingsPack.set_int(libt::settings_pack::cache_size, cacheSize);
settingsPack.set_int(libt::settings_pack::cache_expiry, diskCacheTTL()); settingsPack.set_int(libt::settings_pack::cache_expiry, diskCacheTTL());
@@ -1461,7 +1467,7 @@ void Session::configurePeerClasses()
, 1 << libt::session::global_peer_class_id); , 1 << libt::session::global_peer_class_id);
} }
catch (std::exception &) {} catch (std::exception &) {}
#endif #endif // TORRENT_USE_IPV6
if (ignoreLimitsOnLAN()) { if (ignoreLimitsOnLAN()) {
// local networks // local networks
f.add_rule(libt::address_v4::from_string("10.0.0.0") f.add_rule(libt::address_v4::from_string("10.0.0.0")
@@ -1500,7 +1506,7 @@ void Session::configurePeerClasses()
, 1 << libt::session::local_peer_class_id); , 1 << libt::session::local_peer_class_id);
} }
catch (std::exception &) {} catch (std::exception &) {}
#endif #endif // TORRENT_USE_IPV6
} }
m_nativeSession->set_peer_class_filter(f); m_nativeSession->set_peer_class_filter(f);
@@ -1517,7 +1523,7 @@ void Session::configurePeerClasses()
m_nativeSession->set_peer_class_type_filter(peerClassTypeFilter); m_nativeSession->set_peer_class_type_filter(peerClassTypeFilter);
} }
#else #else // LIBTORRENT_VERSION_NUM >= 10100
void Session::adjustLimits(libt::session_settings &sessionSettings) void Session::adjustLimits(libt::session_settings &sessionSettings)
{ {
@@ -1734,7 +1740,7 @@ void Session::configure(libtorrent::session_settings &sessionSettings)
break; break;
} }
} }
#endif #endif // LIBTORRENT_VERSION_NUM >= 10100
void Session::enableTracker(bool enable) void Session::enableTracker(bool enable)
{ {
@@ -1769,7 +1775,7 @@ void Session::enableBandwidthScheduler()
void Session::populateAdditionalTrackers() void Session::populateAdditionalTrackers()
{ {
m_additionalTrackerList.clear(); m_additionalTrackerList.clear();
foreach (QString tracker, additionalTrackers().split('\n')) { for (QString tracker : asConst(additionalTrackers().split('\n'))) {
tracker = tracker.trimmed(); tracker = tracker.trimmed();
if (!tracker.isEmpty()) if (!tracker.isEmpty())
m_additionalTrackerList << tracker; m_additionalTrackerList << tracker;
@@ -1780,7 +1786,7 @@ void Session::processShareLimits()
{ {
qDebug("Processing share limits..."); qDebug("Processing share limits...");
foreach (TorrentHandle *const torrent, m_torrents) { for (TorrentHandle *const torrent : asConst(torrents())) {
if (torrent->isSeed() && !torrent->isForced()) { if (torrent->isSeed() && !torrent->isForced()) {
if (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT) { if (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT) {
const qreal ratio = torrent->realRatio(); const qreal ratio = torrent->realRatio();
@@ -1933,7 +1939,7 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_partfile); m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_partfile);
#endif #endif
// Remove unwanted and incomplete files // Remove unwanted and incomplete files
foreach (const QString &unwantedFile, unwantedFiles) { for (const QString &unwantedFile : asConst(unwantedFiles)) {
qDebug("Removing unwanted file: %s", qUtf8Printable(unwantedFile)); qDebug("Removing unwanted file: %s", qUtf8Printable(unwantedFile));
Utils::Fs::forceRemove(unwantedFile); Utils::Fs::forceRemove(unwantedFile);
const QString parentFolder = Utils::Fs::branchPath(unwantedFile); const QString parentFolder = Utils::Fs::branchPath(unwantedFile);
@@ -1947,7 +1953,7 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
QStringList filters; QStringList filters;
filters << QString("%1.*").arg(torrent->hash()); filters << QString("%1.*").arg(torrent->hash());
const QStringList files = resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted); const QStringList files = resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted);
foreach (const QString &file, files) for (const QString &file : files)
Utils::Fs::forceRemove(resumeDataDir.absoluteFilePath(file)); Utils::Fs::forceRemove(resumeDataDir.absoluteFilePath(file));
delete torrent; delete torrent;
@@ -1978,12 +1984,12 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
void Session::increaseTorrentsPriority(const QStringList &hashes) void Session::increaseTorrentsPriority(const QStringList &hashes)
{ {
std::priority_queue<QPair<int, TorrentHandle *>, std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >, std::vector<QPair<int, TorrentHandle *>>,
std::greater<QPair<int, TorrentHandle *> > > torrentQueue; std::greater<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority // Sort torrents by priority
foreach (const InfoHash &hash, hashes) { for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(hash); TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed()) if (torrent && !torrent->isSeed())
torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); torrentQueue.push(qMakePair(torrent->queuePosition(), torrent));
} }
@@ -1995,18 +2001,18 @@ void Session::increaseTorrentsPriority(const QStringList &hashes)
torrentQueue.pop(); torrentQueue.pop();
} }
handleTorrentsPrioritiesChanged(); saveTorrentsQueue();
} }
void Session::decreaseTorrentsPriority(const QStringList &hashes) void Session::decreaseTorrentsPriority(const QStringList &hashes)
{ {
std::priority_queue<QPair<int, TorrentHandle *>, std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >, std::vector<QPair<int, TorrentHandle *>>,
std::less<QPair<int, TorrentHandle *> > > torrentQueue; std::less<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority // Sort torrents by priority
foreach (const InfoHash &hash, hashes) { for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(hash); TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed()) if (torrent && !torrent->isSeed())
torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); torrentQueue.push(qMakePair(torrent->queuePosition(), torrent));
} }
@@ -2021,18 +2027,18 @@ void Session::decreaseTorrentsPriority(const QStringList &hashes)
for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i) for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i)
torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key())); torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key()));
handleTorrentsPrioritiesChanged(); saveTorrentsQueue();
} }
void Session::topTorrentsPriority(const QStringList &hashes) void Session::topTorrentsPriority(const QStringList &hashes)
{ {
std::priority_queue<QPair<int, TorrentHandle *>, std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >, std::vector<QPair<int, TorrentHandle *>>,
std::greater<QPair<int, TorrentHandle *> > > torrentQueue; std::greater<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority // Sort torrents by priority
foreach (const InfoHash &hash, hashes) { for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(hash); TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed()) if (torrent && !torrent->isSeed())
torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); torrentQueue.push(qMakePair(torrent->queuePosition(), torrent));
} }
@@ -2044,18 +2050,18 @@ void Session::topTorrentsPriority(const QStringList &hashes)
torrentQueue.pop(); torrentQueue.pop();
} }
handleTorrentsPrioritiesChanged(); saveTorrentsQueue();
} }
void Session::bottomTorrentsPriority(const QStringList &hashes) void Session::bottomTorrentsPriority(const QStringList &hashes)
{ {
std::priority_queue<QPair<int, TorrentHandle *>, std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >, std::vector<QPair<int, TorrentHandle *>>,
std::less<QPair<int, TorrentHandle *> > > torrentQueue; std::less<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority // Sort torrents by priority
foreach (const InfoHash &hash, hashes) { for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(hash); TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed()) if (torrent && !torrent->isSeed())
torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); torrentQueue.push(qMakePair(torrent->queuePosition(), torrent));
} }
@@ -2070,7 +2076,7 @@ void Session::bottomTorrentsPriority(const QStringList &hashes)
for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i) for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i)
torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key())); torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key()));
handleTorrentsPrioritiesChanged(); saveTorrentsQueue();
} }
QHash<InfoHash, TorrentHandle *> Session::torrents() const QHash<InfoHash, TorrentHandle *> Session::torrents() const
@@ -2366,7 +2372,7 @@ void Session::exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolde
void Session::generateResumeData(bool final) void Session::generateResumeData(bool final)
{ {
foreach (TorrentHandle *const torrent, m_torrents) { for (TorrentHandle *const torrent : asConst(m_torrents)) {
if (!torrent->isValid()) continue; if (!torrent->isValid()) continue;
if (torrent->isChecking() || torrent->isPaused()) continue; if (torrent->isChecking() || torrent->isPaused()) continue;
if (!final && !torrent->needSaveResumeData()) continue; if (!final && !torrent->needSaveResumeData()) continue;
@@ -2379,11 +2385,13 @@ void Session::generateResumeData(bool final)
// Called on exit // Called on exit
void Session::saveResumeData() void Session::saveResumeData()
{ {
qDebug("Saving fast resume data..."); qDebug("Saving resume data...");
// Pause session // Pause session
m_nativeSession->pause(); m_nativeSession->pause();
if (isQueueingSystemEnabled())
saveTorrentsQueue();
generateResumeData(true); generateResumeData(true);
while (m_numResumeData > 0) { while (m_numResumeData > 0) {
@@ -2394,7 +2402,7 @@ void Session::saveResumeData()
break; break;
} }
for (const auto a: alerts) { for (const auto a : alerts) {
switch (a->type()) { switch (a->type()) {
case libt::save_resume_data_failed_alert::alert_type: case libt::save_resume_data_failed_alert::alert_type:
case libt::save_resume_data_alert::alert_type: case libt::save_resume_data_alert::alert_type:
@@ -2408,6 +2416,31 @@ void Session::saveResumeData()
} }
} }
void Session::saveTorrentsQueue()
{
QMap<int, QString> queue; // Use QMap since it should be ordered by key
for (const TorrentHandle *torrent : asConst(torrents())) {
// We require actual (non-cached) queue position here!
const int queuePos = torrent->nativeHandle().queue_position();
if (queuePos >= 0)
queue[queuePos] = torrent->hash();
}
QByteArray data;
for (const QString &hash : asConst(queue))
data += (hash.toLatin1() + '\n');
const QString filename = QLatin1String {"queue"};
QMetaObject::invokeMethod(m_resumeDataSavingManager, "save"
, Q_ARG(QString, filename), Q_ARG(QByteArray, data));
}
void Session::removeTorrentsQueue()
{
const QString filename = QLatin1String {"queue"};
QMetaObject::invokeMethod(m_resumeDataSavingManager, "remove", Q_ARG(QString, filename));
}
void Session::setDefaultSavePath(QString path) void Session::setDefaultSavePath(QString path)
{ {
path = normalizeSavePath(path); path = normalizeSavePath(path);
@@ -2416,10 +2449,10 @@ void Session::setDefaultSavePath(QString path)
m_defaultSavePath = path; m_defaultSavePath = path;
if (isDisableAutoTMMWhenDefaultSavePathChanged()) if (isDisableAutoTMMWhenDefaultSavePathChanged())
foreach (TorrentHandle *const torrent, torrents()) for (TorrentHandle *const torrent : asConst(torrents()))
torrent->setAutoTMMEnabled(false); torrent->setAutoTMMEnabled(false);
else else
foreach (TorrentHandle *const torrent, torrents()) for (TorrentHandle *const torrent : asConst(torrents()))
torrent->handleCategorySavePathChanged(); torrent->handleCategorySavePathChanged();
} }
@@ -2430,7 +2463,7 @@ void Session::setTempPath(QString path)
m_tempPath = path; m_tempPath = path;
foreach (TorrentHandle *const torrent, m_torrents) for (TorrentHandle *const torrent : asConst(m_torrents))
torrent->handleTempPathChanged(); torrent->handleTempPathChanged();
} }
@@ -2504,7 +2537,7 @@ const QStringList Session::getListeningIPs()
QHostAddress ip; QHostAddress ip;
QString ipString; QString ipString;
QAbstractSocket::NetworkLayerProtocol protocol; QAbstractSocket::NetworkLayerProtocol protocol;
foreach (const QNetworkAddressEntry &entry, addresses) { for (const QNetworkAddressEntry &entry : addresses) {
ip = entry.ip(); ip = entry.ip();
ipString = ip.toString(); ipString = ip.toString();
protocol = ip.protocol(); protocol = ip.protocol();
@@ -2550,7 +2583,7 @@ void Session::configureListeningInterface()
libt::error_code ec; libt::error_code ec;
const QStringList IPs = getListeningIPs(); const QStringList IPs = getListeningIPs();
foreach (const QString ip, IPs) { for (const QString ip : IPs) {
if (ip.isEmpty()) { if (ip.isEmpty()) {
logger->addMessage(tr("qBittorrent is trying to listen on any interface port: %1", "e.g: qBittorrent is trying to listen on any interface port: TCP/6881").arg(QString::number(port)), Log::INFO); logger->addMessage(tr("qBittorrent is trying to listen on any interface port: %1", "e.g: qBittorrent is trying to listen on any interface port: TCP/6881").arg(QString::number(port)), Log::INFO);
m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port); m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port);
@@ -2570,7 +2603,7 @@ void Session::configureListeningInterface()
#else #else
m_listenInterfaceChanged = true; m_listenInterfaceChanged = true;
configureDeferred(); configureDeferred();
#endif #endif // LIBTORRENT_VERSION_NUM < 10100
} }
int Session::globalDownloadSpeedLimit() const int Session::globalDownloadSpeedLimit() const
@@ -2983,7 +3016,7 @@ void Session::setMaxConnectionsPerTorrent(int max)
m_maxConnectionsPerTorrent = max; m_maxConnectionsPerTorrent = max;
// Apply this to all session torrents // Apply this to all session torrents
for (const auto &handle: m_nativeSession->get_torrents()) { for (const auto &handle : m_nativeSession->get_torrents()) {
if (!handle.is_valid()) continue; if (!handle.is_valid()) continue;
try { try {
handle.set_max_connections(max); handle.set_max_connections(max);
@@ -3005,7 +3038,7 @@ void Session::setMaxUploadsPerTorrent(int max)
m_maxUploadsPerTorrent = max; m_maxUploadsPerTorrent = max;
// Apply this to all session torrents // Apply this to all session torrents
for (const auto &handle: m_nativeSession->get_torrents()) { for (const auto &handle : m_nativeSession->get_torrents()) {
if (!handle.is_valid()) continue; if (!handle.is_valid()) continue;
try { try {
handle.set_max_uploads(max); handle.set_max_uploads(max);
@@ -3055,6 +3088,22 @@ void Session::setAsyncIOThreads(const int num)
configureDeferred(); configureDeferred();
} }
int Session::checkingMemUsage() const
{
return qMax(1, m_checkingMemUsage.value());
}
void Session::setCheckingMemUsage(int size)
{
size = qMax(size, 1);
if (size == m_checkingMemUsage)
return;
m_checkingMemUsage = size;
configureDeferred();
}
int Session::diskCacheSize() const int Session::diskCacheSize() const
{ {
int size = m_diskCacheSize; int size = m_diskCacheSize;
@@ -3213,6 +3262,11 @@ void Session::setQueueingSystemEnabled(bool enabled)
if (enabled != m_isQueueingEnabled) { if (enabled != m_isQueueingEnabled) {
m_isQueueingEnabled = enabled; m_isQueueingEnabled = enabled;
configureDeferred(); configureDeferred();
if (enabled)
saveTorrentsQueue();
else
removeTorrentsQueue();
} }
} }
@@ -3543,18 +3597,6 @@ void Session::handleTorrentShareLimitChanged(TorrentHandle *const torrent)
updateSeedingLimitTimer(); updateSeedingLimitTimer();
} }
void Session::handleTorrentsPrioritiesChanged()
{
// Save fastresume for the torrents that changed queue position
for (TorrentHandle *const torrent : torrents()) {
if (!torrent->isSeed()) {
// cached vs actual queue position, qBt starts queue at 1
if (torrent->queuePosition() != (torrent->nativeHandle().queue_position() + 1))
saveTorrentResumeData(torrent);
}
}
}
void Session::saveTorrentResumeData(TorrentHandle *const torrent) void Session::saveTorrentResumeData(TorrentHandle *const torrent)
{ {
qDebug("Saving fastresume data for %s", qUtf8Printable(torrent->name())); qDebug("Saving fastresume data for %s", qUtf8Printable(torrent->name()));
@@ -3677,11 +3719,8 @@ void Session::handleTorrentChecked(TorrentHandle *const torrent)
void Session::handleTorrentFinished(TorrentHandle *const torrent) void Session::handleTorrentFinished(TorrentHandle *const torrent)
{ {
if (!torrent->hasError() && !torrent->hasMissingFiles()) { if (!torrent->hasError() && !torrent->hasMissingFiles())
saveTorrentResumeData(torrent); saveTorrentResumeData(torrent);
if (isQueueingSystemEnabled())
handleTorrentsPrioritiesChanged();
}
emit torrentFinished(torrent); emit torrentFinished(torrent);
qDebug("Checking if the torrent contains torrent files to download"); qDebug("Checking if the torrent contains torrent files to download");
@@ -3724,8 +3763,9 @@ void Session::handleTorrentResumeDataReady(TorrentHandle *const torrent, const l
QByteArray out; QByteArray out;
libt::bencode(std::back_inserter(out), data); libt::bencode(std::back_inserter(out), data);
QMetaObject::invokeMethod(m_resumeDataSavingManager, "saveResumeData", const QString filename = QString("%1.fastresume").arg(torrent->hash());
Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out)); QMetaObject::invokeMethod(m_resumeDataSavingManager, "save",
Q_ARG(QString, filename), Q_ARG(QByteArray, out));
} }
void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent) void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent)
@@ -3757,7 +3797,7 @@ void Session::handleTorrentTrackerWarning(TorrentHandle *const torrent, const QS
bool Session::hasPerTorrentRatioLimit() const bool Session::hasPerTorrentRatioLimit() const
{ {
foreach (TorrentHandle *const torrent, m_torrents) for (TorrentHandle *const torrent : asConst(m_torrents))
if (torrent->ratioLimit() >= 0) return true; if (torrent->ratioLimit() >= 0) return true;
return false; return false;
@@ -3765,7 +3805,7 @@ bool Session::hasPerTorrentRatioLimit() const
bool Session::hasPerTorrentSeedingTimeLimit() const bool Session::hasPerTorrentSeedingTimeLimit() const
{ {
foreach (TorrentHandle *const torrent, m_torrents) for (TorrentHandle *const torrent : asConst(m_torrents))
if (torrent->seedingTimeLimit() >= 0) return true; if (torrent->seedingTimeLimit() >= 0) return true;
return false; return false;
@@ -3778,11 +3818,11 @@ void Session::initResumeFolder()
if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) { if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) {
m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock")); m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock"));
if (!m_resumeFolderLock.open(QFile::WriteOnly)) { if (!m_resumeFolderLock.open(QFile::WriteOnly)) {
throw std::runtime_error("Cannot write to torrent resume folder."); throw RuntimeError {tr("Cannot write to torrent resume folder.")};
} }
} }
else { else {
throw std::runtime_error("Cannot create torrent resume folder."); throw RuntimeError {tr("Cannot create torrent resume folder.")};
} }
} }
@@ -3894,56 +3934,97 @@ void Session::startUpTorrents()
++resumedTorrentsCount; ++resumedTorrentsCount;
}; };
qDebug("Starting up torrents"); qDebug("Starting up torrents...");
qDebug("Queue size: %d", fastresumes.size()); qDebug("Queue size: %d", fastresumes.size());
// Resume downloads
QMap<int, TorrentResumeData> queuedResumeData;
int nextQueuePosition = 1;
int numOfRemappedFiles = 0;
const QRegularExpression rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); const QRegularExpression rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
foreach (const QString &fastresumeName, fastresumes) {
if (isQueueingSystemEnabled()) {
QFile queueFile {resumeDataDir.absoluteFilePath(QLatin1String {"queue"})};
// TODO: The following code is deprecated in 4.1.5. Remove after several releases in 4.2.x.
// === BEGIN DEPRECATED CODE === //
if (!queueFile.exists()) {
// Resume downloads in a legacy manner
QMap<int, TorrentResumeData> queuedResumeData;
int nextQueuePosition = 1;
int numOfRemappedFiles = 0;
for (const QString &fastresumeName : asConst(fastresumes)) {
const QRegularExpressionMatch rxMatch = rx.match(fastresumeName);
if (!rxMatch.hasMatch()) continue;
QString hash = rxMatch.captured(1);
QString fastresumePath = resumeDataDir.absoluteFilePath(fastresumeName);
QByteArray data;
CreateTorrentParams torrentParams;
MagnetUri magnetUri;
int queuePosition;
if (readFile(fastresumePath, data) && loadTorrentResumeData(data, torrentParams, queuePosition, magnetUri)) {
if (queuePosition <= nextQueuePosition) {
startupTorrent({ hash, magnetUri, torrentParams, data });
if (queuePosition == nextQueuePosition) {
++nextQueuePosition;
while (queuedResumeData.contains(nextQueuePosition)) {
startupTorrent(queuedResumeData.take(nextQueuePosition));
++nextQueuePosition;
}
}
}
else {
int q = queuePosition;
for (; queuedResumeData.contains(q); ++q) {}
if (q != queuePosition)
++numOfRemappedFiles;
queuedResumeData[q] = {hash, magnetUri, torrentParams, data};
}
}
}
if (numOfRemappedFiles > 0) {
logger->addMessage(
QString(tr("Queue positions were corrected in %1 resume files")).arg(numOfRemappedFiles),
Log::CRITICAL);
}
// starting up downloading torrents (queue position > 0)
for (const TorrentResumeData &torrentResumeData : asConst(queuedResumeData))
startupTorrent(torrentResumeData);
return;
}
// === END DEPRECATED CODE === //
QStringList queue;
if (queueFile.open(QFile::ReadOnly)) {
QByteArray line;
while (!(line = queueFile.readLine()).isEmpty())
queue.append(QString::fromLatin1(line.trimmed()) + QLatin1String {".fastresume"});
}
else {
LogMsg(tr("Couldn't load torrents queue from '%1'. Error: %2")
.arg(queueFile.fileName(), queueFile.errorString()), Log::WARNING);
}
if (!queue.empty())
fastresumes = queue + fastresumes.toSet().subtract(queue.toSet()).toList();
}
for (const QString &fastresumeName : asConst(fastresumes)) {
const QRegularExpressionMatch rxMatch = rx.match(fastresumeName); const QRegularExpressionMatch rxMatch = rx.match(fastresumeName);
if (!rxMatch.hasMatch()) continue; if (!rxMatch.hasMatch()) continue;
QString hash = rxMatch.captured(1); const QString hash = rxMatch.captured(1);
QString fastresumePath = resumeDataDir.absoluteFilePath(fastresumeName); const QString fastresumePath = resumeDataDir.absoluteFilePath(fastresumeName);
QByteArray data; QByteArray data;
CreateTorrentParams torrentParams; CreateTorrentParams torrentParams;
MagnetUri magnetUri; MagnetUri magnetUri;
int queuePosition; int queuePosition;
if (readFile(fastresumePath, data) && loadTorrentResumeData(data, torrentParams, queuePosition, magnetUri)) { if (readFile(fastresumePath, data)
if (queuePosition <= nextQueuePosition) { && loadTorrentResumeData(data, torrentParams, queuePosition, magnetUri)) {
startupTorrent({ hash, magnetUri, torrentParams, data }); startupTorrent({hash, magnetUri, torrentParams, data});
if (queuePosition == nextQueuePosition) {
++nextQueuePosition;
while (queuedResumeData.contains(nextQueuePosition)) {
startupTorrent(queuedResumeData.take(nextQueuePosition));
++nextQueuePosition;
}
}
}
else {
int q = queuePosition;
for (; queuedResumeData.contains(q); ++q) {
}
if (q != queuePosition) {
++numOfRemappedFiles;
}
queuedResumeData[q] = {hash, magnetUri, torrentParams, data};
}
} }
} }
if (numOfRemappedFiles > 0) {
logger->addMessage(
QString(tr("Queue positions were corrected in %1 resume files")).arg(numOfRemappedFiles),
Log::CRITICAL);
}
// starting up downloading torrents (queue position > 0)
foreach (const TorrentResumeData &torrentResumeData, queuedResumeData)
startupTorrent(torrentResumeData);
} }
quint64 Session::getAlltimeDL() const quint64 Session::getAlltimeDL() const
@@ -4035,7 +4116,7 @@ void Session::readAlerts()
std::vector<libt::alert *> alerts; std::vector<libt::alert *> alerts;
getPendingAlerts(alerts); getPendingAlerts(alerts);
for (const auto a: alerts) { for (const auto a : alerts) {
handleAlert(a); handleAlert(a);
#if LIBTORRENT_VERSION_NUM < 10100 #if LIBTORRENT_VERSION_NUM < 10100
delete a; delete a;
@@ -4442,7 +4523,7 @@ void Session::handleSessionStatsAlert(libt::session_stats_alert *p)
emit statsUpdated(); emit statsUpdated();
} }
#else #else // LIBTORRENT_VERSION_NUM >= 10100
void Session::updateStats() void Session::updateStats()
{ {
libt::session_status ss = m_nativeSession->status(); libt::session_status ss = m_nativeSession->status();
@@ -4479,7 +4560,7 @@ void Session::updateStats()
emit statsUpdated(); emit statsUpdated();
} }
#endif #endif // LIBTORRENT_VERSION_NUM >= 10100
void Session::handleStateUpdateAlert(libt::state_update_alert *p) void Session::handleStateUpdateAlert(libt::state_update_alert *p)
{ {
@@ -4487,14 +4568,14 @@ void Session::handleStateUpdateAlert(libt::state_update_alert *p)
updateStats(); updateStats();
#endif #endif
foreach (const libt::torrent_status &status, p->status) { for (const libt::torrent_status &status : p->status) {
TorrentHandle *const torrent = m_torrents.value(status.info_hash); TorrentHandle *const torrent = m_torrents.value(status.info_hash);
if (torrent) if (torrent)
torrent->handleStateUpdate(status); torrent->handleStateUpdate(status);
} }
m_torrentStatusReport = TorrentStatusReport(); m_torrentStatusReport = TorrentStatusReport();
foreach (TorrentHandle *const torrent, m_torrents) { for (TorrentHandle *const torrent : asConst(m_torrents)) {
if (torrent->isDownloading()) if (torrent->isDownloading())
++m_torrentStatusReport.nbDownloading; ++m_torrentStatusReport.nbDownloading;
if (torrent->isUploading()) if (torrent->isUploading())
@@ -4530,7 +4611,7 @@ namespace
return true; return true;
} }
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri) bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri)
{ {
torrentParams = CreateTorrentParams(); torrentParams = CreateTorrentParams();
torrentParams.restored = true; torrentParams.restored = true;

View File

@@ -237,7 +237,7 @@ namespace BitTorrent
int diskJobTime = 0; int diskJobTime = 0;
} disk; } disk;
}; };
#endif #endif // LIBTORRENT_VERSION_NUM >= 10100
class Session : public QObject class Session : public QObject
{ {
@@ -377,6 +377,8 @@ namespace BitTorrent
void setAnnounceToAllTiers(bool val); void setAnnounceToAllTiers(bool val);
int asyncIOThreads() const; int asyncIOThreads() const;
void setAsyncIOThreads(int num); void setAsyncIOThreads(int num);
int checkingMemUsage() const;
void setCheckingMemUsage(int size);
int diskCacheSize() const; int diskCacheSize() const;
void setDiskCacheSize(int size); void setDiskCacheSize(int size);
int diskCacheTTL() const; int diskCacheTTL() const;
@@ -481,7 +483,6 @@ namespace BitTorrent
// TorrentHandle interface // TorrentHandle interface
void handleTorrentShareLimitChanged(TorrentHandle *const torrent); void handleTorrentShareLimitChanged(TorrentHandle *const torrent);
void handleTorrentsPrioritiesChanged();
void handleTorrentNameChanged(TorrentHandle *const torrent); void handleTorrentNameChanged(TorrentHandle *const torrent);
void handleTorrentSavePathChanged(TorrentHandle *const torrent); void handleTorrentSavePathChanged(TorrentHandle *const torrent);
void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory); void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory);
@@ -633,6 +634,8 @@ namespace BitTorrent
void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle); void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle);
void saveResumeData(); void saveResumeData();
void saveTorrentsQueue();
void removeTorrentsQueue();
#if LIBTORRENT_VERSION_NUM < 10100 #if LIBTORRENT_VERSION_NUM < 10100
void dispatchAlerts(libtorrent::alert *alertPtr); void dispatchAlerts(libtorrent::alert *alertPtr);
@@ -657,6 +660,7 @@ namespace BitTorrent
CachedSettingValue<bool> m_announceToAllTrackers; CachedSettingValue<bool> m_announceToAllTrackers;
CachedSettingValue<bool> m_announceToAllTiers; CachedSettingValue<bool> m_announceToAllTiers;
CachedSettingValue<int> m_asyncIOThreads; CachedSettingValue<int> m_asyncIOThreads;
CachedSettingValue<int> m_checkingMemUsage;
CachedSettingValue<int> m_diskCacheSize; CachedSettingValue<int> m_diskCacheSize;
CachedSettingValue<int> m_diskCacheTTL; CachedSettingValue<int> m_diskCacheTTL;
CachedSettingValue<bool> m_useOSCache; CachedSettingValue<bool> m_useOSCache;

View File

@@ -110,7 +110,7 @@ void TorrentCreatorThread::run()
QStringList fileNames; QStringList fileNames;
QHash<QString, boost::int64_t> fileSizeMap; QHash<QString, boost::int64_t> fileSizeMap;
for (const auto &dir : qAsConst(dirs)) { for (const auto &dir : asConst(dirs)) {
QStringList tmpNames; // natural sort files within each dir QStringList tmpNames; // natural sort files within each dir
QDirIterator fileIter(dir, QDir::Files); QDirIterator fileIter(dir, QDir::Files);
@@ -126,7 +126,7 @@ void TorrentCreatorThread::run()
fileNames += tmpNames; fileNames += tmpNames;
} }
for (const auto &fileName : qAsConst(fileNames)) for (const auto &fileName : asConst(fileNames))
fs.add_file(fileName.toStdString(), fileSizeMap[fileName]); fs.add_file(fileName.toStdString(), fileSizeMap[fileName]);
} }
@@ -141,14 +141,14 @@ void TorrentCreatorThread::run()
#endif #endif
// Add url seeds // Add url seeds
foreach (QString seed, m_params.urlSeeds) { for (QString seed : asConst(m_params.urlSeeds)) {
seed = seed.trimmed(); seed = seed.trimmed();
if (!seed.isEmpty()) if (!seed.isEmpty())
newTorrent.add_url_seed(seed.toStdString()); newTorrent.add_url_seed(seed.toStdString());
} }
int tier = 0; int tier = 0;
foreach (const QString &tracker, m_params.trackers) { for (const QString &tracker : asConst(m_params.trackers)) {
if (tracker.isEmpty()) if (tracker.isEmpty())
++tier; ++tier;
else else

View File

@@ -55,6 +55,7 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/profile.h" #include "base/profile.h"
@@ -77,7 +78,7 @@ namespace
ListType setToEntryList(const QSet<QString> &input) ListType setToEntryList(const QSet<QString> &input)
{ {
ListType entryList; ListType entryList;
foreach (const QString &setValue, input) for (const QString &setValue : input)
entryList.emplace_back(setValue.toStdString()); entryList.emplace_back(setValue.toStdString());
return entryList; return entryList;
} }
@@ -158,14 +159,14 @@ namespace
{ {
// new constructor is available // new constructor is available
template<typename T, typename std::enable_if<std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0> template<typename T, typename std::enable_if<std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0>
T makeTorrentCreator(const libtorrent::torrent_info & ti) T makeTorrentCreator(const libtorrent::torrent_info &ti)
{ {
return T(ti, true); return T(ti, true);
} }
// new constructor isn't available // new constructor isn't available
template<typename T, typename std::enable_if<!std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0> template<typename T, typename std::enable_if<!std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0>
T makeTorrentCreator(const libtorrent::torrent_info & ti) T makeTorrentCreator(const libtorrent::torrent_info &ti)
{ {
return T(ti); return T(ti);
} }
@@ -223,7 +224,7 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
if (params.paused) { if (params.paused) {
m_startupState = Started; m_startupState = Started;
} }
else if (!params.restored) { else if (!params.restored || !hasMetadata()) {
// Resume torrent because it was added in "resumed" state // Resume torrent because it was added in "resumed" state
// but it's actually paused during initialization // but it's actually paused during initialization
m_startupState = Starting; m_startupState = Starting;
@@ -374,10 +375,9 @@ QString TorrentHandle::nativeActualSavePath() const
QList<TrackerEntry> TorrentHandle::trackers() const QList<TrackerEntry> TorrentHandle::trackers() const
{ {
QList<TrackerEntry> entries; QList<TrackerEntry> entries;
std::vector<libt::announce_entry> announces; const std::vector<libt::announce_entry> announces = m_nativeHandle.trackers();
announces = m_nativeHandle.trackers(); for (const libt::announce_entry &tracker : announces)
foreach (const libt::announce_entry &tracker, announces)
entries << tracker; entries << tracker;
return entries; return entries;
@@ -391,7 +391,7 @@ QHash<QString, TrackerInfo> TorrentHandle::trackerInfos() const
void TorrentHandle::addTrackers(const QList<TrackerEntry> &trackers) void TorrentHandle::addTrackers(const QList<TrackerEntry> &trackers)
{ {
QList<TrackerEntry> addedTrackers; QList<TrackerEntry> addedTrackers;
foreach (const TrackerEntry &tracker, trackers) { for (const TrackerEntry &tracker : trackers) {
if (addTracker(tracker)) if (addTracker(tracker))
addedTrackers << tracker; addedTrackers << tracker;
} }
@@ -400,13 +400,13 @@ void TorrentHandle::addTrackers(const QList<TrackerEntry> &trackers)
m_session->handleTorrentTrackersAdded(this, addedTrackers); m_session->handleTorrentTrackersAdded(this, addedTrackers);
} }
void TorrentHandle::replaceTrackers(QList<TrackerEntry> trackers) void TorrentHandle::replaceTrackers(const QList<TrackerEntry> &trackers)
{ {
QList<TrackerEntry> existingTrackers = this->trackers(); QList<TrackerEntry> existingTrackers = this->trackers();
QList<TrackerEntry> addedTrackers; QList<TrackerEntry> addedTrackers;
std::vector<libt::announce_entry> announces; std::vector<libt::announce_entry> announces;
foreach (const TrackerEntry &tracker, trackers) { for (const TrackerEntry &tracker : trackers) {
announces.push_back(tracker.nativeEntry()); announces.push_back(tracker.nativeEntry());
if (!existingTrackers.contains(tracker)) if (!existingTrackers.contains(tracker))
addedTrackers << tracker; addedTrackers << tracker;
@@ -438,9 +438,9 @@ bool TorrentHandle::addTracker(const TrackerEntry &tracker)
QList<QUrl> TorrentHandle::urlSeeds() const QList<QUrl> TorrentHandle::urlSeeds() const
{ {
QList<QUrl> urlSeeds; QList<QUrl> urlSeeds;
std::set<std::string> seeds = m_nativeHandle.url_seeds(); const std::set<std::string> seeds = m_nativeHandle.url_seeds();
foreach (const std::string &urlSeed, seeds) for (const std::string &urlSeed : seeds)
urlSeeds.append(QUrl(urlSeed.c_str())); urlSeeds.append(QUrl(urlSeed.c_str()));
return urlSeeds; return urlSeeds;
@@ -449,7 +449,7 @@ QList<QUrl> TorrentHandle::urlSeeds() const
void TorrentHandle::addUrlSeeds(const QList<QUrl> &urlSeeds) void TorrentHandle::addUrlSeeds(const QList<QUrl> &urlSeeds)
{ {
QList<QUrl> addedUrlSeeds; QList<QUrl> addedUrlSeeds;
foreach (const QUrl &urlSeed, urlSeeds) { for (const QUrl &urlSeed : urlSeeds) {
if (addUrlSeed(urlSeed)) if (addUrlSeed(urlSeed))
addedUrlSeeds << urlSeed; addedUrlSeeds << urlSeed;
} }
@@ -461,7 +461,7 @@ void TorrentHandle::addUrlSeeds(const QList<QUrl> &urlSeeds)
void TorrentHandle::removeUrlSeeds(const QList<QUrl> &urlSeeds) void TorrentHandle::removeUrlSeeds(const QList<QUrl> &urlSeeds)
{ {
QList<QUrl> removedUrlSeeds; QList<QUrl> removedUrlSeeds;
foreach (const QUrl &urlSeed, urlSeeds) { for (const QUrl &urlSeed : urlSeeds) {
if (removeUrlSeed(urlSeed)) if (removeUrlSeed(urlSeed))
removedUrlSeeds << urlSeed; removedUrlSeeds << urlSeed;
} }
@@ -596,8 +596,7 @@ bool TorrentHandle::removeTag(const QString &tag)
void TorrentHandle::removeAllTags() void TorrentHandle::removeAllTags()
{ {
// QT automatically copies the container in foreach, so it's safe to mutate it. for (const QString &tag : asConst(tags()))
foreach (const QString &tag, m_tags)
removeTag(tag); removeTag(tag);
} }
@@ -623,7 +622,7 @@ QString TorrentHandle::filePath(int index) const
QString TorrentHandle::fileName(int index) const QString TorrentHandle::fileName(int index) const
{ {
if (!hasMetadata()) return QString(); if (!hasMetadata()) return QString();
return Utils::Fs::fileName(filePath(index)); return Utils::Fs::fileName(filePath(index));
} }
@@ -636,7 +635,7 @@ qlonglong TorrentHandle::fileSize(int index) const
// to all files in a torrent // to all files in a torrent
QStringList TorrentHandle::absoluteFilePaths() const QStringList TorrentHandle::absoluteFilePaths() const
{ {
if (!hasMetadata()) return QStringList(); if (!hasMetadata()) return QStringList();
QDir saveDir(savePath(true)); QDir saveDir(savePath(true));
QStringList res; QStringList res;
@@ -647,7 +646,7 @@ QStringList TorrentHandle::absoluteFilePaths() const
QStringList TorrentHandle::absoluteFilePathsUnwanted() const QStringList TorrentHandle::absoluteFilePathsUnwanted() const
{ {
if (!hasMetadata()) return QStringList(); if (!hasMetadata()) return QStringList();
QDir saveDir(savePath(true)); QDir saveDir(savePath(true));
QStringList res; QStringList res;
@@ -883,9 +882,9 @@ bool TorrentHandle::hasError() const
bool TorrentHandle::hasFilteredPieces() const bool TorrentHandle::hasFilteredPieces() const
{ {
std::vector<int> pp = m_nativeHandle.piece_priorities(); const std::vector<int> pp = m_nativeHandle.piece_priorities();
foreach (const int priority, pp) for (const int priority : pp)
if (priority == 0) return true; if (priority == 0) return true;
return false; return false;
@@ -973,12 +972,13 @@ qulonglong TorrentHandle::eta() const
QVector<qreal> TorrentHandle::filesProgress() const QVector<qreal> TorrentHandle::filesProgress() const
{ {
std::vector<boost::int64_t> fp; std::vector<boost::int64_t> fp;
QVector<qreal> result;
m_nativeHandle.file_progress(fp, libt::torrent_handle::piece_granularity); m_nativeHandle.file_progress(fp, libt::torrent_handle::piece_granularity);
int count = static_cast<int>(fp.size()); const int count = static_cast<int>(fp.size());
QVector<qreal> result;
result.reserve(count);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
qlonglong size = fileSize(i); const qlonglong size = fileSize(i);
if ((size <= 0) || (fp[i] == size)) if ((size <= 0) || (fp[i] == size))
result << 1; result << 1;
else else
@@ -1086,7 +1086,7 @@ QList<PeerInfo> TorrentHandle::peers() const
m_nativeHandle.get_peer_info(nativePeers); m_nativeHandle.get_peer_info(nativePeers);
foreach (const libt::peer_info &peer, nativePeers) for (const libt::peer_info &peer : nativePeers)
peers << PeerInfo(this, peer); peers << PeerInfo(this, peer);
return peers; return peers;
@@ -1424,16 +1424,6 @@ bool TorrentHandle::saveTorrentFile(const QString &path)
return false; return false;
} }
void TorrentHandle::setFilePriority(int index, int priority)
{
std::vector<int> priorities = m_nativeHandle.file_priorities();
if ((priorities.size() > static_cast<quint64>(index)) && (priorities[index] != priority)) {
priorities[index] = priority;
prioritizeFiles(QVector<int>::fromStdVector(priorities));
}
}
void TorrentHandle::handleStateUpdate(const libt::torrent_status &nativeStatus) void TorrentHandle::handleStateUpdate(const libt::torrent_status &nativeStatus)
{ {
updateStatus(nativeStatus); updateStatus(nativeStatus);
@@ -2062,7 +2052,7 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
if (created) { if (created) {
// Hide the folder on Windows // Hide the folder on Windows
qDebug() << "Hiding folder (Windows)"; qDebug() << "Hiding folder (Windows)";
std::wstring winPath = Utils::Fs::toNativePath(unwantedAbsPath).toStdWString(); std::wstring winPath = Utils::Fs::toNativePath(unwantedAbsPath).toStdWString();
DWORD dwAttrs = ::GetFileAttributesW(winPath.c_str()); DWORD dwAttrs = ::GetFileAttributesW(winPath.c_str());
bool ret = ::SetFileAttributesW(winPath.c_str(), dwAttrs | FILE_ATTRIBUTE_HIDDEN); bool ret = ::SetFileAttributesW(winPath.c_str(), dwAttrs | FILE_ATTRIBUTE_HIDDEN);
Q_ASSERT(ret != 0); Q_UNUSED(ret); Q_ASSERT(ret != 0); Q_UNUSED(ret);
@@ -2100,7 +2090,7 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
QVector<qreal> TorrentHandle::availableFileFractions() const QVector<qreal> TorrentHandle::availableFileFractions() const
{ {
const auto filesCount = this->filesCount(); const int filesCount = this->filesCount();
if (filesCount < 0) return {}; if (filesCount < 0) return {};
const QVector<int> piecesAvailability = pieceAvailability(); const QVector<int> piecesAvailability = pieceAvailability();
@@ -2109,12 +2099,13 @@ QVector<qreal> TorrentHandle::availableFileFractions() const
QVector<qreal> res; QVector<qreal> res;
res.reserve(filesCount); res.reserve(filesCount);
TorrentInfo info = this->info(); const TorrentInfo info = this->info();
for (int file = 0; file < filesCount; ++file) { for (int i = 0; i < filesCount; ++i) {
TorrentInfo::PieceRange filePieces = info.filePieces(file); const TorrentInfo::PieceRange filePieces = info.filePieces(i);
int availablePieces = 0; int availablePieces = 0;
for (int piece = filePieces.first(); piece <= filePieces.last(); ++piece) { for (int piece = filePieces.first(); piece <= filePieces.last(); ++piece) {
availablePieces += piecesAvailability[piece] > 0 ? 1 : 0; availablePieces += (piecesAvailability[piece] > 0) ? 1 : 0;
} }
res.push_back(static_cast<qreal>(availablePieces) / filePieces.size()); res.push_back(static_cast<qreal>(availablePieces) / filePieces.size());
} }

View File

@@ -348,7 +348,6 @@ namespace BitTorrent
void renameFile(int index, const QString &name); void renameFile(int index, const QString &name);
bool saveTorrentFile(const QString &path); bool saveTorrentFile(const QString &path);
void prioritizeFiles(const QVector<int> &priorities); void prioritizeFiles(const QVector<int> &priorities);
void setFilePriority(int index, int priority);
void setRatioLimit(qreal limit); void setRatioLimit(qreal limit);
void setSeedingTimeLimit(int limit); void setSeedingTimeLimit(int limit);
void setUploadLimit(int limit); void setUploadLimit(int limit);
@@ -356,7 +355,7 @@ namespace BitTorrent
void setSuperSeeding(bool enable); void setSuperSeeding(bool enable);
void flushCache(); void flushCache();
void addTrackers(const QList<TrackerEntry> &trackers); void addTrackers(const QList<TrackerEntry> &trackers);
void replaceTrackers(QList<TrackerEntry> trackers); void replaceTrackers(const QList<TrackerEntry> &trackers);
void addUrlSeeds(const QList<QUrl> &urlSeeds); void addUrlSeeds(const QList<QUrl> &urlSeeds);
void removeUrlSeeds(const QList<QUrl> &urlSeeds); void removeUrlSeeds(const QList<QUrl> &urlSeeds);
bool connectPeer(const PeerAddress &peerAddress); bool connectPeer(const PeerAddress &peerAddress);

View File

@@ -247,7 +247,7 @@ QList<TrackerEntry> TorrentInfo::trackers() const
if (!isValid()) return QList<TrackerEntry>(); if (!isValid()) return QList<TrackerEntry>();
QList<TrackerEntry> trackers; QList<TrackerEntry> trackers;
foreach (const libt::announce_entry &tracker, m_nativeInfo->trackers()) for (const libt::announce_entry &tracker : m_nativeInfo->trackers())
trackers.append(tracker); trackers.append(tracker);
return trackers; return trackers;
@@ -258,7 +258,7 @@ QList<QUrl> TorrentInfo::urlSeeds() const
if (!isValid()) return QList<QUrl>(); if (!isValid()) return QList<QUrl>();
QList<QUrl> urlSeeds; QList<QUrl> urlSeeds;
foreach (const libt::web_seed_entry &webSeed, m_nativeInfo->web_seeds()) for (const libt::web_seed_entry &webSeed : m_nativeInfo->web_seeds())
if (webSeed.type == libt::web_seed_entry::url_seed) if (webSeed.type == libt::web_seed_entry::url_seed)
urlSeeds.append(QUrl(webSeed.url.c_str())); urlSeeds.append(QUrl(webSeed.url.c_str()));
@@ -350,7 +350,7 @@ void TorrentInfo::renameFile(const int index, const QString &newPath)
nativeInfo()->rename_file(index, Utils::Fs::toNativePath(newPath).toStdString()); nativeInfo()->rename_file(index, Utils::Fs::toNativePath(newPath).toStdString());
} }
int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const int BitTorrent::TorrentInfo::fileIndex(const QString &fileName) const
{ {
// the check whether the object is valid is not needed here // the check whether the object is valid is not needed here
// because if filesCount() returns -1 the loop exits immediately // because if filesCount() returns -1 the loop exits immediately

View File

@@ -60,7 +60,7 @@ bool Peer::operator==(const Peer &other) const
QString Peer::uid() const QString Peer::uid() const
{ {
return ip + ':' + QString::number(port); return ip.toString() + ':' + QString::number(port);
} }
libtorrent::entry Peer::toEntry(bool noPeerId) const libtorrent::entry Peer::toEntry(bool noPeerId) const
@@ -68,7 +68,7 @@ libtorrent::entry Peer::toEntry(bool noPeerId) const
libtorrent::entry::dictionary_type peerMap; libtorrent::entry::dictionary_type peerMap;
if (!noPeerId) if (!noPeerId)
peerMap["id"] = libtorrent::entry(peerId.toStdString()); peerMap["id"] = libtorrent::entry(peerId.toStdString());
peerMap["ip"] = libtorrent::entry(ip.toStdString()); peerMap["ip"] = libtorrent::entry(ip.toString().toStdString());
peerMap["port"] = libtorrent::entry(port); peerMap["port"] = libtorrent::entry(port);
return libtorrent::entry(peerMap); return libtorrent::entry(peerMap);
@@ -136,7 +136,7 @@ void Tracker::respondToAnnounceRequest()
QMap<QString, QByteArray> queryParams; QMap<QString, QByteArray> queryParams;
// Parse GET parameters // Parse GET parameters
using namespace Utils::ByteArray; using namespace Utils::ByteArray;
for (const QByteArray &param : copyAsConst(splitToViews(m_request.query, "&"))) { for (const QByteArray &param : asConst(splitToViews(m_request.query, "&"))) {
const int sepPos = param.indexOf('='); const int sepPos = param.indexOf('=');
if (sepPos <= 0) continue; // ignores params without name if (sepPos <= 0) continue; // ignores params without name
@@ -145,10 +145,12 @@ void Tracker::respondToAnnounceRequest()
queryParams[paramName] = paramValue; queryParams[paramName] = paramValue;
} }
TrackerAnnounceRequest annonceReq; TrackerAnnounceRequest announceReq;
// IP // IP
annonceReq.peer.ip = m_env.clientAddress.toString(); // Use the "ip" parameter provided from tracker request first, then fall back to client IP if invalid
const QHostAddress paramIP {QString::fromLatin1(queryParams.value("ip"))};
announceReq.peer.ip = paramIP.isNull() ? m_env.clientAddress : paramIP;
// 1. Get info_hash // 1. Get info_hash
if (!queryParams.contains("info_hash")) { if (!queryParams.contains("info_hash")) {
@@ -156,7 +158,7 @@ void Tracker::respondToAnnounceRequest()
status(101, "Missing info_hash"); status(101, "Missing info_hash");
return; return;
} }
annonceReq.infoHash = queryParams.value("info_hash"); announceReq.infoHash = queryParams.value("info_hash");
// info_hash cannot be longer than 20 bytes // info_hash cannot be longer than 20 bytes
/*if (annonce_req.info_hash.toLatin1().length() > 20) { /*if (annonce_req.info_hash.toLatin1().length() > 20) {
qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length()); qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
@@ -170,7 +172,7 @@ void Tracker::respondToAnnounceRequest()
status(102, "Missing peer_id"); status(102, "Missing peer_id");
return; return;
} }
annonceReq.peer.peerId = queryParams.value("peer_id"); announceReq.peer.peerId = queryParams.value("peer_id");
// peer_id cannot be longer than 20 bytes // peer_id cannot be longer than 20 bytes
/*if (annonce_req.peer.peer_id.length() > 20) { /*if (annonce_req.peer.peer_id.length() > 20) {
qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id)); qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id));
@@ -185,52 +187,52 @@ void Tracker::respondToAnnounceRequest()
return; return;
} }
bool ok = false; bool ok = false;
annonceReq.peer.port = queryParams.value("port").toInt(&ok); announceReq.peer.port = queryParams.value("port").toInt(&ok);
if (!ok || (annonceReq.peer.port < 0) || (annonceReq.peer.port > 65535)) { if (!ok || (announceReq.peer.port < 0) || (announceReq.peer.port > 65535)) {
qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port); qDebug("Tracker: Invalid port number (%d)", announceReq.peer.port);
status(103, "Missing port"); status(103, "Missing port");
return; return;
} }
// 4. Get event // 4. Get event
annonceReq.event = ""; announceReq.event = "";
if (queryParams.contains("event")) { if (queryParams.contains("event")) {
annonceReq.event = queryParams.value("event"); announceReq.event = queryParams.value("event");
qDebug("Tracker: event is %s", qUtf8Printable(annonceReq.event)); qDebug("Tracker: event is %s", qUtf8Printable(announceReq.event));
} }
// 5. Get numwant // 5. Get numwant
annonceReq.numwant = 50; announceReq.numwant = 50;
if (queryParams.contains("numwant")) { if (queryParams.contains("numwant")) {
int tmp = queryParams.value("numwant").toInt(); int tmp = queryParams.value("numwant").toInt();
if (tmp > 0) { if (tmp > 0) {
qDebug("Tracker: numwant = %d", tmp); qDebug("Tracker: numwant = %d", tmp);
annonceReq.numwant = tmp; announceReq.numwant = tmp;
} }
} }
// 6. no_peer_id (extension) // 6. no_peer_id (extension)
annonceReq.noPeerId = false; announceReq.noPeerId = false;
if (queryParams.contains("no_peer_id")) if (queryParams.contains("no_peer_id"))
annonceReq.noPeerId = true; announceReq.noPeerId = true;
// 7. TODO: support "compact" extension // 7. TODO: support "compact" extension
// Done parsing, now let's reply // Done parsing, now let's reply
if (annonceReq.event == "stopped") { if (announceReq.event == "stopped") {
unregisterPeer(annonceReq); unregisterPeer(announceReq);
} }
else { else {
registerPeer(annonceReq); registerPeer(announceReq);
replyWithPeerList(annonceReq); replyWithPeerList(announceReq);
} }
} }
void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq) void Tracker::registerPeer(const TrackerAnnounceRequest &announceReq)
{ {
if (annonceReq.peer.port == 0) return; if (announceReq.peer.port == 0) return;
if (!m_torrents.contains(annonceReq.infoHash)) { if (!m_torrents.contains(announceReq.infoHash)) {
// Unknown torrent // Unknown torrent
if (m_torrents.size() == MAX_TORRENTS) { if (m_torrents.size() == MAX_TORRENTS) {
// Reached max size, remove a random torrent // Reached max size, remove a random torrent
@@ -239,34 +241,34 @@ void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
} }
// Register the user // Register the user
PeerList &peers = m_torrents[annonceReq.infoHash]; PeerList &peers = m_torrents[announceReq.infoHash];
if (!peers.contains(annonceReq.peer.uid())) { if (!peers.contains(announceReq.peer.uid())) {
// Unknown peer // Unknown peer
if (peers.size() == MAX_PEERS_PER_TORRENT) { if (peers.size() == MAX_PEERS_PER_TORRENT) {
// Too many peers, remove a random one // Too many peers, remove a random one
peers.erase(peers.begin()); peers.erase(peers.begin());
} }
} }
peers[annonceReq.peer.uid()] = annonceReq.peer; peers[announceReq.peer.uid()] = announceReq.peer;
} }
void Tracker::unregisterPeer(const TrackerAnnounceRequest &annonceReq) void Tracker::unregisterPeer(const TrackerAnnounceRequest &announceReq)
{ {
if (annonceReq.peer.port == 0) return; if (announceReq.peer.port == 0) return;
if (m_torrents[annonceReq.infoHash].remove(annonceReq.peer.uid()) > 0) if (m_torrents[announceReq.infoHash].remove(announceReq.peer.uid()) > 0)
qDebug("Tracker: Peer stopped downloading, deleting it from the list"); qDebug("Tracker: Peer stopped downloading, deleting it from the list");
} }
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq) void Tracker::replyWithPeerList(const TrackerAnnounceRequest &announceReq)
{ {
// Prepare the entry for bencoding // Prepare the entry for bencoding
libtorrent::entry::dictionary_type replyDict; libtorrent::entry::dictionary_type replyDict;
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL); replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
libtorrent::entry::list_type peerList; libtorrent::entry::list_type peerList;
for (const Peer &p : m_torrents.value(annonceReq.infoHash)) for (const Peer &p : m_torrents.value(announceReq.infoHash))
peerList.push_back(p.toEntry(annonceReq.noPeerId)); peerList.push_back(p.toEntry(announceReq.noPeerId));
replyDict["peers"] = libtorrent::entry(peerList); replyDict["peers"] = libtorrent::entry(peerList);
const libtorrent::entry replyEntry(replyDict); const libtorrent::entry replyEntry(replyDict);

View File

@@ -32,6 +32,7 @@
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include <QHostAddress>
#include "base/http/irequesthandler.h" #include "base/http/irequesthandler.h"
#include "base/http/responsebuilder.h" #include "base/http/responsebuilder.h"
@@ -51,7 +52,7 @@ namespace BitTorrent
{ {
struct Peer struct Peer
{ {
QString ip; QHostAddress ip;
QByteArray peerId; QByteArray peerId;
int port; int port;
@@ -90,9 +91,9 @@ namespace BitTorrent
private: private:
void respondToAnnounceRequest(); void respondToAnnounceRequest();
void registerPeer(const TrackerAnnounceRequest &annonceReq); void registerPeer(const TrackerAnnounceRequest &announceReq);
void unregisterPeer(const TrackerAnnounceRequest &annonceReq); void unregisterPeer(const TrackerAnnounceRequest &announceReq);
void replyWithPeerList(const TrackerAnnounceRequest &annonceReq); void replyWithPeerList(const TrackerAnnounceRequest &announceReq);
Http::Server *m_server; Http::Server *m_server;
TorrentList m_torrents; TorrentList m_torrents;

View File

@@ -44,10 +44,10 @@ namespace BitTorrent
public: public:
enum Status enum Status
{ {
NotContacted, NotContacted = 1,
Working, Working = 2,
Updating, Updating = 3,
NotWorking NotWorking = 4
}; };
TrackerEntry(const QString &url); TrackerEntry(const QString &url);

View File

@@ -30,11 +30,10 @@
RuntimeError::RuntimeError(const QString &message) RuntimeError::RuntimeError(const QString &message)
: std::runtime_error {message.toUtf8().data()} : std::runtime_error {message.toUtf8().data()}
, m_message {message}
{ {
} }
QString RuntimeError::message() const QString RuntimeError::message() const
{ {
return m_message; return what();
} }

View File

@@ -36,7 +36,4 @@ class RuntimeError : public std::runtime_error
public: public:
explicit RuntimeError(const QString &message = ""); explicit RuntimeError(const QString &message = "");
QString message() const; QString message() const;
private:
const QString m_message;
}; };

View File

@@ -64,7 +64,7 @@ FileSystemWatcher::FileSystemWatcher(QObject *parent)
QStringList FileSystemWatcher::directories() const QStringList FileSystemWatcher::directories() const
{ {
QStringList dirs = QFileSystemWatcher::directories(); QStringList dirs = QFileSystemWatcher::directories();
for (const QDir &dir : qAsConst(m_watchedFolders)) for (const QDir &dir : asConst(m_watchedFolders))
dirs << dir.canonicalPath(); dirs << dir.canonicalPath();
return dirs; return dirs;
} }
@@ -113,7 +113,7 @@ void FileSystemWatcher::scanLocalFolder(const QString &path)
void FileSystemWatcher::scanNetworkFolders() void FileSystemWatcher::scanNetworkFolders()
{ {
for (const QDir &dir : qAsConst(m_watchedFolders)) for (const QDir &dir : asConst(m_watchedFolders))
processTorrentsInDir(dir); processTorrentsInDir(dir);
} }

View File

@@ -33,16 +33,13 @@
const char C_TORRENT_FILE_EXTENSION[] = ".torrent"; const char C_TORRENT_FILE_EXTENSION[] = ".torrent";
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
template <typename T> template <typename T>
constexpr typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; } constexpr typename std::add_const<T>::type &asConst(T &t) noexcept { return t; }
// prevent rvalue arguments: // Forward rvalue as const
template <typename T> template <typename T>
void qAsConst(const T &&) = delete; constexpr typename std::add_const<T>::type asConst(T &&t) noexcept { return std::move(t); }
#endif
// returns a const object copy // Prevent const rvalue arguments
template <typename T> template <typename T>
constexpr typename std::add_const<T>::type copyAsConst(T &&t) noexcept { return std::move(t); } void asConst(const T &&) = delete;

View File

@@ -133,7 +133,7 @@ bool Connection::acceptsGzipEncoding(QString codings)
const auto isCodingAvailable = [](const QStringList &list, const QString &encoding) -> bool const auto isCodingAvailable = [](const QStringList &list, const QString &encoding) -> bool
{ {
foreach (const QString &str, list) { for (const QString &str : list) {
if (!str.startsWith(encoding)) if (!str.startsWith(encoding))
continue; continue;

View File

@@ -146,9 +146,9 @@ QList<QSslCipher> Server::safeCipherList() const
const QStringList badCiphers = {"idea", "rc4"}; const QStringList badCiphers = {"idea", "rc4"};
const QList<QSslCipher> allCiphers = QSslSocket::supportedCiphers(); const QList<QSslCipher> allCiphers = QSslSocket::supportedCiphers();
QList<QSslCipher> safeCiphers; QList<QSslCipher> safeCiphers;
foreach (const QSslCipher &cipher, allCiphers) { for (const QSslCipher &cipher : allCiphers) {
bool isSafe = true; bool isSafe = true;
foreach (const QString &badCipher, badCiphers) { for (const QString &badCipher : badCiphers) {
if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) { if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) {
isSafe = false; isSafe = false;
break; break;

View File

@@ -52,6 +52,7 @@ namespace Http
const char HEADER_HOST[] = "host"; const char HEADER_HOST[] = "host";
const char HEADER_ORIGIN[] = "origin"; const char HEADER_ORIGIN[] = "origin";
const char HEADER_REFERER[] = "referer"; const char HEADER_REFERER[] = "referer";
const char HEADER_REFERRER_POLICY[] = "referrer-policy";
const char HEADER_SET_COOKIE[] = "set-cookie"; const char HEADER_SET_COOKIE[] = "set-cookie";
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options"; const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options";
const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host"; const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host";
@@ -107,7 +108,7 @@ namespace Http
uint code; uint code;
QString text; QString text;
ResponseStatus(uint code = 200, const QString& text = "OK"): code(code), text(text) {} ResponseStatus(uint code = 200, const QString &text = "OK"): code(code), text(text) {}
}; };
struct Response struct Response
@@ -116,7 +117,7 @@ namespace Http
QStringMap headers; QStringMap headers;
QByteArray content; QByteArray content;
Response(uint code = 200, const QString& text = "OK"): status(code, text) {} Response(uint code = 200, const QString &text = "OK"): status(code, text) {}
}; };
} }

View File

@@ -39,6 +39,7 @@
#include <QSslError> #include <QSslError>
#include <QUrl> #include <QUrl>
#include "base/global.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "downloadhandler.h" #include "downloadhandler.h"
#include "proxyconfigurationmanager.h" #include "proxyconfigurationmanager.h"
@@ -56,7 +57,7 @@ namespace
{ {
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = Preferences::instance()->getNetworkCookies(); QList<QNetworkCookie> cookies = Preferences::instance()->getNetworkCookies();
foreach (const QNetworkCookie &cookie, Preferences::instance()->getNetworkCookies()) { for (const QNetworkCookie &cookie : asConst(Preferences::instance()->getNetworkCookies())) {
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now)) if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie); cookies.removeAll(cookie);
} }
@@ -68,7 +69,7 @@ namespace
{ {
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = allCookies(); QList<QNetworkCookie> cookies = allCookies();
foreach (const QNetworkCookie &cookie, allCookies()) { for (const QNetworkCookie &cookie : asConst(allCookies())) {
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now)) if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie); cookies.removeAll(cookie);
} }
@@ -83,7 +84,7 @@ namespace
{ {
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = QNetworkCookieJar::cookiesForUrl(url); QList<QNetworkCookie> cookies = QNetworkCookieJar::cookiesForUrl(url);
foreach (const QNetworkCookie &cookie, QNetworkCookieJar::cookiesForUrl(url)) { for (const QNetworkCookie &cookie : asConst(QNetworkCookieJar::cookiesForUrl(url))) {
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now)) if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie); cookies.removeAll(cookie);
} }
@@ -95,7 +96,7 @@ namespace
{ {
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = cookieList; QList<QNetworkCookie> cookies = cookieList;
foreach (const QNetworkCookie &cookie, cookieList) { for (const QNetworkCookie &cookie : cookieList) {
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now)) if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie); cookies.removeAll(cookie);
} }

View File

@@ -40,7 +40,7 @@ const QString KEY_PASSWORD = SETTINGS_KEY("Password");
namespace namespace
{ {
inline SettingsStorage *settings() { return SettingsStorage::instance(); } inline SettingsStorage *settings() { return SettingsStorage::instance(); }
inline bool isSameConfig(const Net::ProxyConfiguration &conf1, const Net::ProxyConfiguration &conf2) inline bool isSameConfig(const Net::ProxyConfiguration &conf1, const Net::ProxyConfiguration &conf2)
{ {

View File

@@ -43,6 +43,7 @@
#include <QTcpSocket> #include <QTcpSocket>
#endif #endif
#include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/preferences.h" #include "base/preferences.h"
@@ -291,7 +292,7 @@ QByteArray Smtp::encodeMimeHeader(const QString &key, const QString &value, QTex
if (!prefix.isEmpty()) line += prefix; if (!prefix.isEmpty()) line += prefix;
if (!value.contains("=?") && latin1->canEncode(value)) { if (!value.contains("=?") && latin1->canEncode(value)) {
bool firstWord = true; bool firstWord = true;
foreach (const QByteArray& word, value.toLatin1().split(' ')) { for (const QByteArray &word : asConst(value.toLatin1().split(' '))) {
if (line.size() > 78) { if (line.size() > 78) {
rv = rv + line + "\r\n"; rv = rv + line + "\r\n";
line.clear(); line.clear();

View File

@@ -50,6 +50,7 @@
#include <CoreServices/CoreServices.h> #include <CoreServices/CoreServices.h>
#endif #endif
#include "global.h"
#include "logger.h" #include "logger.h"
#include "settingsstorage.h" #include "settingsstorage.h"
#include "utils/fs.h" #include "utils/fs.h"
@@ -212,7 +213,7 @@ void Preferences::setCloseToTrayNotified(bool b)
{ {
setValue("Preferences/General/CloseToTrayNotified", b); setValue("Preferences/General/CloseToTrayNotified", b);
} }
#endif #endif // Q_OS_MAC
bool Preferences::isToolbarDisplayed() const bool Preferences::isToolbarDisplayed() const
{ {
@@ -293,7 +294,7 @@ void Preferences::setWinStartup(bool b)
settings.remove("qBittorrent"); settings.remove("qBittorrent");
} }
} }
#endif #endif // Q_OS_WIN
// Downloads // Downloads
QString Preferences::lastLocationPath() const QString Preferences::lastLocationPath() const
@@ -505,7 +506,7 @@ void Preferences::setWebUiAuthSubnetWhitelistEnabled(bool enabled)
QList<Utils::Net::Subnet> Preferences::getWebUiAuthSubnetWhitelist() const QList<Utils::Net::Subnet> Preferences::getWebUiAuthSubnetWhitelist() const
{ {
QList<Utils::Net::Subnet> subnets; QList<Utils::Net::Subnet> subnets;
foreach (const QString &rawSubnet, value("Preferences/WebUI/AuthSubnetWhitelist").toStringList()) { for (const QString &rawSubnet : asConst(value("Preferences/WebUI/AuthSubnetWhitelist").toStringList())) {
bool ok = false; bool ok = false;
const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(rawSubnet.trimmed(), &ok); const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(rawSubnet.trimmed(), &ok);
if (ok) if (ok)
@@ -626,6 +627,16 @@ void Preferences::setWebUiCSRFProtectionEnabled(bool enabled)
setValue("Preferences/WebUI/CSRFProtection", enabled); setValue("Preferences/WebUI/CSRFProtection", enabled);
} }
bool Preferences::isWebUIHostHeaderValidationEnabled() const
{
return value("Preferences/WebUI/HostHeaderValidation", true).toBool();
}
void Preferences::setWebUIHostHeaderValidationEnabled(const bool enabled)
{
setValue("Preferences/WebUI/HostHeaderValidation", enabled);
}
bool Preferences::isWebUiHttpsEnabled() const bool Preferences::isWebUiHttpsEnabled() const
{ {
return value("Preferences/WebUI/HTTPS/Enabled", false).toBool(); return value("Preferences/WebUI/HTTPS/Enabled", false).toBool();
@@ -957,7 +968,7 @@ void Preferences::setMagnetLinkAssoc(bool set)
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0); SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
} }
#endif #endif // Q_OS_WIN
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
namespace namespace
@@ -1013,7 +1024,7 @@ void Preferences::setMagnetLinkAssoc()
CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle()); CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
LSSetDefaultHandlerForURLScheme(magnetUrlScheme, myBundleId); LSSetDefaultHandlerForURLScheme(magnetUrlScheme, myBundleId);
} }
#endif #endif // Q_OS_MAC
int Preferences::getTrackerPort() const int Preferences::getTrackerPort() const
{ {
@@ -1416,8 +1427,8 @@ void Preferences::setToolbarTextPosition(const int position)
QList<QNetworkCookie> Preferences::getNetworkCookies() const QList<QNetworkCookie> Preferences::getNetworkCookies() const
{ {
QList<QNetworkCookie> cookies; QList<QNetworkCookie> cookies;
QStringList rawCookies = value("Network/Cookies").toStringList(); const QStringList rawCookies = value("Network/Cookies").toStringList();
foreach (const QString &rawCookie, rawCookies) for (const QString &rawCookie : rawCookies)
cookies << QNetworkCookie::parseCookies(rawCookie.toUtf8()); cookies << QNetworkCookie::parseCookies(rawCookie.toUtf8());
return cookies; return cookies;
@@ -1426,7 +1437,7 @@ QList<QNetworkCookie> Preferences::getNetworkCookies() const
void Preferences::setNetworkCookies(const QList<QNetworkCookie> &cookies) void Preferences::setNetworkCookies(const QList<QNetworkCookie> &cookies)
{ {
QStringList rawCookies; QStringList rawCookies;
foreach (const QNetworkCookie &cookie, cookies) for (const QNetworkCookie &cookie : cookies)
rawCookies << cookie.toRawForm(); rawCookies << cookie.toRawForm();
setValue("Network/Cookies", rawCookies); setValue("Network/Cookies", rawCookies);
@@ -1467,10 +1478,10 @@ void Preferences::upgrade()
{ {
SettingsStorage *settingsStorage = SettingsStorage::instance(); SettingsStorage *settingsStorage = SettingsStorage::instance();
QStringList labels = value("TransferListFilters/customLabels").toStringList(); const QStringList labels = value("TransferListFilters/customLabels").toStringList();
if (!labels.isEmpty()) { if (!labels.isEmpty()) {
QVariantMap categories = value("BitTorrent/Session/Categories").toMap(); QVariantMap categories = value("BitTorrent/Session/Categories").toMap();
foreach (const QString &label, labels) { for (const QString &label : labels) {
if (!categories.contains(label)) if (!categories.contains(label))
categories[label] = ""; categories[label] = "";
} }

View File

@@ -201,6 +201,8 @@ public:
void setWebUiClickjackingProtectionEnabled(bool enabled); void setWebUiClickjackingProtectionEnabled(bool enabled);
bool isWebUiCSRFProtectionEnabled() const; bool isWebUiCSRFProtectionEnabled() const;
void setWebUiCSRFProtectionEnabled(bool enabled); void setWebUiCSRFProtectionEnabled(bool enabled);
bool isWebUIHostHeaderValidationEnabled() const;
void setWebUIHostHeaderValidationEnabled(bool enabled);
// HTTPS // HTTPS
bool isWebUiHttpsEnabled() const; bool isWebUiHttpsEnabled() const;
@@ -297,7 +299,7 @@ public:
void setCloseToTrayNotified(bool b); void setCloseToTrayNotified(bool b);
TrayIcon::Style trayIconStyle() const; TrayIcon::Style trayIconStyle() const;
void setTrayIconStyle(TrayIcon::Style style); void setTrayIconStyle(TrayIcon::Style style);
#endif #endif // Q_OS_MAC
// Stuff that don't appear in the Options GUI but are saved // Stuff that don't appear in the Options GUI but are saved
// in the same file. // in the same file.

View File

@@ -435,13 +435,13 @@ namespace
if (leapSecond) if (leapSecond)
second = 59; // apparently a leap second - validate below, once time zone is known second = 59; // apparently a leap second - validate below, once time zone is known
int month = 0; int month = 0;
for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month); for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month);
int dayOfWeek = -1; int dayOfWeek = -1;
if (!parts[nwday].isEmpty()) { if (!parts[nwday].isEmpty()) {
// Look up the weekday name // Look up the weekday name
while (++dayOfWeek < 7 && (shortDay[dayOfWeek] != parts[nwday])); while ((++dayOfWeek < 7) && (shortDay[dayOfWeek] != parts[nwday]));
if (dayOfWeek >= 7) if (dayOfWeek >= 7)
for (dayOfWeek = 0; dayOfWeek < 7 && (longDay[dayOfWeek] != parts[nwday]); ++dayOfWeek); for (dayOfWeek = 0; (dayOfWeek < 7) && (longDay[dayOfWeek] != parts[nwday]); ++dayOfWeek);
} }
// if (month >= 12 || dayOfWeek >= 7 // if (month >= 12 || dayOfWeek >= 7
@@ -450,7 +450,7 @@ namespace
int i = parts[nyear].size(); int i = parts[nyear].size();
if (i < 4) { if (i < 4) {
// It's an obsolete year specification with less than 4 digits // It's an obsolete year specification with less than 4 digits
year += (i == 2 && year < 50) ? 2000 : 1900; year += ((i == 2) && (year < 50)) ? 2000 : 1900;
} }
// Parse the UTC offset part // Parse the UTC offset part
@@ -473,17 +473,17 @@ namespace
else { else {
// Check for an obsolete time zone name // Check for an obsolete time zone name
QByteArray zone = parts[10].toLatin1(); QByteArray zone = parts[10].toLatin1();
if (zone.length() == 1 && isalpha(zone[0]) && toupper(zone[0]) != 'J') { if ((zone.length() == 1) && (isalpha(zone[0])) && (toupper(zone[0]) != 'J')) {
negOffset = true; // military zone: RFC 2822 treats as '-0000' negOffset = true; // military zone: RFC 2822 treats as '-0000'
} }
else if (zone != "UT" && zone != "GMT") { // treated as '+0000' else if ((zone != "UT") && (zone != "GMT")) { // treated as '+0000'
offset = (zone == "EDT") offset = (zone == "EDT")
? -4 * 3600 ? -4 * 3600
: ((zone == "EST") || (zone == "CDT")) : ((zone == "EST") || (zone == "CDT"))
? -5 * 3600 ? -5 * 3600
: ((zone == "CST") || (zone == "MDT")) : ((zone == "CST") || (zone == "MDT"))
? -6 * 3600 ? -6 * 3600
: (zone == "MST" || zone == "PDT") : ((zone == "MST") || (zone == "PDT"))
? -7 * 3600 ? -7 * 3600
: (zone == "PST") : (zone == "PST")
? -8 * 3600 ? -8 * 3600
@@ -502,12 +502,12 @@ namespace
} }
} }
QDate qdate(year, month + 1, day); // convert date, and check for out-of-range QDate qDate(year, month + 1, day); // convert date, and check for out-of-range
if (!qdate.isValid()) if (!qDate.isValid())
return QDateTime::currentDateTime(); return QDateTime::currentDateTime();
QTime qTime(hour, minute, second); QTime qTime(hour, minute, second);
QDateTime result(qdate, qTime, Qt::UTC); QDateTime result(qDate, qTime, Qt::UTC);
if (offset) if (offset)
result = result.addSecs(-offset); result = result.addSecs(-offset);
if (!result.isValid()) if (!result.isValid())

View File

@@ -241,7 +241,7 @@ void AutoDownloader::importRules(const QByteArray &data, AutoDownloader::RulesFi
QByteArray AutoDownloader::exportRulesToJSONFormat() const QByteArray AutoDownloader::exportRulesToJSONFormat() const
{ {
QJsonObject jsonObj; QJsonObject jsonObj;
for (const auto &rule : copyAsConst(rules())) for (const auto &rule : asConst(rules()))
jsonObj.insert(rule.name(), rule.toJsonObject()); jsonObj.insert(rule.name(), rule.toJsonObject());
return QJsonDocument(jsonObj).toJson(); return QJsonDocument(jsonObj).toJson();
@@ -249,14 +249,14 @@ QByteArray AutoDownloader::exportRulesToJSONFormat() const
void AutoDownloader::importRulesFromJSONFormat(const QByteArray &data) void AutoDownloader::importRulesFromJSONFormat(const QByteArray &data)
{ {
for (const auto &rule : copyAsConst(rulesFromJSON(data))) for (const auto &rule : asConst(rulesFromJSON(data)))
insertRule(rule); insertRule(rule);
} }
QByteArray AutoDownloader::exportRulesToLegacyFormat() const QByteArray AutoDownloader::exportRulesToLegacyFormat() const
{ {
QVariantHash dict; QVariantHash dict;
for (const auto &rule : copyAsConst(rules())) for (const auto &rule : asConst(rules()))
dict[rule.name()] = rule.toLegacyDict(); dict[rule.name()] = rule.toLegacyDict();
QByteArray data; QByteArray data;
@@ -276,7 +276,7 @@ void AutoDownloader::importRulesFromLegacyFormat(const QByteArray &data)
if (in.status() != QDataStream::Ok) if (in.status() != QDataStream::Ok)
throw ParsingError(tr("Invalid data format")); throw ParsingError(tr("Invalid data format"));
for (const QVariant &val : qAsConst(dict)) for (const QVariant &val : asConst(dict))
insertRule(AutoDownloadRule::fromLegacyDict(val.toHash())); insertRule(AutoDownloadRule::fromLegacyDict(val.toHash()));
} }
@@ -373,7 +373,7 @@ void AutoDownloader::addJobForArticle(Article *article)
void AutoDownloader::processJob(const QSharedPointer<ProcessingJob> &job) void AutoDownloader::processJob(const QSharedPointer<ProcessingJob> &job)
{ {
for (AutoDownloadRule &rule: m_rules) { for (AutoDownloadRule &rule : m_rules) {
if (!rule.isEnabled()) continue; if (!rule.isEnabled()) continue;
if (!rule.feedURLs().contains(job->feedURL)) continue; if (!rule.feedURLs().contains(job->feedURL)) continue;
if (!rule.accepts(job->articleData)) continue; if (!rule.accepts(job->articleData)) continue;
@@ -435,8 +435,8 @@ void AutoDownloader::loadRules(const QByteArray &data)
void AutoDownloader::loadRulesLegacy() void AutoDownloader::loadRulesLegacy()
{ {
SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss")); SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss"));
QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash(); const QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash();
foreach (const QVariant &ruleVar, rules) { for (const QVariant &ruleVar : rules) {
auto rule = AutoDownloadRule::fromLegacyDict(ruleVar.toHash()); auto rule = AutoDownloadRule::fromLegacyDict(ruleVar.toHash());
if (!rule.name().isEmpty()) if (!rule.name().isEmpty())
insertRule(rule); insertRule(rule);
@@ -451,7 +451,7 @@ void AutoDownloader::store()
m_savingTimer.stop(); m_savingTimer.stop();
QJsonObject jsonObj; QJsonObject jsonObj;
foreach (auto rule, m_rules) for (const auto &rule : asConst(m_rules))
jsonObj.insert(rule.name(), rule.toJsonObject()); jsonObj.insert(rule.name(), rule.toJsonObject());
m_fileStorage->store(RulesFileName, QJsonDocument(jsonObj).toJson()); m_fileStorage->store(RulesFileName, QJsonDocument(jsonObj).toJson());
@@ -473,7 +473,7 @@ void AutoDownloader::resetProcessingQueue()
m_processingQueue.clear(); m_processingQueue.clear();
if (!m_processingEnabled) return; if (!m_processingEnabled) return;
foreach (Article *article, Session::instance()->rootFolder()->articles()) { for (Article *article : asConst(Session::instance()->rootFolder()->articles())) {
if (!article->isRead() && !article->torrentUrl().isEmpty()) if (!article->isRead() && !article->torrentUrl().isEmpty())
addJobForArticle(article); addJobForArticle(article);
} }

View File

@@ -126,7 +126,7 @@ namespace RSS
bool smartFilter = false; bool smartFilter = false;
QStringList previouslyMatchedEpisodes; QStringList previouslyMatchedEpisodes;
mutable QString lastComputedEpisode; mutable QStringList lastComputedEpisodes;
mutable QHash<QString, QRegularExpression> cachedRegexes; mutable QHash<QString, QRegularExpression> cachedRegexes;
bool operator==(const AutoDownloadRuleData &other) const bool operator==(const AutoDownloadRuleData &other) const
@@ -237,7 +237,7 @@ bool AutoDownloadRule::matchesMustContainExpression(const QString &articleTitle)
// Each expression is either a regex, or a set of wildcards separated by whitespace. // Each expression is either a regex, or a set of wildcards separated by whitespace.
// Accept if any complete expression matches. // Accept if any complete expression matches.
for (const QString &expression : qAsConst(m_dataPtr->mustContain)) { for (const QString &expression : asConst(m_dataPtr->mustContain)) {
// A regex of the form "expr|" will always match, so do the same for wildcards // A regex of the form "expr|" will always match, so do the same for wildcards
if (matchesExpression(articleTitle, expression)) if (matchesExpression(articleTitle, expression))
return true; return true;
@@ -246,14 +246,14 @@ bool AutoDownloadRule::matchesMustContainExpression(const QString &articleTitle)
return false; return false;
} }
bool AutoDownloadRule::matchesMustNotContainExpression(const QString& articleTitle) const bool AutoDownloadRule::matchesMustNotContainExpression(const QString &articleTitle) const
{ {
if (m_dataPtr->mustNotContain.empty()) if (m_dataPtr->mustNotContain.empty())
return true; return true;
// Each expression is either a regex, or a set of wildcards separated by whitespace. // Each expression is either a regex, or a set of wildcards separated by whitespace.
// Reject if any complete expression matches. // Reject if any complete expression matches.
for (const QString &expression : qAsConst(m_dataPtr->mustNotContain)) { for (const QString &expression : asConst(m_dataPtr->mustNotContain)) {
// A regex of the form "expr|" will always match, so do the same for wildcards // A regex of the form "expr|" will always match, so do the same for wildcards
if (matchesExpression(articleTitle, expression)) if (matchesExpression(articleTitle, expression))
return false; return false;
@@ -262,10 +262,10 @@ bool AutoDownloadRule::matchesMustNotContainExpression(const QString& articleTit
return true; return true;
} }
bool AutoDownloadRule::matchesEpisodeFilterExpression(const QString& articleTitle) const bool AutoDownloadRule::matchesEpisodeFilterExpression(const QString &articleTitle) const
{ {
// Reset the lastComputedEpisode, we don't want to leak it between matches // Reset the lastComputedEpisode, we don't want to leak it between matches
m_dataPtr->lastComputedEpisode.clear(); m_dataPtr->lastComputedEpisodes.clear();
if (m_dataPtr->episodeFilter.isEmpty()) if (m_dataPtr->episodeFilter.isEmpty())
return true; return true;
@@ -332,7 +332,7 @@ bool AutoDownloadRule::matchesEpisodeFilterExpression(const QString& articleTitl
return false; return false;
} }
bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString& articleTitle) const bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString &articleTitle) const
{ {
if (!useSmartFilter()) if (!useSmartFilter())
return true; return true;
@@ -343,11 +343,35 @@ bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString& articleTitle) co
// See if this episode has been downloaded before // See if this episode has been downloaded before
const bool previouslyMatched = m_dataPtr->previouslyMatchedEpisodes.contains(episodeStr); const bool previouslyMatched = m_dataPtr->previouslyMatchedEpisodes.contains(episodeStr);
const bool isRepack = articleTitle.contains("REPACK", Qt::CaseInsensitive) || articleTitle.contains("PROPER", Qt::CaseInsensitive); if (previouslyMatched) {
if (previouslyMatched && (!isRepack || !AutoDownloader::instance()->downloadRepacks())) if (!AutoDownloader::instance()->downloadRepacks())
return false; return false;
m_dataPtr->lastComputedEpisode = episodeStr; // Now see if we've downloaded this particular repack/proper combination
const bool isRepack = articleTitle.contains("REPACK", Qt::CaseInsensitive);
const bool isProper = articleTitle.contains("PROPER", Qt::CaseInsensitive);
if (!isRepack && !isProper)
return false;
const QString fullEpisodeStr = QString("%1%2%3").arg(episodeStr,
isRepack ? "-REPACK" : "",
isProper ? "-PROPER" : "");
const bool previouslyMatchedFull = m_dataPtr->previouslyMatchedEpisodes.contains(fullEpisodeStr);
if (previouslyMatchedFull)
return false;
m_dataPtr->lastComputedEpisodes.append(fullEpisodeStr);
// If this is a REPACK and PROPER download, add the individual entries to the list
// so we don't download those
if (isRepack && isProper) {
m_dataPtr->lastComputedEpisodes.append(QString("%1-REPACK").arg(episodeStr));
m_dataPtr->lastComputedEpisodes.append(QString("%1-PROPER").arg(episodeStr));
}
}
m_dataPtr->lastComputedEpisodes.append(episodeStr);
return true; return true;
} }
@@ -379,10 +403,10 @@ bool AutoDownloadRule::accepts(const QVariantHash &articleData)
setLastMatch(articleData[Article::KeyDate].toDateTime()); setLastMatch(articleData[Article::KeyDate].toDateTime());
if (!m_dataPtr->lastComputedEpisode.isEmpty()) { // If there's a matched episode string, add that to the previously matched list
// TODO: probably need to add a marker for PROPER/REPACK to avoid duplicate downloads if (!m_dataPtr->lastComputedEpisodes.isEmpty()) {
m_dataPtr->previouslyMatchedEpisodes.append(m_dataPtr->lastComputedEpisode); m_dataPtr->previouslyMatchedEpisodes.append(m_dataPtr->lastComputedEpisodes);
m_dataPtr->lastComputedEpisode.clear(); m_dataPtr->lastComputedEpisodes.clear();
} }
return true; return true;
@@ -442,7 +466,7 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
QStringList feedURLs; QStringList feedURLs;
if (feedsVal.isString()) if (feedsVal.isString())
feedURLs << feedsVal.toString(); feedURLs << feedsVal.toString();
else foreach (const QJsonValue &urlVal, feedsVal.toArray()) else for (const QJsonValue &urlVal : asConst(feedsVal.toArray()))
feedURLs << urlVal.toString(); feedURLs << urlVal.toString();
rule.setFeedURLs(feedURLs); rule.setFeedURLs(feedURLs);
@@ -452,7 +476,7 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
previouslyMatched << previouslyMatchedVal.toString(); previouslyMatched << previouslyMatchedVal.toString();
} }
else { else {
foreach (const QJsonValue &val, previouslyMatchedVal.toArray()) for (const QJsonValue &val : asConst(previouslyMatchedVal.toArray()))
previouslyMatched << val.toString(); previouslyMatched << val.toString();
} }
rule.setPreviouslyMatchedEpisodes(previouslyMatched); rule.setPreviouslyMatchedEpisodes(previouslyMatched);

View File

@@ -109,7 +109,7 @@ QList<Article *> Feed::articles() const
void Feed::markAsRead() void Feed::markAsRead()
{ {
auto oldUnreadCount = m_unreadCount; auto oldUnreadCount = m_unreadCount;
foreach (Article *article, m_articles) { for (Article *article : asConst(m_articles)) {
if (!article->isRead()) { if (!article->isRead()) {
article->disconnect(this); article->disconnect(this);
article->markAsRead(); article->markAsRead();
@@ -282,9 +282,9 @@ void Feed::loadArticles(const QByteArray &data)
return; return;
} }
QJsonArray jsonArr = jsonDoc.array(); const QJsonArray jsonArr = jsonDoc.array();
int i = -1; int i = -1;
foreach (const QJsonValue &jsonVal, jsonArr) { for (const QJsonValue &jsonVal : jsonArr) {
++i; ++i;
if (!jsonVal.isObject()) { if (!jsonVal.isObject()) {
LogMsg(tr("Couldn't load RSS article '%1#%2'. Invalid data format.").arg(m_url).arg(i) LogMsg(tr("Couldn't load RSS article '%1#%2'. Invalid data format.").arg(m_url).arg(i)
@@ -304,9 +304,9 @@ void Feed::loadArticles(const QByteArray &data)
void Feed::loadArticlesLegacy() void Feed::loadArticlesLegacy()
{ {
SettingsPtr qBTRSSFeeds = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss-feeds")); SettingsPtr qBTRSSFeeds = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss-feeds"));
QVariantHash allOldItems = qBTRSSFeeds->value("old_items").toHash(); const QVariantHash allOldItems = qBTRSSFeeds->value("old_items").toHash();
foreach (const QVariant &var, allOldItems.value(m_url).toList()) { for (const QVariant &var : asConst(allOldItems.value(m_url).toList())) {
auto hash = var.toHash(); auto hash = var.toHash();
// update legacy keys // update legacy keys
hash[Article::KeyLink] = hash.take(QLatin1String("news_link")); hash[Article::KeyLink] = hash.take(QLatin1String("news_link"));
@@ -329,7 +329,7 @@ void Feed::store()
m_savingTimer.stop(); m_savingTimer.stop();
QJsonArray jsonArr; QJsonArray jsonArr;
foreach (Article *article, m_articles) for (Article *article :asConst(m_articles))
jsonArr << article->toJsonObject(); jsonArr << article->toJsonObject();
m_session->dataFileStorage()->store(m_dataFileName, QJsonDocument(jsonArr).toJson()); m_session->dataFileStorage()->store(m_dataFileName, QJsonDocument(jsonArr).toJson());
@@ -474,7 +474,7 @@ int Feed::updateArticles(const QList<QVariantHash> &loadedArticles)
return (a1.first > a2.first); return (a1.first > a2.first);
}); });
if (sortData.size() > m_session->maxArticlesPerFeed()) if (sortData.size() > static_cast<uint>(m_session->maxArticlesPerFeed()))
sortData.resize(m_session->maxArticlesPerFeed()); sortData.resize(m_session->maxArticlesPerFeed());
int newArticlesCount = 0; int newArticlesCount = 0;
@@ -507,7 +507,7 @@ QJsonValue Feed::toJsonValue(bool withData) const
jsonObj.insert(KEY_HASERROR, hasError()); jsonObj.insert(KEY_HASERROR, hasError());
QJsonArray jsonArr; QJsonArray jsonArr;
for (Article *article : qAsConst(m_articles)) for (Article *article : asConst(m_articles))
jsonArr << article->toJsonObject(); jsonArr << article->toJsonObject();
jsonObj.insert(KEY_ARTICLES, jsonArr); jsonObj.insert(KEY_ARTICLES, jsonArr);
} }

View File

@@ -47,7 +47,7 @@ Folder::~Folder()
{ {
emit aboutToBeDestroyed(this); emit aboutToBeDestroyed(this);
foreach (auto item, items()) for (auto item : asConst(items()))
delete item; delete item;
} }
@@ -55,7 +55,7 @@ QList<Article *> Folder::articles() const
{ {
QList<Article *> news; QList<Article *> news;
foreach (Item *item, items()) { for (Item *item : asConst(items())) {
int n = news.size(); int n = news.size();
news << item->articles(); news << item->articles();
std::inplace_merge(news.begin(), news.begin() + n, news.end() std::inplace_merge(news.begin(), news.begin() + n, news.end()
@@ -70,20 +70,20 @@ QList<Article *> Folder::articles() const
int Folder::unreadCount() const int Folder::unreadCount() const
{ {
int count = 0; int count = 0;
foreach (Item *item, items()) for (Item *item : asConst(items()))
count += item->unreadCount(); count += item->unreadCount();
return count; return count;
} }
void Folder::markAsRead() void Folder::markAsRead()
{ {
foreach (Item *item, items()) for (Item *item : asConst(items()))
item->markAsRead(); item->markAsRead();
} }
void Folder::refresh() void Folder::refresh()
{ {
foreach (Item *item, items()) for (Item *item : asConst(items()))
item->refresh(); item->refresh();
} }
@@ -95,7 +95,7 @@ QList<Item *> Folder::items() const
QJsonValue Folder::toJsonValue(bool withData) const QJsonValue Folder::toJsonValue(bool withData) const
{ {
QJsonObject jsonObj; QJsonObject jsonObj;
foreach (Item *item, items()) for (Item *item : asConst(items()))
jsonObj.insert(item->name(), item->toJsonValue(withData)); jsonObj.insert(item->name(), item->toJsonValue(withData));
return jsonObj; return jsonObj;
@@ -108,7 +108,7 @@ void Folder::handleItemUnreadCountChanged()
void Folder::cleanup() void Folder::cleanup()
{ {
foreach (Item *item, items()) for (Item *item : asConst(items()))
item->cleanup(); item->cleanup();
} }
@@ -123,7 +123,7 @@ void Folder::addItem(Item *item)
connect(item, &Item::articleAboutToBeRemoved, this, &Item::articleAboutToBeRemoved); connect(item, &Item::articleAboutToBeRemoved, this, &Item::articleAboutToBeRemoved);
connect(item, &Item::unreadCountChanged, this, &Folder::handleItemUnreadCountChanged); connect(item, &Item::unreadCountChanged, this, &Folder::handleItemUnreadCountChanged);
for (auto article: copyAsConst(item->articles())) for (auto article : asConst(item->articles()))
emit newArticle(article); emit newArticle(article);
if (item->unreadCount() > 0) if (item->unreadCount() > 0)
@@ -134,7 +134,7 @@ void Folder::removeItem(Item *item)
{ {
Q_ASSERT(m_items.contains(item)); Q_ASSERT(m_items.contains(item));
for (auto article: copyAsConst(item->articles())) for (auto article : asConst(item->articles()))
emit articleAboutToBeRemoved(article); emit articleAboutToBeRemoved(article);
item->disconnect(this); item->disconnect(this);

View File

@@ -41,6 +41,7 @@
#include <QVariantHash> #include <QVariantHash>
#include "../asyncfilestorage.h" #include "../asyncfilestorage.h"
#include "../global.h"
#include "../logger.h" #include "../logger.h"
#include "../profile.h" #include "../profile.h"
#include "../settingsstorage.h" #include "../settingsstorage.h"
@@ -283,7 +284,7 @@ void Session::load()
void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder) void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
{ {
bool updated = false; bool updated = false;
foreach (const QString &key, jsonObj.keys()) { for (const QString &key : asConst(jsonObj.keys())) {
const QJsonValue val {jsonObj[key]}; const QJsonValue val {jsonObj[key]};
if (val.isString()) { if (val.isString()) {
// previous format (reduced form) doesn't contain UID // previous format (reduced form) doesn't contain UID
@@ -355,7 +356,7 @@ void Session::loadLegacy()
const QString parentFolderPath = Item::parentPath(legacyPath); const QString parentFolderPath = Item::parentPath(legacyPath);
const QString feedUrl = Item::relativeName(legacyPath); const QString feedUrl = Item::relativeName(legacyPath);
foreach (const QString &folderPath, Item::expandPath(parentFolderPath)) for (const QString &folderPath : asConst(Item::expandPath(parentFolderPath)))
addFolder(folderPath); addFolder(folderPath);
const QString feedPath = feedAliases[i].isEmpty() const QString feedPath = feedAliases[i].isEmpty()

View File

@@ -35,6 +35,7 @@
#include "bittorrent/session.h" #include "bittorrent/session.h"
#include "filesystemwatcher.h" #include "filesystemwatcher.h"
#include "global.h"
#include "preferences.h" #include "preferences.h"
#include "utils/fs.h" #include "utils/fs.h"
@@ -254,7 +255,7 @@ void ScanFoldersModel::addToFSWatcher(const QStringList &watchPaths)
if (!m_fsWatcher) if (!m_fsWatcher)
return; // addPath() wasn't called before this return; // addPath() wasn't called before this
foreach (const QString &path, watchPaths) { for (const QString &path : watchPaths) {
QDir watchDir(path); QDir watchDir(path);
const QString canonicalWatchPath = watchDir.canonicalPath(); const QString canonicalWatchPath = watchDir.canonicalPath();
m_fsWatcher->addPath(canonicalWatchPath); m_fsWatcher->addPath(canonicalWatchPath);
@@ -282,7 +283,7 @@ bool ScanFoldersModel::removePath(const QString &path, bool removeFromFSWatcher)
void ScanFoldersModel::removeFromFSWatcher(const QStringList &watchPaths) void ScanFoldersModel::removeFromFSWatcher(const QStringList &watchPaths)
{ {
foreach (const QString &path, watchPaths) for (const QString &path : watchPaths)
m_fsWatcher->removePath(path); m_fsWatcher->removePath(path);
} }
@@ -326,7 +327,7 @@ void ScanFoldersModel::makePersistent()
{ {
QVariantHash dirs; QVariantHash dirs;
foreach (const PathData *pathData, m_pathList) { for (const PathData *pathData : asConst(m_pathList)) {
if (pathData->downloadType == CUSTOM_LOCATION) if (pathData->downloadType == CUSTOM_LOCATION)
dirs.insert(Utils::Fs::fromNativePath(pathData->watchPath), Utils::Fs::fromNativePath(pathData->downloadPath)); dirs.insert(Utils::Fs::fromNativePath(pathData->watchPath), Utils::Fs::fromNativePath(pathData->downloadPath));
else else
@@ -350,7 +351,7 @@ void ScanFoldersModel::configure()
void ScanFoldersModel::addTorrentsToSession(const QStringList &pathList) void ScanFoldersModel::addTorrentsToSession(const QStringList &pathList)
{ {
foreach (const QString &file, pathList) { for (const QString &file : pathList) {
qDebug("File %s added", qUtf8Printable(file)); qDebug("File %s added", qUtf8Printable(file));
BitTorrent::AddTorrentParams params; BitTorrent::AddTorrentParams params;

View File

@@ -32,6 +32,7 @@
#include <QProcess> #include <QProcess>
#include <QTimer> #include <QTimer>
#include "../global.h"
#include "../utils/foreignapps.h" #include "../utils/foreignapps.h"
#include "../utils/fs.h" #include "../utils/fs.h"
#include "searchpluginmanager.h" #include "searchpluginmanager.h"
@@ -138,7 +139,7 @@ void SearchHandler::readSearchOutput()
m_searchResultLineTruncated = lines.takeLast().trimmed(); m_searchResultLineTruncated = lines.takeLast().trimmed();
QList<SearchResult> searchResultList; QList<SearchResult> searchResultList;
foreach (const QByteArray &line, lines) { for (const QByteArray &line : asConst(lines)) {
SearchResult searchResult; SearchResult searchResult;
if (parseSearchResult(QString::fromUtf8(line), searchResult)) if (parseSearchResult(QString::fromUtf8(line), searchResult))
searchResultList << searchResult; searchResultList << searchResult;

View File

@@ -65,7 +65,7 @@ namespace
while (iter.hasNext()) while (iter.hasNext())
dirs += iter.next(); dirs += iter.next();
for (const QString &dir : qAsConst(dirs)) { for (const QString &dir : asConst(dirs)) {
// python 3: remove "__pycache__" folders // python 3: remove "__pycache__" folders
if (dir.endsWith("/__pycache__")) { if (dir.endsWith("/__pycache__")) {
Utils::Fs::removeDirRecursive(dir); Utils::Fs::removeDirRecursive(dir);
@@ -101,9 +101,17 @@ SearchPluginManager::~SearchPluginManager()
SearchPluginManager *SearchPluginManager::instance() SearchPluginManager *SearchPluginManager::instance()
{ {
if (!m_instance)
m_instance = new SearchPluginManager;
return m_instance; return m_instance;
} }
void SearchPluginManager::freeInstance()
{
if (m_instance)
delete m_instance;
}
QStringList SearchPluginManager::allPlugins() const QStringList SearchPluginManager::allPlugins() const
{ {
return m_plugins.keys(); return m_plugins.keys();
@@ -112,7 +120,7 @@ QStringList SearchPluginManager::allPlugins() const
QStringList SearchPluginManager::enabledPlugins() const QStringList SearchPluginManager::enabledPlugins() const
{ {
QStringList plugins; QStringList plugins;
for (const PluginInfo *plugin : qAsConst(m_plugins)) { for (const PluginInfo *plugin : asConst(m_plugins)) {
if (plugin->enabled) if (plugin->enabled)
plugins << plugin->name; plugins << plugin->name;
} }
@@ -123,9 +131,9 @@ QStringList SearchPluginManager::enabledPlugins() const
QStringList SearchPluginManager::supportedCategories() const QStringList SearchPluginManager::supportedCategories() const
{ {
QStringList result; QStringList result;
for (const PluginInfo *plugin : qAsConst(m_plugins)) { for (const PluginInfo *plugin : asConst(m_plugins)) {
if (plugin->enabled) { if (plugin->enabled) {
foreach (QString cat, plugin->supportedCategories) { for (const QString &cat : plugin->supportedCategories) {
if (!result.contains(cat)) if (!result.contains(cat))
result << cat; result << cat;
} }
@@ -146,7 +154,7 @@ QStringList SearchPluginManager::getPluginCategories(const QString &pluginName)
plugins << pluginName.trimmed(); plugins << pluginName.trimmed();
QSet<QString> categories; QSet<QString> categories;
for (const QString &name : qAsConst(plugins)) { for (const QString &name : asConst(plugins)) {
const PluginInfo *plugin = pluginInfo(name); const PluginInfo *plugin = pluginInfo(name);
if (!plugin) continue; // plugin wasn't found if (!plugin) continue; // plugin wasn't found
for (const QString &category : plugin->supportedCategories) for (const QString &category : plugin->supportedCategories)
@@ -269,9 +277,8 @@ bool SearchPluginManager::uninstallPlugin(const QString &name)
QDir pluginsFolder(pluginsLocation()); QDir pluginsFolder(pluginsLocation());
QStringList filters; QStringList filters;
filters << name + ".*"; filters << name + ".*";
QStringList files = pluginsFolder.entryList(filters, QDir::Files, QDir::Unsorted); const QStringList files = pluginsFolder.entryList(filters, QDir::Files, QDir::Unsorted);
QString file; for (const QString &file : files)
foreach (file, files)
Utils::Fs::forceRemove(pluginsFolder.absoluteFilePath(file)); Utils::Fs::forceRemove(pluginsFolder.absoluteFilePath(file));
// Remove it from supported engines // Remove it from supported engines
delete m_plugins.take(name); delete m_plugins.take(name);

View File

@@ -62,6 +62,7 @@ public:
~SearchPluginManager() override; ~SearchPluginManager() override;
static SearchPluginManager *instance(); static SearchPluginManager *instance();
static void freeInstance();
QStringList allPlugins() const; QStringList allPlugins() const;
QStringList enabledPlugins() const; QStringList enabledPlugins() const;

View File

@@ -33,6 +33,7 @@
#include <QFile> #include <QFile>
#include <QHash> #include <QHash>
#include "global.h"
#include "logger.h" #include "logger.h"
#include "profile.h" #include "profile.h"
#include "utils/fs.h" #include "utils/fs.h"
@@ -286,7 +287,7 @@ QString TransactionalSettings::deserialize(const QString &name, QVariantHash &da
// Copy everything into memory. This means even keys inserted in the file manually // Copy everything into memory. This means even keys inserted in the file manually
// or that we don't touch directly in this code (eg disabled by ifdef). This ensures // or that we don't touch directly in this code (eg disabled by ifdef). This ensures
// that they will be copied over when save our settings to disk. // that they will be copied over when save our settings to disk.
foreach (const QString &key, settings->allKeys()) for (const QString &key : asConst(settings->allKeys()))
data.insert(key, settings->value(key)); data.insert(key, settings->value(key));
return settings->fileName(); return settings->fileName();

View File

@@ -229,7 +229,7 @@ namespace
return QString(); return QString();
} }
#endif #endif // Q_OS_WIN
} }
bool Utils::ForeignApps::PythonInfo::isValid() const bool Utils::ForeignApps::PythonInfo::isValid() const

View File

@@ -133,7 +133,7 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
std::sort(dirList.begin(), dirList.end() std::sort(dirList.begin(), dirList.end()
, [](const QString &l, const QString &r) { return l.count('/') > r.count('/'); }); , [](const QString &l, const QString &r) { return l.count('/') > r.count('/'); });
for (const QString &p : qAsConst(dirList)) { for (const QString &p : asConst(dirList)) {
// remove unwanted files // remove unwanted files
for (const QString &f : deleteFilesList) { for (const QString &f : deleteFilesList) {
forceRemove(p + f); forceRemove(p + f);
@@ -141,7 +141,7 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
// remove temp files on linux (file ends with '~'), e.g. `filename~` // remove temp files on linux (file ends with '~'), e.g. `filename~`
QDir dir(p); QDir dir(p);
QStringList tmpFileList = dir.entryList(QDir::Files); const QStringList tmpFileList = dir.entryList(QDir::Files);
for (const QString &f : tmpFileList) { for (const QString &f : tmpFileList) {
if (f.endsWith('~')) if (f.endsWith('~'))
forceRemove(p + f); forceRemove(p + f);
@@ -329,7 +329,7 @@ bool Utils::Fs::isNetworkFileSystem(const QString &path)
return ((strncmp(buf.f_fstypename, "cifs", sizeof(buf.f_fstypename)) == 0) return ((strncmp(buf.f_fstypename, "cifs", sizeof(buf.f_fstypename)) == 0)
|| (strncmp(buf.f_fstypename, "nfs", sizeof(buf.f_fstypename)) == 0) || (strncmp(buf.f_fstypename, "nfs", sizeof(buf.f_fstypename)) == 0)
|| (strncmp(buf.f_fstypename, "smbfs", sizeof(buf.f_fstypename)) == 0)); || (strncmp(buf.f_fstypename, "smbfs", sizeof(buf.f_fstypename)) == 0));
#else #else // Q_OS_WIN
QString file = path; QString file = path;
if (!file.endsWith('/')) if (!file.endsWith('/'))
file += '/'; file += '/';
@@ -351,6 +351,6 @@ bool Utils::Fs::isNetworkFileSystem(const QString &path)
default: default:
return false; return false;
} }
#endif #endif // Q_OS_WIN
} }
#endif #endif // Q_OS_HAIKU

View File

@@ -66,7 +66,7 @@
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
#include "base/utils/version.h" #include "base/utils/version.h"
#endif #endif
#endif #endif // DISABLE_GUI
#include "base/logger.h" #include "base/logger.h"
#include "base/unicodestrings.h" #include "base/unicodestrings.h"
@@ -391,7 +391,7 @@ QString Utils::Misc::getUserIDString()
QStringList Utils::Misc::toStringList(const QList<bool> &l) QStringList Utils::Misc::toStringList(const QList<bool> &l)
{ {
QStringList ret; QStringList ret;
foreach (const bool &b, l) for (const bool b : l)
ret << (b ? "1" : "0"); ret << (b ? "1" : "0");
return ret; return ret;
} }
@@ -399,7 +399,7 @@ QStringList Utils::Misc::toStringList(const QList<bool> &l)
QList<int> Utils::Misc::intListfromStringList(const QStringList &l) QList<int> Utils::Misc::intListfromStringList(const QStringList &l)
{ {
QList<int> ret; QList<int> ret;
foreach (const QString &s, l) for (const QString &s : l)
ret << s.toInt(); ret << s.toInt();
return ret; return ret;
} }
@@ -407,7 +407,7 @@ QList<int> Utils::Misc::intListfromStringList(const QStringList &l)
QList<bool> Utils::Misc::boolListfromStringList(const QStringList &l) QList<bool> Utils::Misc::boolListfromStringList(const QStringList &l)
{ {
QList<bool> ret; QList<bool> ret;
foreach (const QString &s, l) for (const QString &s : l)
ret << (s == "1"); ret << (s == "1");
return ret; return ret;
} }

View File

@@ -124,7 +124,7 @@ namespace Utils
return reinterpret_cast<T>( return reinterpret_cast<T>(
::GetProcAddress(::LoadLibraryW(pathWchar.get()), funcName)); ::GetProcAddress(::LoadLibraryW(pathWchar.get()), funcName));
} }
#endif #endif // Q_OS_WIN
} }
} }

View File

@@ -60,7 +60,7 @@ namespace Utils
{ {
if (str.length() < 2) return str; if (str.length() < 2) return str;
for (auto const quote : quotes) { for (const auto &quote : quotes) {
if (str.startsWith(quote) && str.endsWith(quote)) if (str.startsWith(quote) && str.endsWith(quote))
return str.mid(1, str.length() - 2); return str.mid(1, str.length() - 2);
} }

View File

@@ -36,6 +36,7 @@
#include <QUrl> #include <QUrl>
#include <QVector> #include <QVector>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/magneturi.h" #include "base/bittorrent/magneturi.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
@@ -143,7 +144,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
m_ui->categoryComboBox->addItem(defaultCategory); m_ui->categoryComboBox->addItem(defaultCategory);
m_ui->categoryComboBox->addItem(""); m_ui->categoryComboBox->addItem("");
foreach (const QString &category, categories) for (const QString &category : asConst(categories))
if (category != defaultCategory && category != m_torrentParams.category) if (category != defaultCategory && category != m_torrentParams.category)
m_ui->categoryComboBox->addItem(category); m_ui->categoryComboBox->addItem(category);
@@ -398,7 +399,7 @@ void AddNewTorrentDialog::saveSavePathHistory() const
// Get current history // Get current history
QStringList history = settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList(); QStringList history = settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList();
QVector<QDir> historyDirs; QVector<QDir> historyDirs;
for (const QString &path : qAsConst(history)) for (const QString &path : asConst(history))
historyDirs << QDir {path}; historyDirs << QDir {path};
const QDir selectedSavePath {m_ui->savePath->selectedPath()}; const QDir selectedSavePath {m_ui->savePath->selectedPath()};
@@ -622,18 +623,18 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &)
renameSelectedFile(); renameSelectedFile();
} }
else { else {
int prio = prio::NORMAL; BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
if (act == m_ui->actionHigh) if (act == m_ui->actionHigh)
prio = prio::HIGH; prio = BitTorrent::FilePriority::High;
else if (act == m_ui->actionMaximum) else if (act == m_ui->actionMaximum)
prio = prio::MAXIMUM; prio = BitTorrent::FilePriority::Maximum;
else if (act == m_ui->actionNotDownloaded) else if (act == m_ui->actionNotDownloaded)
prio = prio::IGNORED; prio = BitTorrent::FilePriority::Ignored;
qDebug("Setting files priority"); qDebug("Setting files priority");
foreach (const QModelIndex &index, selectedRows) { for (const QModelIndex &index : selectedRows) {
qDebug("Setting priority(%d) for file at row %d", prio, index.row()); qDebug("Setting priority(%d) for file at row %d", static_cast<int>(prio), index.row());
m_contentModel->setData(m_contentModel->index(index.row(), PRIORITY, index.parent()), prio); m_contentModel->setData(m_contentModel->index(index.row(), PRIORITY, index.parent()), static_cast<int>(prio));
} }
} }
} }

View File

@@ -36,6 +36,7 @@
#include <QNetworkInterface> #include <QNetworkInterface>
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/global.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/unicodestrings.h" #include "base/unicodestrings.h"
#include "app/application.h" #include "app/application.h"
@@ -83,6 +84,7 @@ enum AdvSettingsRows
#if LIBTORRENT_VERSION_NUM >= 10100 #if LIBTORRENT_VERSION_NUM >= 10100
ASYNC_IO_THREADS, ASYNC_IO_THREADS,
#endif #endif
CHECKING_MEM_USAGE,
// cache // cache
DISK_CACHE, DISK_CACHE,
DISK_CACHE_TTL, DISK_CACHE_TTL,
@@ -152,6 +154,8 @@ void AdvancedSettings::saveAdvancedSettings()
// Async IO threads // Async IO threads
session->setAsyncIOThreads(spinBoxAsyncIOThreads.value()); session->setAsyncIOThreads(spinBoxAsyncIOThreads.value());
#endif #endif
// Checking Memory Usage
session->setCheckingMemUsage(spinBoxCheckingMemUsage.value());
// Disk write cache // Disk write cache
session->setDiskCacheSize(spinBoxCache.value()); session->setDiskCacheSize(spinBoxCache.value());
session->setDiskCacheTTL(spinBoxCacheTTL.value()); session->setDiskCacheTTL(spinBoxCacheTTL.value());
@@ -286,13 +290,13 @@ void AdvancedSettings::updateInterfaceAddressCombo()
}; };
if (ifaceName.isEmpty()) { if (ifaceName.isEmpty()) {
foreach (const QHostAddress &ip, QNetworkInterface::allAddresses()) for (const QHostAddress &ip : asConst(QNetworkInterface::allAddresses()))
populateCombo(ip.toString(), ip.protocol()); populateCombo(ip.toString(), ip.protocol());
} }
else { else {
const QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName); const QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName);
const QList<QNetworkAddressEntry> addresses = iface.addressEntries(); const QList<QNetworkAddressEntry> addresses = iface.addressEntries();
foreach (const QNetworkAddressEntry &entry, addresses) { for (const QNetworkAddressEntry &entry : addresses) {
const QHostAddress ip = entry.ip(); const QHostAddress ip = entry.ip();
populateCombo(ip.toString(), ip.protocol()); populateCombo(ip.toString(), ip.protocol());
} }
@@ -325,6 +329,13 @@ void AdvancedSettings::loadAdvancedSettings()
spinBoxAsyncIOThreads.setValue(session->asyncIOThreads()); spinBoxAsyncIOThreads.setValue(session->asyncIOThreads());
addRow(ASYNC_IO_THREADS, tr("Asynchronous I/O threads"), &spinBoxAsyncIOThreads); addRow(ASYNC_IO_THREADS, tr("Asynchronous I/O threads"), &spinBoxAsyncIOThreads);
#endif #endif
// Checking Memory Usage
spinBoxCheckingMemUsage.setMinimum(1);
spinBoxCheckingMemUsage.setValue(session->checkingMemUsage());
spinBoxCheckingMemUsage.setSuffix(tr(" MiB"));
addRow(CHECKING_MEM_USAGE, tr("Outstanding memory when checking torrents"), &spinBoxCheckingMemUsage);
// Disk write cache // Disk write cache
spinBoxCache.setMinimum(-1); spinBoxCache.setMinimum(-1);
// When build as 32bit binary, set the maximum at less than 2GB to prevent crashes. // When build as 32bit binary, set the maximum at less than 2GB to prevent crashes.
@@ -425,7 +436,7 @@ void AdvancedSettings::loadAdvancedSettings()
const QString currentInterface = session->networkInterface(); const QString currentInterface = session->networkInterface();
bool interfaceExists = currentInterface.isEmpty(); bool interfaceExists = currentInterface.isEmpty();
int i = 1; int i = 1;
foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) { for (const QNetworkInterface &iface : asConst(QNetworkInterface::allInterfaces())) {
// This line fixes a Qt bug => https://bugreports.qt.io/browse/QTBUG-52633 // This line fixes a Qt bug => https://bugreports.qt.io/browse/QTBUG-52633
// Tested in Qt 5.6.0. For more info see: // Tested in Qt 5.6.0. For more info see:
// https://github.com/qbittorrent/qBittorrent/issues/5131 // https://github.com/qbittorrent/qBittorrent/issues/5131

View File

@@ -59,7 +59,7 @@ private:
template <typename T> void addRow(int row, const QString &rowText, T *widget); template <typename T> void addRow(int row, const QString &rowText, T *widget);
QLabel labelQbtLink, labelLibtorrentLink; QLabel labelQbtLink, labelLibtorrentLink;
QSpinBox spinBoxAsyncIOThreads, spinBoxCache, spinBoxSaveResumeDataInterval, spinBoxOutgoingPortsMin, spinBoxOutgoingPortsMax, spinBoxListRefresh, spinBoxMaxHalfOpen, QSpinBox spinBoxAsyncIOThreads, spinBoxCheckingMemUsage, spinBoxCache, spinBoxSaveResumeDataInterval, spinBoxOutgoingPortsMin, spinBoxOutgoingPortsMax, spinBoxListRefresh, spinBoxMaxHalfOpen,
spinBoxTrackerPort, spinBoxCacheTTL, spinBoxSendBufferWatermark, spinBoxSendBufferLowWatermark, spinBoxTrackerPort, spinBoxCacheTTL, spinBoxSendBufferWatermark, spinBoxSendBufferLowWatermark,
spinBoxSendBufferWatermarkFactor, spinBoxSavePathHistoryLength; spinBoxSendBufferWatermarkFactor, spinBoxSavePathHistoryLength;
QCheckBox checkBoxOsCache, checkBoxRecheckCompleted, checkBoxResolveCountries, checkBoxResolveHosts, checkBoxSuperSeeding, QCheckBox checkBoxOsCache, checkBoxRecheckCompleted, checkBoxResolveCountries, checkBoxResolveHosts, checkBoxSuperSeeding,

View File

@@ -107,8 +107,8 @@ void BanListOptionsDialog::on_buttonBanIP_clicked()
void BanListOptionsDialog::on_buttonDeleteIP_clicked() void BanListOptionsDialog::on_buttonDeleteIP_clicked()
{ {
QModelIndexList selection = m_ui->bannedIPList->selectionModel()->selectedIndexes(); const QModelIndexList selection = m_ui->bannedIPList->selectionModel()->selectedIndexes();
for (auto &i : selection) for (const auto &i : selection)
m_sortFilter->removeRow(i.row()); m_sortFilter->removeRow(i.row());
m_modified = true; m_modified = true;

View File

@@ -33,6 +33,7 @@
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/global.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
class CategoryModelItem class CategoryModelItem
@@ -407,7 +408,7 @@ void CategoryFilterModel::populate()
const QString &category = i.key(); const QString &category = i.key();
if (m_isSubcategoriesEnabled) { if (m_isSubcategoriesEnabled) {
CategoryModelItem *parent = m_rootItem; CategoryModelItem *parent = m_rootItem;
foreach (const QString &subcat, session->expandCategory(category)) { for (const QString &subcat : asConst(session->expandCategory(category))) {
const QString subcatName = shortName(subcat); const QString subcatName = shortName(subcat);
if (!parent->hasChild(subcatName)) { if (!parent->hasChild(subcatName)) {
new CategoryModelItem( new CategoryModelItem(
@@ -436,7 +437,7 @@ CategoryModelItem *CategoryFilterModel::findItem(const QString &fullName) const
return m_rootItem->child(fullName); return m_rootItem->child(fullName);
CategoryModelItem *item = m_rootItem; CategoryModelItem *item = m_rootItem;
foreach (const QString &subcat, BitTorrent::Session::expandCategory(fullName)) { for (const QString &subcat : asConst(BitTorrent::Session::expandCategory(fullName))) {
const QString subcatName = shortName(subcat); const QString subcatName = shortName(subcat);
if (!item->hasChild(subcatName)) return nullptr; if (!item->hasChild(subcatName)) return nullptr;
item = item->child(subcatName); item = item->child(subcatName);

View File

@@ -231,7 +231,7 @@ void CategoryFilterWidget::removeCategory()
void CategoryFilterWidget::removeUnusedCategories() void CategoryFilterWidget::removeUnusedCategories()
{ {
auto session = BitTorrent::Session::instance(); auto session = BitTorrent::Session::instance();
for (const QString &category : copyAsConst(session->categories().keys())) { for (const QString &category : asConst(session->categories().keys())) {
if (model()->data(static_cast<CategoryFilterProxyModel *>(model())->index(category), Qt::UserRole) == 0) if (model()->data(static_cast<CategoryFilterProxyModel *>(model())->index(category), Qt::UserRole) == 0)
session->removeCategory(category); session->removeCategory(category);
} }

View File

@@ -30,6 +30,7 @@
#include <algorithm> #include <algorithm>
#include "base/global.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/settingsstorage.h" #include "base/settingsstorage.h"
#include "cookiesmodel.h" #include "cookiesmodel.h"
@@ -100,6 +101,6 @@ void CookiesDialog::onButtonDeleteClicked()
} }
); );
for (const QModelIndex &idx : idxs) for (const QModelIndex &idx : asConst(idxs))
m_cookiesModel->removeRow(idx.row()); m_cookiesModel->removeRow(idx.row());
} }

View File

@@ -32,6 +32,7 @@
#include <QDateTime> #include <QDateTime>
#include <QPalette> #include <QPalette>
#include "base/global.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
#include "loglistwidget.h" #include "loglistwidget.h"
#include "ui_executionlogwidget.h" #include "ui_executionlogwidget.h"
@@ -52,9 +53,9 @@ ExecutionLogWidget::ExecutionLogWidget(QWidget *parent, const Log::MsgTypes &typ
m_ui->tabBan->layout()->addWidget(m_peerList); m_ui->tabBan->layout()->addWidget(m_peerList);
const Logger *const logger = Logger::instance(); const Logger *const logger = Logger::instance();
foreach (const Log::Msg &msg, logger->getMessages()) for (const Log::Msg &msg : asConst(logger->getMessages()))
addLogMessage(msg); addLogMessage(msg);
foreach (const Log::Peer &peer, logger->getPeers()) for (const Log::Peer &peer : asConst(logger->getPeers()))
addPeerMessage(peer); addPeerMessage(peer);
connect(logger, &Logger::newLogMessage, this, &ExecutionLogWidget::addLogMessage); connect(logger, &Logger::newLogMessage, this, &ExecutionLogWidget::addLogMessage);
connect(logger, &Logger::newLogPeer, this, &ExecutionLogWidget::addPeerMessage); connect(logger, &Logger::newLogPeer, this, &ExecutionLogWidget::addPeerMessage);

View File

@@ -350,7 +350,7 @@ void FileSystemPathComboEdit::addItem(const QString &text)
editWidget<WidgetType>()->addItem(Utils::Fs::toNativePath(text)); editWidget<WidgetType>()->addItem(Utils::Fs::toNativePath(text));
} }
void FileSystemPathComboEdit::insertItem(int index, const QString& text) void FileSystemPathComboEdit::insertItem(int index, const QString &text)
{ {
editWidget<WidgetType>()->insertItem(index, Utils::Fs::toNativePath(text)); editWidget<WidgetType>()->insertItem(index, Utils::Fs::toNativePath(text));
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Thomas Piccirello <thomas@piccirello.com> * Copyright (C) 2017 Thomas Piccirello <thomas.piccirello@gmail.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -46,7 +46,7 @@ IPSubnetWhitelistOptionsDialog::IPSubnetWhitelistOptionsDialog(QWidget *parent)
m_ui->setupUi(this); m_ui->setupUi(this);
QStringList authSubnetWhitelistStringList; QStringList authSubnetWhitelistStringList;
for (const Utils::Net::Subnet &subnet : copyAsConst(Preferences::instance()->getWebUiAuthSubnetWhitelist())) for (const Utils::Net::Subnet &subnet : asConst(Preferences::instance()->getWebUiAuthSubnetWhitelist()))
authSubnetWhitelistStringList << Utils::Net::subnetToString(subnet); authSubnetWhitelistStringList << Utils::Net::subnetToString(subnet);
m_model = new QStringListModel(authSubnetWhitelistStringList, this); m_model = new QStringListModel(authSubnetWhitelistStringList, this);
@@ -99,7 +99,7 @@ void IPSubnetWhitelistOptionsDialog::on_buttonWhitelistIPSubnet_clicked()
void IPSubnetWhitelistOptionsDialog::on_buttonDeleteIPSubnet_clicked() void IPSubnetWhitelistOptionsDialog::on_buttonDeleteIPSubnet_clicked()
{ {
for (const auto &i : copyAsConst(m_ui->whitelistedIPSubnetList->selectionModel()->selectedIndexes())) for (const auto &i : asConst(m_ui->whitelistedIPSubnetList->selectionModel()->selectedIndexes()))
m_sortFilter->removeRow(i.row()); m_sortFilter->removeRow(i.row());
m_modified = true; m_modified = true;

View File

@@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Thomas Piccirello <thomas@piccirello.com> * Copyright (C) 2017 Thomas Piccirello <thomas.piccirello@gmail.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@@ -36,6 +36,7 @@
#include <QListWidgetItem> #include <QListWidgetItem>
#include <QRegularExpression> #include <QRegularExpression>
#include "base/global.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget *parent) LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget *parent)
@@ -97,7 +98,7 @@ void LogListWidget::copySelection()
{ {
static const QRegularExpression htmlTag("<[^>]+>"); static const QRegularExpression htmlTag("<[^>]+>");
QStringList strings; QStringList strings;
foreach (QListWidgetItem* it, selectedItems()) for (QListWidgetItem* it : asConst(selectedItems()))
strings << static_cast<QLabel*>(itemWidget(it))->text().remove(htmlTag); strings << static_cast<QLabel*>(itemWidget(it))->text().remove(htmlTag);
QApplication::clipboard()->setText(strings.join('\n')); QApplication::clipboard()->setText(strings.join('\n'));

View File

@@ -284,7 +284,7 @@ MainWindow::MainWindow(QWidget *parent)
m_prioSeparatorMenu = m_ui->menuEdit->insertSeparator(m_ui->actionTopPriority); m_prioSeparatorMenu = m_ui->menuEdit->insertSeparator(m_ui->actionTopPriority);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
foreach (QAction *action, m_ui->toolBar->actions()) { for (QAction *action : asConst(m_ui->toolBar->actions())) {
if (action->isSeparator()) { if (action->isSeparator()) {
QWidget *spacer = new QWidget(this); QWidget *spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
@@ -305,7 +305,7 @@ MainWindow::MainWindow(QWidget *parent)
spacer->setMinimumWidth(8); spacer->setMinimumWidth(8);
m_ui->toolBar->addWidget(spacer); m_ui->toolBar->addWidget(spacer);
} }
#endif #endif // Q_OS_MAC
// Transfer list slots // Transfer list slots
connect(m_ui->actionStart, &QAction::triggered, m_transferListWidget, &TransferListWidget::startSelectedTorrents); connect(m_ui->actionStart, &QAction::triggered, m_transferListWidget, &TransferListWidget::startSelectedTorrents);
@@ -1110,7 +1110,7 @@ void MainWindow::toggleVisibility(const QSystemTrayIcon::ActivationReason reason
break; break;
} }
} }
#endif #endif // Q_OS_MAC
// Display About Dialog // Display About Dialog
void MainWindow::on_actionAbout_triggered() void MainWindow::on_actionAbout_triggered()
@@ -1239,7 +1239,7 @@ bool MainWindow::event(QEvent *e)
qDebug() << "Has active window:" << (qApp->activeWindow() != nullptr); qDebug() << "Has active window:" << (qApp->activeWindow() != nullptr);
// Check if there is a modal window // Check if there is a modal window
bool hasModalWindow = false; bool hasModalWindow = false;
foreach (QWidget *widget, QApplication::allWidgets()) { for (QWidget *widget : asConst(QApplication::allWidgets())) {
if (widget->isModal()) { if (widget->isModal()) {
hasModalWindow = true; hasModalWindow = true;
break; break;
@@ -1272,7 +1272,7 @@ bool MainWindow::event(QEvent *e)
default: default:
break; break;
} }
#endif #endif // Q_OS_MAC
return QMainWindow::event(e); return QMainWindow::event(e);
} }
@@ -1285,7 +1285,7 @@ void MainWindow::dropEvent(QDropEvent *event)
// remove scheme // remove scheme
QStringList files; QStringList files;
if (event->mimeData()->hasUrls()) { if (event->mimeData()->hasUrls()) {
foreach (const QUrl &url, event->mimeData()->urls()) { for (const QUrl &url : asConst(event->mimeData()->urls())) {
if (url.isEmpty()) if (url.isEmpty())
continue; continue;
@@ -1300,7 +1300,7 @@ void MainWindow::dropEvent(QDropEvent *event)
// differentiate ".torrent" files/links & magnet links from others // differentiate ".torrent" files/links & magnet links from others
QStringList torrentFiles, otherFiles; QStringList torrentFiles, otherFiles;
foreach (const QString &file, files) { for (const QString &file : asConst(files)) {
const bool isTorrentLink = (file.startsWith("magnet:", Qt::CaseInsensitive) const bool isTorrentLink = (file.startsWith("magnet:", Qt::CaseInsensitive)
|| file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive) || file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)
|| Utils::Misc::isUrl(file)); || Utils::Misc::isUrl(file));
@@ -1312,7 +1312,7 @@ void MainWindow::dropEvent(QDropEvent *event)
// Download torrents // Download torrents
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
foreach (const QString &file, torrentFiles) { for (const QString &file : asConst(torrentFiles)) {
if (useTorrentAdditionDialog) if (useTorrentAdditionDialog)
AddNewTorrentDialog::show(file, this); AddNewTorrentDialog::show(file, this);
else else
@@ -1321,7 +1321,7 @@ void MainWindow::dropEvent(QDropEvent *event)
if (!torrentFiles.isEmpty()) return; if (!torrentFiles.isEmpty()) return;
// Create torrent // Create torrent
foreach (const QString &file, otherFiles) { for (const QString &file : asConst(otherFiles)) {
createTorrentTriggered(file); createTorrentTriggered(file);
// currently only hande the first entry // currently only hande the first entry
@@ -1333,7 +1333,7 @@ void MainWindow::dropEvent(QDropEvent *event)
// Decode if we accept drag 'n drop or not // Decode if we accept drag 'n drop or not
void MainWindow::dragEnterEvent(QDragEnterEvent *event) void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{ {
foreach (const QString &mime, event->mimeData()->formats()) for (const QString &mime : asConst(event->mimeData()->formats()))
qDebug("mimeData: %s", mime.toLocal8Bit().data()); qDebug("mimeData: %s", mime.toLocal8Bit().data());
if (event->mimeData()->hasFormat("text/plain") || event->mimeData()->hasFormat("text/uri-list")) if (event->mimeData()->hasFormat("text/plain") || event->mimeData()->hasFormat("text/uri-list"))
event->acceptProposedAction(); event->acceptProposedAction();
@@ -1361,7 +1361,7 @@ void MainWindow::setupDockClickHandler()
MacUtils::overrideDockClickHandler(dockClickHandler); MacUtils::overrideDockClickHandler(dockClickHandler);
} }
#endif #endif // Q_OS_MAC
/***************************************************** /*****************************************************
* * * *
@@ -1382,7 +1382,7 @@ void MainWindow::on_actionOpen_triggered()
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
if (!pathsList.isEmpty()) { if (!pathsList.isEmpty()) {
foreach (QString file, pathsList) { for (const QString &file : pathsList) {
qDebug("Dropped file %s on download list", qUtf8Printable(file)); qDebug("Dropped file %s on download list", qUtf8Printable(file));
if (useTorrentAdditionDialog) if (useTorrentAdditionDialog)
AddNewTorrentDialog::show(file, this); AddNewTorrentDialog::show(file, this);
@@ -1635,7 +1635,7 @@ void MainWindow::showNotificationBaloon(QString title, QString msg) const
void MainWindow::downloadFromURLList(const QStringList &urlList) void MainWindow::downloadFromURLList(const QStringList &urlList)
{ {
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
foreach (QString url, urlList) { for (QString url : urlList) {
if (((url.size() == 40) && !url.contains(QRegularExpression("[^0-9A-Fa-f]"))) if (((url.size() == 40) && !url.contains(QRegularExpression("[^0-9A-Fa-f]")))
|| ((url.size() == 32) && !url.contains(QRegularExpression("[^2-7A-Za-z]")))) || ((url.size() == 32) && !url.contains(QRegularExpression("[^2-7A-Za-z]"))))
url = "magnet:?xt=urn:btih:" + url; url = "magnet:?xt=urn:btih:" + url;

View File

@@ -71,6 +71,21 @@
#include "ui_optionsdialog.h" #include "ui_optionsdialog.h"
#include "utils.h" #include "utils.h"
namespace
{
QStringList translatedWeekdayNames()
{
// return translated strings from Monday to Sunday in user selected locale
const QLocale locale {Preferences::instance()->getLocale()};
const QDate date {2018, 11, 5}; // Monday
QStringList ret;
for (int i = 0; i < 7; ++i)
ret.append(locale.toString(date.addDays(i), "dddd"));
return ret;
}
}
class WheelEventEater : public QObject class WheelEventEater : public QObject
{ {
public: public:
@@ -145,10 +160,10 @@ OptionsDialog::OptionsDialog(QWidget *parent)
m_ui->hsplitter->setCollapsible(0, false); m_ui->hsplitter->setCollapsible(0, false);
m_ui->hsplitter->setCollapsible(1, false); m_ui->hsplitter->setCollapsible(1, false);
// Get apply button in button box // Get apply button in button box
QList<QAbstractButton *> buttons = m_ui->buttonBox->buttons(); const QList<QAbstractButton *> buttons = m_ui->buttonBox->buttons();
foreach (QAbstractButton *button, buttons) { for (QAbstractButton *button : buttons) {
if (m_ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { if (m_ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) {
applyButton = button; m_applyButton = button;
break; break;
} }
} }
@@ -164,8 +179,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
initializeLanguageCombo(); initializeLanguageCombo();
// Load week days (scheduler) // Load week days (scheduler)
for (uint i = 1; i <= 7; ++i) m_ui->comboBoxScheduleDays->addItems(translatedWeekdayNames());
m_ui->comboBoxScheduleDays->addItem(QDate::longDayName(i, QDate::StandaloneFormat));
// Load options // Load options
loadOptions(); loadOptions();
@@ -390,6 +404,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, m_ui->IPSubnetWhitelistButton, &QPushButton::setEnabled); connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, m_ui->IPSubnetWhitelistButton, &QPushButton::setEnabled);
connect(m_ui->checkClickjacking, &QCheckBox::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkClickjacking, &QCheckBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkCSRFProtection, &QCheckBox::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkCSRFProtection, &QCheckBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->groupHostHeaderValidation, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkDynDNS, &QGroupBox::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkDynDNS, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->comboDNSService, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboDNSService, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
connect(m_ui->domainNameTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); connect(m_ui->domainNameTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
@@ -409,13 +424,13 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->btnEditRules, &QPushButton::clicked, this, [this]() { AutomatedRssDownloader(this).exec(); }); connect(m_ui->btnEditRules, &QPushButton::clicked, this, [this]() { AutomatedRssDownloader(this).exec(); });
// Disable apply Button // Disable apply Button
applyButton->setEnabled(false); m_applyButton->setEnabled(false);
// Tab selection mechanism // Tab selection mechanism
connect(m_ui->tabSelection, &QListWidget::currentItemChanged, this, &ThisType::changePage); connect(m_ui->tabSelection, &QListWidget::currentItemChanged, this, &ThisType::changePage);
// Load Advanced settings // Load Advanced settings
advancedSettings = new AdvancedSettings(m_ui->tabAdvancedPage); m_advancedSettings = new AdvancedSettings(m_ui->tabAdvancedPage);
m_ui->advPageLayout->addWidget(advancedSettings); m_ui->advPageLayout->addWidget(m_advancedSettings);
connect(advancedSettings, &AdvancedSettings::settingsChanged, this, &ThisType::enableApplyButton); connect(m_advancedSettings, &AdvancedSettings::settingsChanged, this, &ThisType::enableApplyButton);
m_ui->textFileLogPath->setDialogCaption(tr("Choose a save directory")); m_ui->textFileLogPath->setDialogCaption(tr("Choose a save directory"));
m_ui->textFileLogPath->setMode(FileSystemPathEdit::Mode::DirectorySave); m_ui->textFileLogPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
@@ -438,9 +453,9 @@ OptionsDialog::OptionsDialog(QWidget *parent)
// disable mouse wheel event on widgets to avoid mis-selection // disable mouse wheel event on widgets to avoid mis-selection
WheelEventEater *wheelEventEater = new WheelEventEater(this); WheelEventEater *wheelEventEater = new WheelEventEater(this);
for (QComboBox *widget : copyAsConst(findChildren<QComboBox *>())) for (QComboBox *widget : asConst(findChildren<QComboBox *>()))
widget->installEventFilter(wheelEventEater); widget->installEventFilter(wheelEventEater);
for (QSpinBox *widget : copyAsConst(findChildren<QSpinBox *>())) for (QSpinBox *widget : asConst(findChildren<QSpinBox *>()))
widget->installEventFilter(wheelEventEater); widget->installEventFilter(wheelEventEater);
loadWindowState(); loadWindowState();
@@ -454,7 +469,7 @@ void OptionsDialog::initializeLanguageCombo()
// List language files // List language files
const QDir langDir(":/lang"); const QDir langDir(":/lang");
const QStringList langFiles = langDir.entryList(QStringList("qbittorrent_*.qm"), QDir::Files); const QStringList langFiles = langDir.entryList(QStringList("qbittorrent_*.qm"), QDir::Files);
foreach (const QString langFile, langFiles) { for (const QString &langFile : langFiles) {
QString localeStr = langFile.mid(12); // remove "qbittorrent_" QString localeStr = langFile.mid(12); // remove "qbittorrent_"
localeStr.chop(3); // Remove ".qm" localeStr.chop(3); // Remove ".qm"
QString languageName; QString languageName;
@@ -478,7 +493,7 @@ OptionsDialog::~OptionsDialog()
saveWindowState(); saveWindowState();
foreach (const QString &path, addedScanDirs) for (const QString &path : asConst(m_addedScanDirs))
ScanFoldersModel::instance()->removePath(path); ScanFoldersModel::instance()->removePath(path);
ScanFoldersModel::instance()->configure(); // reloads "removed" paths ScanFoldersModel::instance()->configure(); // reloads "removed" paths
delete m_ui; delete m_ui;
@@ -526,7 +541,7 @@ void OptionsDialog::saveWindowState() const
void OptionsDialog::saveOptions() void OptionsDialog::saveOptions()
{ {
applyButton->setEnabled(false); m_applyButton->setEnabled(false);
Preferences *const pref = Preferences::instance(); Preferences *const pref = Preferences::instance();
// Load the translation // Load the translation
QString locale = getLocale(); QString locale = getLocale();
@@ -550,8 +565,8 @@ void OptionsDialog::saveOptions()
pref->setTrayIconStyle(TrayIcon::Style(m_ui->comboTrayIcon->currentIndex())); pref->setTrayIconStyle(TrayIcon::Style(m_ui->comboTrayIcon->currentIndex()));
pref->setCloseToTray(closeToTray()); pref->setCloseToTray(closeToTray());
pref->setMinimizeToTray(minimizeToTray()); pref->setMinimizeToTray(minimizeToTray());
pref->setStartMinimized(startMinimized());
#endif #endif
pref->setStartMinimized(startMinimized());
pref->setSplashScreenDisabled(isSplashScreenDisabled()); pref->setSplashScreenDisabled(isSplashScreenDisabled());
pref->setConfirmOnExit(m_ui->checkProgramExitConfirm->isChecked()); pref->setConfirmOnExit(m_ui->checkProgramExitConfirm->isChecked());
pref->setDontConfirmAutoExit(!m_ui->checkProgramAutoExitConfirm->isChecked()); pref->setDontConfirmAutoExit(!m_ui->checkProgramAutoExitConfirm->isChecked());
@@ -610,11 +625,11 @@ void OptionsDialog::saveOptions()
AddNewTorrentDialog::setTopLevel(m_ui->checkAdditionDialogFront->isChecked()); AddNewTorrentDialog::setTopLevel(m_ui->checkAdditionDialogFront->isChecked());
session->setAddTorrentPaused(addTorrentsInPause()); session->setAddTorrentPaused(addTorrentsInPause());
session->setCreateTorrentSubfolder(m_ui->checkCreateSubfolder->isChecked()); session->setCreateTorrentSubfolder(m_ui->checkCreateSubfolder->isChecked());
ScanFoldersModel::instance()->removeFromFSWatcher(removedScanDirs); ScanFoldersModel::instance()->removeFromFSWatcher(m_removedScanDirs);
ScanFoldersModel::instance()->addToFSWatcher(addedScanDirs); ScanFoldersModel::instance()->addToFSWatcher(m_addedScanDirs);
ScanFoldersModel::instance()->makePersistent(); ScanFoldersModel::instance()->makePersistent();
removedScanDirs.clear(); m_removedScanDirs.clear();
addedScanDirs.clear(); m_addedScanDirs.clear();
session->setTorrentExportDirectory(getTorrentExportDir()); session->setTorrentExportDirectory(getTorrentExportDir());
session->setFinishedTorrentExportDirectory(getFinishedTorrentExportDir()); session->setFinishedTorrentExportDirectory(getFinishedTorrentExportDir());
pref->setMailNotificationEnabled(m_ui->groupMailNotification->isChecked()); pref->setMailNotificationEnabled(m_ui->groupMailNotification->isChecked());
@@ -719,6 +734,7 @@ void OptionsDialog::saveOptions()
// Security // Security
pref->setWebUiClickjackingProtectionEnabled(m_ui->checkClickjacking->isChecked()); pref->setWebUiClickjackingProtectionEnabled(m_ui->checkClickjacking->isChecked());
pref->setWebUiCSRFProtectionEnabled(m_ui->checkCSRFProtection->isChecked()); pref->setWebUiCSRFProtectionEnabled(m_ui->checkCSRFProtection->isChecked());
pref->setWebUIHostHeaderValidationEnabled(m_ui->groupHostHeaderValidation->isChecked());
// DynDNS // DynDNS
pref->setDynDNSEnabled(m_ui->checkDynDNS->isChecked()); pref->setDynDNSEnabled(m_ui->checkDynDNS->isChecked());
pref->setDynDNSService(m_ui->comboDNSService->currentIndex()); pref->setDynDNSService(m_ui->comboDNSService->currentIndex());
@@ -732,7 +748,7 @@ void OptionsDialog::saveOptions()
// End Web UI // End Web UI
// End preferences // End preferences
// Save advanced settings // Save advanced settings
advancedSettings->saveAdvancedSettings(); m_advancedSettings->saveAdvancedSettings();
// Assume that user changed multiple settings // Assume that user changed multiple settings
// so it's best to save immediately // so it's best to save immediately
pref->apply(); pref->apply();
@@ -1082,6 +1098,7 @@ void OptionsDialog::loadOptions()
// Security // Security
m_ui->checkClickjacking->setChecked(pref->isWebUiClickjackingProtectionEnabled()); m_ui->checkClickjacking->setChecked(pref->isWebUiClickjackingProtectionEnabled());
m_ui->checkCSRFProtection->setChecked(pref->isWebUiCSRFProtectionEnabled()); m_ui->checkCSRFProtection->setChecked(pref->isWebUiCSRFProtectionEnabled());
m_ui->groupHostHeaderValidation->setChecked(pref->isWebUIHostHeaderValidationEnabled());
m_ui->checkDynDNS->setChecked(pref->isDynDNSEnabled()); m_ui->checkDynDNS->setChecked(pref->isDynDNSEnabled());
m_ui->comboDNSService->setCurrentIndex(static_cast<int>(pref->getDynDNSService())); m_ui->comboDNSService->setCurrentIndex(static_cast<int>(pref->getDynDNSService()));
@@ -1223,7 +1240,7 @@ int OptionsDialog::getMaxUploadsPerTorrent() const
void OptionsDialog::on_buttonBox_accepted() void OptionsDialog::on_buttonBox_accepted()
{ {
if (applyButton->isEnabled()) { if (m_applyButton->isEnabled()) {
if (!schedTimesOk()) { if (!schedTimesOk()) {
m_ui->tabSelection->setCurrentRow(TAB_SPEED); m_ui->tabSelection->setCurrentRow(TAB_SPEED);
return; return;
@@ -1232,7 +1249,11 @@ void OptionsDialog::on_buttonBox_accepted()
m_ui->tabSelection->setCurrentRow(TAB_WEBUI); m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return; return;
} }
applyButton->setEnabled(false); if (!isAlternativeWebUIPathValid()) {
m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return;
}
m_applyButton->setEnabled(false);
this->hide(); this->hide();
saveOptions(); saveOptions();
} }
@@ -1242,7 +1263,7 @@ void OptionsDialog::on_buttonBox_accepted()
void OptionsDialog::applySettings(QAbstractButton *button) void OptionsDialog::applySettings(QAbstractButton *button)
{ {
if (button == applyButton) { if (button == m_applyButton) {
if (!schedTimesOk()) { if (!schedTimesOk()) {
m_ui->tabSelection->setCurrentRow(TAB_SPEED); m_ui->tabSelection->setCurrentRow(TAB_SPEED);
return; return;
@@ -1251,6 +1272,10 @@ void OptionsDialog::applySettings(QAbstractButton *button)
m_ui->tabSelection->setCurrentRow(TAB_WEBUI); m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return; return;
} }
if (!isAlternativeWebUIPathValid()) {
m_ui->tabSelection->setCurrentRow(TAB_WEBUI);
return;
}
saveOptions(); saveOptions();
} }
} }
@@ -1274,7 +1299,7 @@ bool OptionsDialog::useAdditionDialog() const
void OptionsDialog::enableApplyButton() void OptionsDialog::enableApplyButton()
{ {
applyButton->setEnabled(true); m_applyButton->setEnabled(true);
} }
void OptionsDialog::toggleComboRatioLimitAct() void OptionsDialog::toggleComboRatioLimitAct()
@@ -1469,7 +1494,7 @@ void OptionsDialog::on_addScanFolderButton_clicked()
break; break;
default: default:
pref->setScanDirsLastPath(dir); pref->setScanDirsLastPath(dir);
addedScanDirs << dir; m_addedScanDirs << dir;
for (int i = 0; i < ScanFoldersModel::instance()->columnCount(); ++i) for (int i = 0; i < ScanFoldersModel::instance()->columnCount(); ++i)
m_ui->scanFoldersView->resizeColumnToContents(i); m_ui->scanFoldersView->resizeColumnToContents(i);
enableApplyButton(); enableApplyButton();
@@ -1487,9 +1512,9 @@ void OptionsDialog::on_removeScanFolderButton_clicked()
if (selected.isEmpty()) if (selected.isEmpty())
return; return;
Q_ASSERT(selected.count() == ScanFoldersModel::instance()->columnCount()); Q_ASSERT(selected.count() == ScanFoldersModel::instance()->columnCount());
foreach (const QModelIndex &index, selected) { for (const QModelIndex &index : selected) {
if (index.column() == ScanFoldersModel::WATCH) if (index.column() == ScanFoldersModel::WATCH)
removedScanDirs << index.data().toString(); m_removedScanDirs << index.data().toString();
} }
ScanFoldersModel::instance()->removePath(selected.first().row(), false); ScanFoldersModel::instance()->removePath(selected.first().row(), false);
} }
@@ -1733,6 +1758,15 @@ bool OptionsDialog::webUIAuthenticationOk()
return true; return true;
} }
bool OptionsDialog::isAlternativeWebUIPathValid()
{
if (m_ui->groupAltWebUI->isChecked() && m_ui->textWebUIRootFolder->selectedPath().trimmed().isEmpty()) {
QMessageBox::warning(this, tr("Location Error"), tr("The alternative Web UI files location cannot be blank."));
return false;
}
return true;
}
void OptionsDialog::on_banListButton_clicked() void OptionsDialog::on_banListButton_clicked()
{ {
// call dialog window // call dialog window

View File

@@ -172,15 +172,15 @@ private:
bool setSslCertificate(const QByteArray &cert); bool setSslCertificate(const QByteArray &cert);
bool schedTimesOk(); bool schedTimesOk();
bool webUIAuthenticationOk(); bool webUIAuthenticationOk();
bool isAlternativeWebUIPathValid();
QByteArray m_sslCert, m_sslKey; QByteArray m_sslCert, m_sslKey;
Ui::OptionsDialog *m_ui; Ui::OptionsDialog *m_ui;
QButtonGroup choiceLanguage; QAbstractButton *m_applyButton;
QAbstractButton *applyButton; AdvancedSettings *m_advancedSettings;
AdvancedSettings *advancedSettings; QList<QString> m_addedScanDirs;
QList<QString> addedScanDirs; QList<QString> m_removedScanDirs;
QList<QString> removedScanDirs;
}; };
#endif // OPTIONSDIALOG_H #endif // OPTIONSDIALOG_H

View File

@@ -941,7 +941,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="labelCategoryChanged"> <widget class="QLabel" name="labelCategoryChanged">
<property name="text"> <property name="text">
<string>When Category changed:</string> <string>When Category Save Path changed:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -2944,28 +2944,6 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="labelServerDomains">
<property name="text">
<string>Server domains:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textServerDomains">
<property name="toolTip">
<string>Whitelist for filtering HTTP Host header values.
In order to defend against DNS rebinding attack,
you should put in domain names used by WebUI server.
Use ';' to split multiple entries. Can use wildcard '*'.</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QCheckBox" name="checkWebUIUPnP"> <widget class="QCheckBox" name="checkWebUIUPnP">
<property name="text"> <property name="text">
@@ -3177,17 +3155,60 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="checkClickjacking"> <widget class="QGroupBox" name="groupBox_3">
<property name="text"> <property name="title">
<string>Enable clickjacking protection</string> <string>Security</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkCSRFProtection">
<property name="text">
<string>Enable Cross-Site Request Forgery (CSRF) protection</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_33">
<item>
<widget class="QCheckBox" name="checkClickjacking">
<property name="text">
<string>Enable clickjacking protection</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkCSRFProtection">
<property name="text">
<string>Enable Cross-Site Request Forgery (CSRF) protection</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupHostHeaderValidation">
<property name="title">
<string>Enable Host header validation</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_32">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="labelServerDomains">
<property name="text">
<string>Server domains:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textServerDomains">
<property name="toolTip">
<string>Whitelist for filtering HTTP Host header values.
In order to defend against DNS rebinding attack,
you should put in domain names used by WebUI server.
Use ';' to split multiple entries. Can use wildcard '*'.</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>

View File

@@ -141,7 +141,7 @@ bool ProgramUpdater::isVersionMoreRecent(const QString &remoteVersion) const
qDebug() << Q_FUNC_INFO << "local version:" << localVersion << "/" << QBT_VERSION; qDebug() << Q_FUNC_INFO << "local version:" << localVersion << "/" << QBT_VERSION;
QStringList remoteParts = remoteVersion.split('.'); QStringList remoteParts = remoteVersion.split('.');
QStringList localParts = localVersion.split('.'); QStringList localParts = localVersion.split('.');
for (int i = 0; i<qMin(remoteParts.size(), localParts.size()); ++i) { for (int i = 0; i < qMin(remoteParts.size(), localParts.size()); ++i) {
if (remoteParts[i].toInt() > localParts[i].toInt()) if (remoteParts[i].toInt() > localParts[i].toInt())
return true; return true;
if (remoteParts[i].toInt() < localParts[i].toInt()) if (remoteParts[i].toInt() < localParts[i].toInt())

View File

@@ -103,7 +103,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
hideColumn(PeerListDelegate::COUNTRY); hideColumn(PeerListDelegate::COUNTRY);
// Ensure that at least one column is visible at all times // Ensure that at least one column is visible at all times
bool atLeastOne = false; bool atLeastOne = false;
for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) {
if (!isColumnHidden(i)) { if (!isColumnHidden(i)) {
atLeastOne = true; atLeastOne = true;
break; break;
@@ -114,7 +114,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
// To also mitigate the above issue, we have to resize each column when // To also mitigate the above issue, we have to resize each column when
// its size is 0, because explicitly 'showing' the column isn't enough // its size is 0, because explicitly 'showing' the column isn't enough
// in the above scenario. // in the above scenario.
for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i)
if ((columnWidth(i) <= 0) && !isColumnHidden(i)) if ((columnWidth(i) <= 0) && !isColumnHidden(i))
resizeColumnToContents(i); resizeColumnToContents(i);
// Context menu // Context menu
@@ -169,7 +169,7 @@ void PeerListWidget::displayToggleColumnsMenu(const QPoint &)
actions.append(myAct); actions.append(myAct);
} }
int visibleCols = 0; int visibleCols = 0;
for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) {
if (!isColumnHidden(i)) if (!isColumnHidden(i))
++visibleCols; ++visibleCols;
@@ -248,9 +248,9 @@ void PeerListWidget::showPeerListMenu(const QPoint &)
if (!act) return; if (!act) return;
if (act == addPeerAct) { if (act == addPeerAct) {
QList<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this); const QList<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this);
int peerCount = 0; int peerCount = 0;
foreach (const BitTorrent::PeerAddress &addr, peersList) { for (const BitTorrent::PeerAddress &addr : peersList) {
if (torrent->connectPeer(addr)) { if (torrent->connectPeer(addr)) {
qDebug("Adding peer %s...", qUtf8Printable(addr.ip.toString())); qDebug("Adding peer %s...", qUtf8Printable(addr.ip.toString()));
Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString())); Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString()));
@@ -284,8 +284,8 @@ void PeerListWidget::banSelectedPeers()
QString(), 0, 1); QString(), 0, 1);
if (ret) return; if (ret) return;
QModelIndexList selectedIndexes = selectionModel()->selectedRows(); const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
foreach (const QModelIndex &index, selectedIndexes) { for (const QModelIndex &index : selectedIndexes) {
int row = m_proxyModel->mapToSource(index).row(); int row = m_proxyModel->mapToSource(index).row();
QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString();
qDebug("Banning peer %s...", ip.toLocal8Bit().data()); qDebug("Banning peer %s...", ip.toLocal8Bit().data());
@@ -298,9 +298,9 @@ void PeerListWidget::banSelectedPeers()
void PeerListWidget::copySelectedPeers() void PeerListWidget::copySelectedPeers()
{ {
QModelIndexList selectedIndexes = selectionModel()->selectedRows(); const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
QStringList selectedPeers; QStringList selectedPeers;
foreach (const QModelIndex &index, selectedIndexes) { for (const QModelIndex &index : selectedIndexes) {
int row = m_proxyModel->mapToSource(index).row(); int row = m_proxyModel->mapToSource(index).row();
QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString();
QString myport = m_listModel->data(m_listModel->index(row, PeerListDelegate::PORT)).toString(); QString myport = m_listModel->data(m_listModel->index(row, PeerListDelegate::PORT)).toString();
@@ -321,7 +321,7 @@ void PeerListWidget::clear()
int nbrows = m_listModel->rowCount(); int nbrows = m_listModel->rowCount();
if (nbrows > 0) { if (nbrows > 0) {
qDebug("Cleared %d peers", nbrows); qDebug("Cleared %d peers", nbrows);
m_listModel->removeRows(0, nbrows); m_listModel->removeRows(0, nbrows);
} }
} }
@@ -339,10 +339,10 @@ void PeerListWidget::loadPeers(BitTorrent::TorrentHandle *const torrent, bool fo
{ {
if (!torrent) return; if (!torrent) return;
QList<BitTorrent::PeerInfo> peers = torrent->peers(); const QList<BitTorrent::PeerInfo> peers = torrent->peers();
QSet<QString> oldPeersSet = m_peerItems.keys().toSet(); QSet<QString> oldPeersSet = m_peerItems.keys().toSet();
foreach (const BitTorrent::PeerInfo &peer, peers) { for (const BitTorrent::PeerInfo &peer : peers) {
BitTorrent::PeerAddress addr = peer.address(); BitTorrent::PeerAddress addr = peer.address();
if (addr.ip.isNull()) continue; if (addr.ip.isNull()) continue;

View File

@@ -31,6 +31,7 @@
#include <QHostAddress> #include <QHostAddress>
#include <QMessageBox> #include <QMessageBox>
#include "base/global.h"
#include "ui_peersadditiondialog.h" #include "ui_peersadditiondialog.h"
PeersAdditionDialog::PeersAdditionDialog(QWidget *parent) PeersAdditionDialog::PeersAdditionDialog(QWidget *parent)
@@ -61,7 +62,7 @@ void PeersAdditionDialog::validateInput()
QMessageBox::Ok); QMessageBox::Ok);
return; return;
} }
foreach (const QString &peer, m_ui->textEditPeers->toPlainText().trimmed().split('\n')) { for (const QString &peer : asConst(m_ui->textEditPeers->toPlainText().trimmed().split('\n'))) {
BitTorrent::PeerAddress addr = parsePeer(peer); BitTorrent::PeerAddress addr = parsePeer(peer);
if (!addr.ip.isNull()) { if (!addr.ip.isNull()) {
m_peersList.append(addr); m_peersList.append(addr);

View File

@@ -259,7 +259,7 @@ void PiecesBar::showToolTip(const QHelpEvent *e)
stream << "<html><body>"; stream << "<html><body>";
PieceIndexToImagePos transform {m_torrent->info(), m_image}; PieceIndexToImagePos transform {m_torrent->info(), m_image};
int pieceIndex = transform.pieceIndex(imagePos); int pieceIndex = transform.pieceIndex(imagePos);
QVector<int> files {m_torrent->info().fileIndicesForPiece(pieceIndex)}; const QVector<int> files {m_torrent->info().fileIndicesForPiece(pieceIndex)};
QString tooltipTitle; QString tooltipTitle;
if (files.count() > 1) { if (files.count() > 1) {
@@ -275,7 +275,7 @@ void PiecesBar::showToolTip(const QHelpEvent *e)
DetailedTooltipRenderer renderer(stream, tooltipTitle); DetailedTooltipRenderer renderer(stream, tooltipTitle);
const bool isFileNameCorrectionNeeded = this->isFileNameCorrectionNeeded(); const bool isFileNameCorrectionNeeded = this->isFileNameCorrectionNeeded();
for (int f: files) { for (int f : files) {
QString filePath {m_torrent->info().filePath(f)}; QString filePath {m_torrent->info().filePath(f)};
if (isFileNameCorrectionNeeded) if (isFileNameCorrectionNeeded)
filePath.replace(QLatin1String("/.unwanted"), QString()); filePath.replace(QLatin1String("/.unwanted"), QString());

View File

@@ -38,6 +38,7 @@
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/unicodestrings.h" #include "base/unicodestrings.h"
@@ -511,7 +512,7 @@ void PropertiesWidget::loadUrlSeeds()
qDebug("Loading URL seeds"); qDebug("Loading URL seeds");
const QList<QUrl> hcSeeds = m_torrent->urlSeeds(); const QList<QUrl> hcSeeds = m_torrent->urlSeeds();
// Add url seeds // Add url seeds
foreach (const QUrl &hcSeed, hcSeeds) { for (const QUrl &hcSeed : hcSeeds) {
qDebug("Loading URL seed: %s", qUtf8Printable(hcSeed.toString())); qDebug("Loading URL seed: %s", qUtf8Printable(hcSeed.toString()));
new QListWidgetItem(hcSeed.toString(), m_ui->listWebSeeds); new QListWidgetItem(hcSeed.toString(), m_ui->listWebSeeds);
} }
@@ -582,7 +583,7 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
{ {
if (!m_torrent) return; if (!m_torrent) return;
QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0); const QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0);
if (selectedRows.empty()) return; if (selectedRows.empty()) return;
QMenu myFilesLlistMenu; QMenu myFilesLlistMenu;
@@ -621,18 +622,18 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
renameSelectedFile(); renameSelectedFile();
} }
else { else {
int prio = prio::NORMAL; BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
if (act == m_ui->actionHigh) if (act == m_ui->actionHigh)
prio = prio::HIGH; prio = BitTorrent::FilePriority::High;
else if (act == m_ui->actionMaximum) else if (act == m_ui->actionMaximum)
prio = prio::MAXIMUM; prio = BitTorrent::FilePriority::Maximum;
else if (act == m_ui->actionNotDownloaded) else if (act == m_ui->actionNotDownloaded)
prio = prio::IGNORED; prio = BitTorrent::FilePriority::Ignored;
qDebug("Setting files priority"); qDebug("Setting files priority");
foreach (QModelIndex index, selectedRows) { for (const QModelIndex &index : selectedRows) {
qDebug("Setting priority(%d) for file at row %d", prio, index.row()); qDebug("Setting priority(%d) for file at row %d", static_cast<int>(prio), index.row());
m_propListModel->setData(m_propListModel->index(index.row(), PRIORITY, index.parent()), prio); m_propListModel->setData(m_propListModel->index(index.row(), PRIORITY, index.parent()), static_cast<int>(prio));
} }
// Save changes // Save changes
filteredFilesChanged(); filteredFilesChanged();
@@ -847,7 +848,7 @@ void PropertiesWidget::deleteSelectedUrlSeeds()
if (selectedItems.isEmpty()) return; if (selectedItems.isEmpty()) return;
QList<QUrl> urlSeeds; QList<QUrl> urlSeeds;
foreach (const QListWidgetItem *item, selectedItems) for (const QListWidgetItem *item : selectedItems)
urlSeeds << item->text(); urlSeeds << item->text();
m_torrent->removeUrlSeeds(urlSeeds); m_torrent->removeUrlSeeds(urlSeeds);
@@ -861,7 +862,7 @@ void PropertiesWidget::copySelectedWebSeedsToClipboard() const
if (selectedItems.isEmpty()) return; if (selectedItems.isEmpty()) return;
QStringList urlsToCopy; QStringList urlsToCopy;
foreach (QListWidgetItem *item, selectedItems) for (const QListWidgetItem *item : selectedItems)
urlsToCopy << item->text(); urlsToCopy << item->text();
QApplication::clipboard()->setText(urlsToCopy.join('\n')); QApplication::clipboard()->setText(urlsToCopy.join('\n'));

View File

@@ -40,6 +40,7 @@
#include <QProxyStyle> #include <QProxyStyle>
#endif #endif
#include "base/bittorrent/filepriority.h"
#include "base/unicodestrings.h" #include "base/unicodestrings.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/string.h" #include "base/utils/string.h"
@@ -92,7 +93,7 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
newopt.maximum = 100; newopt.maximum = 100;
newopt.minimum = 0; newopt.minimum = 0;
newopt.textVisible = true; newopt.textVisible = true;
if (index.sibling(index.row(), PRIORITY).data().toInt() == prio::IGNORED) { if (index.sibling(index.row(), PRIORITY).data().toInt() == static_cast<int>(BitTorrent::FilePriority::Ignored)) {
newopt.state &= ~QStyle::State_Enabled; newopt.state &= ~QStyle::State_Enabled;
newopt.palette = progressBarDisabledPalette(); newopt.palette = progressBarDisabledPalette();
} }
@@ -110,17 +111,17 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
break; break;
case PRIORITY: { case PRIORITY: {
QString text = ""; QString text = "";
switch (index.data().toInt()) { switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) {
case prio::MIXED: case BitTorrent::FilePriority::Mixed:
text = tr("Mixed", "Mixed (priorities"); text = tr("Mixed", "Mixed (priorities");
break; break;
case prio::IGNORED: case BitTorrent::FilePriority::Ignored:
text = tr("Not downloaded"); text = tr("Not downloaded");
break; break;
case prio::HIGH: case BitTorrent::FilePriority::High:
text = tr("High", "High (priority)"); text = tr("High", "High (priority)");
break; break;
case prio::MAXIMUM: case BitTorrent::FilePriority::Maximum:
text = tr("Maximum", "Maximum (priority)"); text = tr("Maximum", "Maximum (priority)");
break; break;
default: default:
@@ -154,14 +155,14 @@ void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
{ {
QComboBox *combobox = static_cast<QComboBox *>(editor); QComboBox *combobox = static_cast<QComboBox *>(editor);
// Set combobox index // Set combobox index
switch (index.data().toInt()) { switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) {
case prio::IGNORED: case BitTorrent::FilePriority::Ignored:
combobox->setCurrentIndex(0); combobox->setCurrentIndex(0);
break; break;
case prio::HIGH: case BitTorrent::FilePriority::High:
combobox->setCurrentIndex(2); combobox->setCurrentIndex(2);
break; break;
case prio::MAXIMUM: case BitTorrent::FilePriority::Maximum:
combobox->setCurrentIndex(3); combobox->setCurrentIndex(3);
break; break;
default: default:
@@ -180,7 +181,7 @@ QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewI
return nullptr; return nullptr;
} }
if (index.data().toInt() == prio::MIXED) if (index.data().toInt() == static_cast<int>(BitTorrent::FilePriority::Mixed))
return nullptr; return nullptr;
QComboBox *editor = new QComboBox(parent); QComboBox *editor = new QComboBox(parent);
@@ -198,20 +199,20 @@ void PropListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
int value = combobox->currentIndex(); int value = combobox->currentIndex();
qDebug("PropListDelegate: setModelData(%d)", value); qDebug("PropListDelegate: setModelData(%d)", value);
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; // NORMAL
switch (value) { switch (value) {
case 0: case 0:
model->setData(index, prio::IGNORED); // IGNORED prio = BitTorrent::FilePriority::Ignored; // IGNORED
break; break;
case 2: case 2:
model->setData(index, prio::HIGH); // HIGH prio = BitTorrent::FilePriority::High; // HIGH
break; break;
case 3: case 3:
model->setData(index, prio::MAXIMUM); // MAX prio = BitTorrent::FilePriority::Maximum; // MAX
break; break;
default:
model->setData(index, prio::NORMAL); // NORMAL
} }
model->setData(index, static_cast<int>(prio));
emit filteredFilesChanged(); emit filteredFilesChanged();
} }

View File

@@ -33,6 +33,7 @@
#include <QPushButton> #include <QPushButton>
#include <QSpacerItem> #include <QSpacerItem>
#include "base/global.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
PropTabBar::PropTabBar(QWidget *parent) PropTabBar::PropTabBar(QWidget *parent)
@@ -102,7 +103,7 @@ PropTabBar::PropTabBar(QWidget *parent)
connect(m_btnGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked) connect(m_btnGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked)
, this, &PropTabBar::setCurrentIndex); , this, &PropTabBar::setCurrentIndex);
// Disable buttons focus // Disable buttons focus
foreach (QAbstractButton *btn, m_btnGroup->buttons()) for (QAbstractButton *btn : asConst(m_btnGroup->buttons()))
btn->setFocusPolicy(Qt::NoFocus); btn->setFocusPolicy(Qt::NoFocus);
} }

View File

@@ -274,7 +274,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
rect.adjust(0, fontMetrics.height(), 0, 0); // Add top padding for top speed text rect.adjust(0, fontMetrics.height(), 0, 0); // Add top padding for top speed text
// draw Y axis speed labels // draw Y axis speed labels
QVector<QString> speedLabels = { const QVector<QString> speedLabels = {
formatLabel(niceScale.arg, niceScale.unit), formatLabel(niceScale.arg, niceScale.unit),
formatLabel((0.75 * niceScale.arg), niceScale.unit), formatLabel((0.75 * niceScale.arg), niceScale.unit),
formatLabel((0.50 * niceScale.arg), niceScale.unit), formatLabel((0.50 * niceScale.arg), niceScale.unit),
@@ -348,7 +348,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
double legendHeight = 0; double legendHeight = 0;
int legendWidth = 0; int legendWidth = 0;
for (const auto &property : qAsConst(m_properties)) { for (const auto &property : asConst(m_properties)) {
if (!property.enable) if (!property.enable)
continue; continue;
@@ -363,7 +363,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
painter.fillRect(legendBackgroundRect, legendBackgroundColor); painter.fillRect(legendBackgroundRect, legendBackgroundColor);
i = 0; i = 0;
for (const auto &property : qAsConst(m_properties)) { for (const auto &property : asConst(m_properties)) {
if (!property.enable) if (!property.enable)
continue; continue;

View File

@@ -45,6 +45,7 @@
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/trackerentry.h" #include "base/bittorrent/trackerentry.h"
#include "base/global.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "autoexpandabledialog.h" #include "autoexpandabledialog.h"
@@ -96,23 +97,23 @@ TrackerListWidget::TrackerListWidget(PropertiesWidget *properties)
insertTopLevelItem(2, m_LSDItem); insertTopLevelItem(2, m_LSDItem);
setRowColor(2, QColor("grey")); setRowColor(2, QColor("grey"));
// Set static items alignment // Set static items alignment
m_DHTItem->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter));
m_PEXItem->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter));
m_LSDItem->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter));
m_DHTItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
m_PEXItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
m_LSDItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
m_DHTItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); m_DHTItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
m_PEXItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); m_PEXItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
m_LSDItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); m_LSDItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
m_DHTItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
m_PEXItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
m_LSDItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
m_DHTItem->setTextAlignment(COL_LEECHES, (Qt::AlignRight | Qt::AlignVCenter));
m_PEXItem->setTextAlignment(COL_LEECHES, (Qt::AlignRight | Qt::AlignVCenter));
m_LSDItem->setTextAlignment(COL_LEECHES, (Qt::AlignRight | Qt::AlignVCenter));
m_DHTItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); m_DHTItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter));
m_PEXItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); m_PEXItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter));
m_LSDItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); m_LSDItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter));
// Set header alignment // Set header alignment
headerItem()->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter)); headerItem()->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter));
headerItem()->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter));
headerItem()->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
headerItem()->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); headerItem()->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
headerItem()->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
headerItem()->setTextAlignment(COL_LEECHES, (Qt::AlignRight | Qt::AlignVCenter));
headerItem()->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); headerItem()->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter));
// Set hotkeys // Set hotkeys
m_editHotkey = new QShortcut(Qt::Key_F2, this, nullptr, nullptr, Qt::WidgetShortcut); m_editHotkey = new QShortcut(Qt::Key_F2, this, nullptr, nullptr, Qt::WidgetShortcut);
@@ -140,7 +141,7 @@ QList<QTreeWidgetItem*> TrackerListWidget::getSelectedTrackerItems() const
{ {
const QList<QTreeWidgetItem *> selectedTrackerItems = selectedItems(); const QList<QTreeWidgetItem *> selectedTrackerItems = selectedItems();
QList<QTreeWidgetItem *> selectedTrackers; QList<QTreeWidgetItem *> selectedTrackers;
foreach (QTreeWidgetItem *item, selectedTrackerItems) { for (QTreeWidgetItem *item : selectedTrackerItems) {
if (indexOfTopLevelItem(item) >= NB_STICKY_ITEM) // Ignore STICKY ITEMS if (indexOfTopLevelItem(item) >= NB_STICKY_ITEM) // Ignore STICKY ITEMS
selectedTrackers << item; selectedTrackers << item;
} }
@@ -163,11 +164,11 @@ void TrackerListWidget::moveSelectionUp()
clear(); clear();
return; return;
} }
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems(); const QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
if (selectedTrackerItems.isEmpty()) return; if (selectedTrackerItems.isEmpty()) return;
bool change = false; bool change = false;
foreach (QTreeWidgetItem *item, selectedTrackerItems) { for (QTreeWidgetItem *item : selectedTrackerItems) {
int index = indexOfTopLevelItem(item); int index = indexOfTopLevelItem(item);
if (index > NB_STICKY_ITEM) { if (index > NB_STICKY_ITEM) {
insertTopLevelItem(index - 1, takeTopLevelItem(index)); insertTopLevelItem(index - 1, takeTopLevelItem(index));
@@ -178,7 +179,7 @@ void TrackerListWidget::moveSelectionUp()
// Restore selection // Restore selection
QItemSelectionModel *selection = selectionModel(); QItemSelectionModel *selection = selectionModel();
foreach (QTreeWidgetItem *item, selectedTrackerItems) for (QTreeWidgetItem *item : selectedTrackerItems)
selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select)); selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select));
setSelectionModel(selection); setSelectionModel(selection);
@@ -204,7 +205,7 @@ void TrackerListWidget::moveSelectionDown()
clear(); clear();
return; return;
} }
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems(); const QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
if (selectedTrackerItems.isEmpty()) return; if (selectedTrackerItems.isEmpty()) return;
bool change = false; bool change = false;
@@ -219,7 +220,7 @@ void TrackerListWidget::moveSelectionDown()
// Restore selection // Restore selection
QItemSelectionModel *selection = selectionModel(); QItemSelectionModel *selection = selectionModel();
foreach (QTreeWidgetItem *item, selectedTrackerItems) for (QTreeWidgetItem *item : selectedTrackerItems)
selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select)); selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select));
setSelectionModel(selection); setSelectionModel(selection);
@@ -244,15 +245,15 @@ void TrackerListWidget::clear()
m_trackerItems.clear(); m_trackerItems.clear();
m_DHTItem->setText(COL_STATUS, ""); m_DHTItem->setText(COL_STATUS, "");
m_DHTItem->setText(COL_SEEDS, ""); m_DHTItem->setText(COL_SEEDS, "");
m_DHTItem->setText(COL_PEERS, ""); m_DHTItem->setText(COL_LEECHES, "");
m_DHTItem->setText(COL_MSG, ""); m_DHTItem->setText(COL_MSG, "");
m_PEXItem->setText(COL_STATUS, ""); m_PEXItem->setText(COL_STATUS, "");
m_PEXItem->setText(COL_SEEDS, ""); m_PEXItem->setText(COL_SEEDS, "");
m_PEXItem->setText(COL_PEERS, ""); m_PEXItem->setText(COL_LEECHES, "");
m_PEXItem->setText(COL_MSG, ""); m_PEXItem->setText(COL_MSG, "");
m_LSDItem->setText(COL_STATUS, ""); m_LSDItem->setText(COL_STATUS, "");
m_LSDItem->setText(COL_SEEDS, ""); m_LSDItem->setText(COL_SEEDS, "");
m_LSDItem->setText(COL_PEERS, ""); m_LSDItem->setText(COL_LEECHES, "");
m_LSDItem->setText(COL_MSG, ""); m_LSDItem->setText(COL_MSG, "");
} }
@@ -289,7 +290,7 @@ void TrackerListWidget::loadStickyItems(BitTorrent::TorrentHandle *const torrent
// XXX: libtorrent should provide this info... // XXX: libtorrent should provide this info...
// Count peers from DHT, PeX, LSD // Count peers from DHT, PeX, LSD
uint seedsDHT = 0, seedsPeX = 0, seedsLSD = 0, peersDHT = 0, peersPeX = 0, peersLSD = 0; uint seedsDHT = 0, seedsPeX = 0, seedsLSD = 0, peersDHT = 0, peersPeX = 0, peersLSD = 0;
foreach (const BitTorrent::PeerInfo &peer, torrent->peers()) { for (const BitTorrent::PeerInfo &peer : asConst(torrent->peers())) {
if (peer.isConnecting()) continue; if (peer.isConnecting()) continue;
if (peer.fromDHT()) { if (peer.fromDHT()) {
@@ -313,11 +314,11 @@ void TrackerListWidget::loadStickyItems(BitTorrent::TorrentHandle *const torrent
} }
m_DHTItem->setText(COL_SEEDS, QString::number(seedsDHT)); m_DHTItem->setText(COL_SEEDS, QString::number(seedsDHT));
m_DHTItem->setText(COL_PEERS, QString::number(peersDHT)); m_DHTItem->setText(COL_LEECHES, QString::number(peersDHT));
m_PEXItem->setText(COL_SEEDS, QString::number(seedsPeX)); m_PEXItem->setText(COL_SEEDS, QString::number(seedsPeX));
m_PEXItem->setText(COL_PEERS, QString::number(peersPeX)); m_PEXItem->setText(COL_LEECHES, QString::number(peersPeX));
m_LSDItem->setText(COL_SEEDS, QString::number(seedsLSD)); m_LSDItem->setText(COL_SEEDS, QString::number(seedsLSD));
m_LSDItem->setText(COL_PEERS, QString::number(peersLSD)); m_LSDItem->setText(COL_LEECHES, QString::number(peersLSD));
} }
void TrackerListWidget::loadTrackers() void TrackerListWidget::loadTrackers()
@@ -331,7 +332,7 @@ void TrackerListWidget::loadTrackers()
// Load actual trackers information // Load actual trackers information
QHash<QString, BitTorrent::TrackerInfo> trackerData = torrent->trackerInfos(); QHash<QString, BitTorrent::TrackerInfo> trackerData = torrent->trackerInfos();
QStringList oldTrackerURLs = m_trackerItems.keys(); QStringList oldTrackerURLs = m_trackerItems.keys();
foreach (const BitTorrent::TrackerEntry &entry, torrent->trackers()) { for (const BitTorrent::TrackerEntry &entry : asConst(torrent->trackers())) {
QString trackerURL = entry.url(); QString trackerURL = entry.url();
QTreeWidgetItem *item = m_trackerItems.value(trackerURL, nullptr); QTreeWidgetItem *item = m_trackerItems.value(trackerURL, nullptr);
if (!item) { if (!item) {
@@ -365,25 +366,19 @@ void TrackerListWidget::loadTrackers()
break; break;
} }
item->setText(COL_RECEIVED, QString::number(data.numPeers)); item->setText(COL_PEERS, QString::number(data.numPeers));
#if LIBTORRENT_VERSION_NUM >= 10000
item->setText(COL_SEEDS, (entry.nativeEntry().scrape_complete > -1) ? QString::number(entry.nativeEntry().scrape_complete) : tr("N/A")); item->setText(COL_SEEDS, (entry.nativeEntry().scrape_complete > -1) ? QString::number(entry.nativeEntry().scrape_complete) : tr("N/A"));
item->setText(COL_PEERS, (entry.nativeEntry().scrape_incomplete > -1) ? QString::number(entry.nativeEntry().scrape_incomplete) : tr("N/A")); item->setText(COL_LEECHES, (entry.nativeEntry().scrape_incomplete > -1) ? QString::number(entry.nativeEntry().scrape_incomplete) : tr("N/A"));
item->setText(COL_DOWNLOADED, (entry.nativeEntry().scrape_downloaded > -1) ? QString::number(entry.nativeEntry().scrape_downloaded) : tr("N/A")); item->setText(COL_DOWNLOADED, (entry.nativeEntry().scrape_downloaded > -1) ? QString::number(entry.nativeEntry().scrape_downloaded) : tr("N/A"));
#else
item->setText(COL_SEEDS, tr("N/A"));
item->setText(COL_PEERS, tr("N/A"));
item->setText(COL_DOWNLOADED, tr("N/A"));
#endif
item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter)); item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_LEECHES, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); item->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter));
} }
// Remove old trackers // Remove old trackers
foreach (const QString &tracker, oldTrackerURLs) for (const QString &tracker : asConst(oldTrackerURLs))
delete m_trackerItems.take(tracker); delete m_trackerItems.take(tracker);
} }
@@ -394,7 +389,7 @@ void TrackerListWidget::askForTrackers()
if (!torrent) return; if (!torrent) return;
QList<BitTorrent::TrackerEntry> trackers; QList<BitTorrent::TrackerEntry> trackers;
foreach (const QString &tracker, TrackersAdditionDialog::askForTrackers(this, torrent)) for (const QString &tracker : asConst(TrackersAdditionDialog::askForTrackers(this, torrent)))
trackers << tracker; trackers << tracker;
torrent->addTrackers(trackers); torrent->addTrackers(trackers);
@@ -402,11 +397,11 @@ void TrackerListWidget::askForTrackers()
void TrackerListWidget::copyTrackerUrl() void TrackerListWidget::copyTrackerUrl()
{ {
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems(); const QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
if (selectedTrackerItems.isEmpty()) return; if (selectedTrackerItems.isEmpty()) return;
QStringList urlsToCopy; QStringList urlsToCopy;
foreach (QTreeWidgetItem *item, selectedTrackerItems) { for (const QTreeWidgetItem *item : selectedTrackerItems) {
QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString(); QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
qDebug() << QString("Copy: ") + trackerURL; qDebug() << QString("Copy: ") + trackerURL;
urlsToCopy << trackerURL; urlsToCopy << trackerURL;
@@ -423,11 +418,11 @@ void TrackerListWidget::deleteSelectedTrackers()
return; return;
} }
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems(); const QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
if (selectedTrackerItems.isEmpty()) return; if (selectedTrackerItems.isEmpty()) return;
QStringList urlsToRemove; QStringList urlsToRemove;
foreach (QTreeWidgetItem *item, selectedTrackerItems) { for (const QTreeWidgetItem *item : selectedTrackerItems) {
QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString(); QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
urlsToRemove << trackerURL; urlsToRemove << trackerURL;
m_trackerItems.remove(trackerURL); m_trackerItems.remove(trackerURL);
@@ -436,8 +431,8 @@ void TrackerListWidget::deleteSelectedTrackers()
// Iterate over the trackers and remove the selected ones // Iterate over the trackers and remove the selected ones
QList<BitTorrent::TrackerEntry> remainingTrackers; QList<BitTorrent::TrackerEntry> remainingTrackers;
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers(); const QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
foreach (const BitTorrent::TrackerEntry &entry, trackers) { for (const BitTorrent::TrackerEntry &entry : trackers) {
if (!urlsToRemove.contains(entry.url())) if (!urlsToRemove.contains(entry.url()))
remainingTrackers.push_back(entry); remainingTrackers.push_back(entry);
} }
@@ -493,7 +488,7 @@ void TrackerListWidget::editSelectedTracker()
void TrackerListWidget::reannounceSelected() void TrackerListWidget::reannounceSelected()
{ {
QList<QTreeWidgetItem *> selItems = selectedItems(); const QList<QTreeWidgetItem *> selItems = selectedItems();
if (selItems.isEmpty()) return; if (selItems.isEmpty()) return;
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent();
@@ -501,7 +496,7 @@ void TrackerListWidget::reannounceSelected()
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers(); QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
foreach (QTreeWidgetItem* item, selItems) { for (const QTreeWidgetItem *item : selItems) {
// DHT case // DHT case
if (item == m_DHTItem) { if (item == m_DHTItem) {
torrent->forceDHTAnnounce(); torrent->forceDHTAnnounce();
@@ -533,9 +528,9 @@ void TrackerListWidget::showTrackerListMenu(QPoint)
QAction *delAct = nullptr; QAction *delAct = nullptr;
QAction *editAct = nullptr; QAction *editAct = nullptr;
if (!getSelectedTrackerItems().isEmpty()) { if (!getSelectedTrackerItems().isEmpty()) {
editAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit tracker URL..."));
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker")); delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker"));
copyAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker URL")); copyAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker URL"));
editAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit selected tracker URL"));
} }
QAction *reannounceSelAct = nullptr; QAction *reannounceSelAct = nullptr;
QAction *reannounceAllAct = nullptr; QAction *reannounceAllAct = nullptr;
@@ -591,9 +586,9 @@ QStringList TrackerListWidget::headerLabels()
"#" "#"
, tr("URL") , tr("URL")
, tr("Status") , tr("Status")
, tr("Received")
, tr("Seeds")
, tr("Peers") , tr("Peers")
, tr("Seeds")
, tr("Leeches")
, tr("Downloaded") , tr("Downloaded")
, tr("Message") , tr("Message")
}; };

View File

@@ -54,9 +54,9 @@ public:
COL_TIER, COL_TIER,
COL_URL, COL_URL,
COL_STATUS, COL_STATUS,
COL_RECEIVED,
COL_SEEDS,
COL_PEERS, COL_PEERS,
COL_SEEDS,
COL_LEECHES,
COL_DOWNLOADED, COL_DOWNLOADED,
COL_MSG, COL_MSG,

View File

@@ -34,6 +34,7 @@
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/trackerentry.h" #include "base/bittorrent/trackerentry.h"
#include "base/global.h"
#include "base/net/downloadhandler.h" #include "base/net/downloadhandler.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
@@ -59,7 +60,7 @@ TrackersAdditionDialog::~TrackersAdditionDialog()
QStringList TrackersAdditionDialog::newTrackers() const QStringList TrackersAdditionDialog::newTrackers() const
{ {
QStringList cleanTrackers; QStringList cleanTrackers;
foreach (QString url, m_ui->textEditTrackersList->toPlainText().split('\n')) { for (QString url : asConst(m_ui->textEditTrackersList->toPlainText().split('\n'))) {
url = url.trimmed(); url = url.trimmed();
if (!url.isEmpty()) if (!url.isEmpty())
cleanTrackers << url; cleanTrackers << url;
@@ -83,8 +84,8 @@ void TrackersAdditionDialog::parseUTorrentList(const QString &, const QByteArray
// Load from torrent handle // Load from torrent handle
QList<BitTorrent::TrackerEntry> existingTrackers = m_torrent->trackers(); QList<BitTorrent::TrackerEntry> existingTrackers = m_torrent->trackers();
// Load from current user list // Load from current user list
QStringList tmp = m_ui->textEditTrackersList->toPlainText().split('\n'); const QStringList tmp = m_ui->textEditTrackersList->toPlainText().split('\n');
foreach (const QString &userURL, tmp) { for (const QString &userURL : tmp) {
BitTorrent::TrackerEntry userTracker(userURL); BitTorrent::TrackerEntry userTracker(userURL);
if (!existingTrackers.contains(userTracker)) if (!existingTrackers.contains(userTracker))
existingTrackers << userTracker; existingTrackers << userTracker;

View File

@@ -30,6 +30,7 @@
#include <QListWidgetItem> #include <QListWidgetItem>
#include "base/global.h"
#include "base/rss/rss_article.h" #include "base/rss/rss_article.h"
#include "base/rss/rss_item.h" #include "base/rss/rss_item.h"
@@ -68,7 +69,7 @@ void ArticleListWidget::setRSSItem(RSS::Item *rssItem, bool unreadOnly)
connect(m_rssItem, &RSS::Item::articleRead, this, &ArticleListWidget::handleArticleRead); connect(m_rssItem, &RSS::Item::articleRead, this, &ArticleListWidget::handleArticleRead);
connect(m_rssItem, &RSS::Item::articleAboutToBeRemoved, this, &ArticleListWidget::handleArticleAboutToBeRemoved); connect(m_rssItem, &RSS::Item::articleAboutToBeRemoved, this, &ArticleListWidget::handleArticleAboutToBeRemoved);
foreach (auto article, rssItem->articles()) { for (const auto article : asConst(rssItem->articles())) {
if (!(m_unreadOnly && article->isRead())) { if (!(m_unreadOnly && article->isRead())) {
auto item = createItem(article); auto item = createItem(article);
addItem(item); addItem(item);

View File

@@ -41,6 +41,7 @@
#include <QString> #include <QString>
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/global.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/rss/rss_article.h" #include "base/rss/rss_article.h"
#include "base/rss/rss_autodownloader.h" #include "base/rss/rss_autodownloader.h"
@@ -131,7 +132,7 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
loadFeedList(); loadFeedList();
m_ui->listRules->blockSignals(true); m_ui->listRules->blockSignals(true);
foreach (const RSS::AutoDownloadRule &rule, RSS::AutoDownloader::instance()->rules()) for (const RSS::AutoDownloadRule &rule : asConst(RSS::AutoDownloader::instance()->rules()))
createRuleItem(rule); createRuleItem(rule);
m_ui->listRules->blockSignals(false); m_ui->listRules->blockSignals(false);
@@ -181,7 +182,7 @@ void AutomatedRssDownloader::loadFeedList()
{ {
const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds); const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds);
foreach (auto feed, RSS::Session::instance()->feeds()) { for (const auto feed : asConst(RSS::Session::instance()->feeds())) {
QListWidgetItem *item = new QListWidgetItem(feed->name(), m_ui->listFeeds); QListWidgetItem *item = new QListWidgetItem(feed->name(), m_ui->listFeeds);
item->setData(Qt::UserRole, feed->url()); item->setData(Qt::UserRole, feed->url());
item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsTristate);
@@ -211,7 +212,7 @@ void AutomatedRssDownloader::updateFeedList()
bool allEnabled = true; bool allEnabled = true;
bool anyEnabled = false; bool anyEnabled = false;
foreach (const QListWidgetItem *ruleItem, selection) { for (const QListWidgetItem *ruleItem : asConst(selection)) {
auto rule = RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()); auto rule = RSS::AutoDownloader::instance()->ruleByName(ruleItem->text());
if (rule.feedURLs().contains(feedURL)) if (rule.feedURLs().contains(feedURL))
anyEnabled = true; anyEnabled = true;
@@ -384,7 +385,7 @@ void AutomatedRssDownloader::on_removeRuleBtn_clicked()
if (QMessageBox::question(this, tr("Rule deletion confirmation"), confirmText, QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes) if (QMessageBox::question(this, tr("Rule deletion confirmation"), confirmText, QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
return; return;
foreach (QListWidgetItem *item, selection) for (const QListWidgetItem *item : selection)
RSS::AutoDownloader::instance()->removeRule(item->text()); RSS::AutoDownloader::instance()->removeRule(item->text());
} }
@@ -548,7 +549,7 @@ void AutomatedRssDownloader::clearSelectedRuleDownloadedEpisodeList()
void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedItem) void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedItem)
{ {
const QString feedURL = feedItem->data(Qt::UserRole).toString(); const QString feedURL = feedItem->data(Qt::UserRole).toString();
foreach (QListWidgetItem *ruleItem, m_ui->listRules->selectedItems()) { for (QListWidgetItem *ruleItem : asConst(m_ui->listRules->selectedItems())) {
RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem
? m_currentRule ? m_currentRule
: RSS::AutoDownloader::instance()->ruleByName(ruleItem->text())); : RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()));
@@ -572,16 +573,16 @@ void AutomatedRssDownloader::updateMatchingArticles()
{ {
m_ui->treeMatchingArticles->clear(); m_ui->treeMatchingArticles->clear();
foreach (const QListWidgetItem *ruleItem, m_ui->listRules->selectedItems()) { for (const QListWidgetItem *ruleItem : asConst(m_ui->listRules->selectedItems())) {
RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem
? m_currentRule ? m_currentRule
: RSS::AutoDownloader::instance()->ruleByName(ruleItem->text())); : RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()));
foreach (const QString &feedURL, rule.feedURLs()) { for (const QString &feedURL : asConst(rule.feedURLs())) {
auto feed = RSS::Session::instance()->feedByURL(feedURL); auto feed = RSS::Session::instance()->feedByURL(feedURL);
if (!feed) continue; // feed doesn't exist if (!feed) continue; // feed doesn't exist
QStringList matchingArticles; QStringList matchingArticles;
foreach (auto article, feed->articles()) for (const auto article : asConst(feed->articles()))
if (rule.matches(article->data())) if (rule.matches(article->data()))
matchingArticles << article->title(); matchingArticles << article->title();
if (!matchingArticles.isEmpty()) if (!matchingArticles.isEmpty())
@@ -620,7 +621,7 @@ void AutomatedRssDownloader::addFeedArticlesToTree(RSS::Feed *feed, const QStrin
} }
// Insert the articles // Insert the articles
foreach (const QString &article, articles) { for (const QString &article : articles) {
QPair<QString, QString> key(feed->name(), article); QPair<QString, QString> key(feed->name(), article);
if (!m_treeListEntries.contains(key)) { if (!m_treeListEntries.contains(key)) {
@@ -675,10 +676,10 @@ void AutomatedRssDownloader::updateMustLineValidity()
if (isRegex) if (isRegex)
tokens << text; tokens << text;
else else
foreach (const QString &token, text.split('|')) for (const QString &token : asConst(text.split('|')))
tokens << Utils::String::wildcardToRegex(token); tokens << Utils::String::wildcardToRegex(token);
foreach (const QString &token, tokens) { for (const QString &token : asConst(tokens)) {
QRegularExpression reg(token, QRegularExpression::CaseInsensitiveOption); QRegularExpression reg(token, QRegularExpression::CaseInsensitiveOption);
if (!reg.isValid()) { if (!reg.isValid()) {
if (isRegex) if (isRegex)
@@ -713,10 +714,10 @@ void AutomatedRssDownloader::updateMustNotLineValidity()
if (isRegex) if (isRegex)
tokens << text; tokens << text;
else else
foreach (const QString &token, text.split('|')) for (const QString &token : asConst(text.split('|')))
tokens << Utils::String::wildcardToRegex(token); tokens << Utils::String::wildcardToRegex(token);
foreach (const QString &token, tokens) { for (const QString &token : asConst(tokens)) {
QRegularExpression reg(token, QRegularExpression::CaseInsensitiveOption); QRegularExpression reg(token, QRegularExpression::CaseInsensitiveOption);
if (!reg.isValid()) { if (!reg.isValid()) {
if (isRegex) if (isRegex)

View File

@@ -33,6 +33,7 @@
#include <QDropEvent> #include <QDropEvent>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
#include "base/global.h"
#include "base/rss/rss_article.h" #include "base/rss/rss_article.h"
#include "base/rss/rss_feed.h" #include "base/rss/rss_feed.h"
#include "base/rss/rss_folder.h" #include "base/rss/rss_folder.h"
@@ -219,7 +220,7 @@ void FeedListWidget::dropEvent(QDropEvent *event)
: RSS::Session::instance()->rootFolder()); : RSS::Session::instance()->rootFolder());
// move as much items as possible // move as much items as possible
foreach (QTreeWidgetItem *srcItem, selectedItems()) { for (QTreeWidgetItem *srcItem : asConst(selectedItems())) {
auto rssItem = getRSSItem(srcItem); auto rssItem = getRSSItem(srcItem);
RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(destFolder->path(), rssItem->name())); RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(destFolder->path(), rssItem->name()));
} }
@@ -264,7 +265,7 @@ QTreeWidgetItem *FeedListWidget::createItem(RSS::Item *rssItem, QTreeWidgetItem
void FeedListWidget::fill(QTreeWidgetItem *parent, RSS::Folder *rssParent) void FeedListWidget::fill(QTreeWidgetItem *parent, RSS::Folder *rssParent)
{ {
foreach (auto rssItem, rssParent->items()) { for (const auto rssItem : asConst(rssParent->items())) {
QTreeWidgetItem *item = createItem(rssItem, parent); QTreeWidgetItem *item = createItem(rssItem, parent);
// Recursive call if this is a folder. // Recursive call if this is a folder.
if (auto folder = qobject_cast<RSS::Folder *>(rssItem)) if (auto folder = qobject_cast<RSS::Folder *>(rssItem))

View File

@@ -41,6 +41,7 @@
#include <QString> #include <QString>
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/global.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/rss/rss_article.h" #include "base/rss/rss_article.h"
@@ -186,7 +187,7 @@ void RSSWidget::displayItemsListMenu(const QPoint &)
{ {
bool hasTorrent = false; bool hasTorrent = false;
bool hasLink = false; bool hasLink = false;
foreach (const QListWidgetItem *item, m_articleListWidget->selectedItems()) { for (const QListWidgetItem *item : asConst(m_articleListWidget->selectedItems())) {
auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>()); auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>());
Q_ASSERT(article); Q_ASSERT(article);
@@ -286,7 +287,7 @@ void RSSWidget::on_newFeedButton_clicked()
void RSSWidget::deleteSelectedItems() void RSSWidget::deleteSelectedItems()
{ {
QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); const QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems();
if (selectedItems.isEmpty()) if (selectedItems.isEmpty())
return; return;
if ((selectedItems.size() == 1) && (selectedItems.first() == m_feedListWidget->stickyUnreadItem())) if ((selectedItems.size() == 1) && (selectedItems.first() == m_feedListWidget->stickyUnreadItem()))
@@ -298,7 +299,7 @@ void RSSWidget::deleteSelectedItems()
if (answer == QMessageBox::No) if (answer == QMessageBox::No)
return; return;
foreach (QTreeWidgetItem *item, selectedItems) for (QTreeWidgetItem *item : selectedItems)
if (item != m_feedListWidget->stickyUnreadItem()) if (item != m_feedListWidget->stickyUnreadItem())
RSS::Session::instance()->removeItem(m_feedListWidget->itemPath(item)); RSS::Session::instance()->removeItem(m_feedListWidget->itemPath(item));
} }
@@ -306,9 +307,9 @@ void RSSWidget::deleteSelectedItems()
void RSSWidget::loadFoldersOpenState() void RSSWidget::loadFoldersOpenState()
{ {
const QStringList openedFolders = Preferences::instance()->getRssOpenFolders(); const QStringList openedFolders = Preferences::instance()->getRssOpenFolders();
foreach (const QString &varPath, openedFolders) { for (const QString &varPath : openedFolders) {
QTreeWidgetItem *parent = nullptr; QTreeWidgetItem *parent = nullptr;
foreach (const QString &name, varPath.split('\\')) { for (const QString &name : asConst(varPath.split('\\'))) {
int nbChildren = (parent ? parent->childCount() : m_feedListWidget->topLevelItemCount()); int nbChildren = (parent ? parent->childCount() : m_feedListWidget->topLevelItemCount());
for (int i = 0; i < nbChildren; ++i) { for (int i = 0; i < nbChildren; ++i) {
QTreeWidgetItem *child = (parent ? parent->child(i) : m_feedListWidget->topLevelItem(i)); QTreeWidgetItem *child = (parent ? parent->child(i) : m_feedListWidget->topLevelItem(i));
@@ -325,7 +326,7 @@ void RSSWidget::loadFoldersOpenState()
void RSSWidget::saveFoldersOpenState() void RSSWidget::saveFoldersOpenState()
{ {
QStringList openedFolders; QStringList openedFolders;
foreach (QTreeWidgetItem *item, m_feedListWidget->getAllOpenedFolders()) for (QTreeWidgetItem *item : asConst(m_feedListWidget->getAllOpenedFolders()))
openedFolders << m_feedListWidget->itemPath(item); openedFolders << m_feedListWidget->itemPath(item);
Preferences::instance()->setRssOpenFolders(openedFolders); Preferences::instance()->setRssOpenFolders(openedFolders);
} }
@@ -337,7 +338,7 @@ void RSSWidget::refreshAllFeeds()
void RSSWidget::downloadSelectedTorrents() void RSSWidget::downloadSelectedTorrents()
{ {
foreach (QListWidgetItem *item, m_articleListWidget->selectedItems()) { for (QListWidgetItem *item : asConst(m_articleListWidget->selectedItems())) {
auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>()); auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>());
Q_ASSERT(article); Q_ASSERT(article);
@@ -356,7 +357,7 @@ void RSSWidget::downloadSelectedTorrents()
// open the url of the selected RSS articles in the Web browser // open the url of the selected RSS articles in the Web browser
void RSSWidget::openSelectedArticlesUrls() void RSSWidget::openSelectedArticlesUrls()
{ {
foreach (QListWidgetItem *item, m_articleListWidget->selectedItems()) { for (QListWidgetItem *item : asConst(m_articleListWidget->selectedItems())) {
auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>()); auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>());
Q_ASSERT(article); Q_ASSERT(article);
@@ -397,7 +398,7 @@ void RSSWidget::renameSelectedRSSItem()
void RSSWidget::refreshSelectedItems() void RSSWidget::refreshSelectedItems()
{ {
foreach (QTreeWidgetItem *item, m_feedListWidget->selectedItems()) { for (QTreeWidgetItem *item : asConst(m_feedListWidget->selectedItems())) {
if (item == m_feedListWidget->stickyUnreadItem()) { if (item == m_feedListWidget->stickyUnreadItem()) {
refreshAllFeeds(); refreshAllFeeds();
return; return;
@@ -410,7 +411,7 @@ void RSSWidget::refreshSelectedItems()
void RSSWidget::copySelectedFeedsURL() void RSSWidget::copySelectedFeedsURL()
{ {
QStringList URLs; QStringList URLs;
foreach (QTreeWidgetItem *item, m_feedListWidget->selectedItems()) { for (QTreeWidgetItem *item : asConst(m_feedListWidget->selectedItems())) {
if (auto feed = qobject_cast<RSS::Feed *>(m_feedListWidget->getRSSItem(item))) if (auto feed = qobject_cast<RSS::Feed *>(m_feedListWidget->getRSSItem(item)))
URLs << feed->url(); URLs << feed->url();
} }
@@ -425,7 +426,7 @@ void RSSWidget::handleCurrentFeedItemChanged(QTreeWidgetItem *currentItem)
void RSSWidget::on_markReadButton_clicked() void RSSWidget::on_markReadButton_clicked()
{ {
foreach (QTreeWidgetItem *item, m_feedListWidget->selectedItems()) { for (QTreeWidgetItem *item : asConst(m_feedListWidget->selectedItems())) {
m_feedListWidget->getRSSItem(item)->markAsRead(); m_feedListWidget->getRSSItem(item)->markAsRead();
if (item == m_feedListWidget->stickyUnreadItem()) if (item == m_feedListWidget->stickyUnreadItem())
break; // all items was read break; // all items was read

View File

@@ -39,6 +39,7 @@
#include <QMimeData> #include <QMimeData>
#include <QTableView> #include <QTableView>
#include "base/global.h"
#include "base/net/downloadhandler.h" #include "base/net/downloadhandler.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
@@ -110,7 +111,7 @@ void PluginSelectDialog::dropEvent(QDropEvent *event)
QStringList files; QStringList files;
if (event->mimeData()->hasUrls()) { if (event->mimeData()->hasUrls()) {
foreach (const QUrl &url, event->mimeData()->urls()) { for (const QUrl &url : asConst(event->mimeData()->urls())) {
if (!url.isEmpty()) { if (!url.isEmpty()) {
if (url.scheme().compare("file", Qt::CaseInsensitive) == 0) if (url.scheme().compare("file", Qt::CaseInsensitive) == 0)
files << url.toLocalFile(); files << url.toLocalFile();
@@ -125,7 +126,7 @@ void PluginSelectDialog::dropEvent(QDropEvent *event)
if (files.isEmpty()) return; if (files.isEmpty()) return;
foreach (QString file, files) { for (const QString &file : asConst(files)) {
qDebug("dropped %s", qUtf8Printable(file)); qDebug("dropped %s", qUtf8Printable(file));
startAsyncOp(); startAsyncOp();
m_pluginManager->installPlugin(file); m_pluginManager->installPlugin(file);
@@ -135,8 +136,7 @@ void PluginSelectDialog::dropEvent(QDropEvent *event)
// Decode if we accept drag 'n drop or not // Decode if we accept drag 'n drop or not
void PluginSelectDialog::dragEnterEvent(QDragEnterEvent *event) void PluginSelectDialog::dragEnterEvent(QDragEnterEvent *event)
{ {
QString mime; for (const QString &mime : asConst(event->mimeData()->formats())) {
foreach (mime, event->mimeData()->formats()) {
qDebug("mimeData: %s", qUtf8Printable(mime)); qDebug("mimeData: %s", qUtf8Printable(mime));
} }
@@ -188,7 +188,7 @@ void PluginSelectDialog::on_closeButton_clicked()
void PluginSelectDialog::on_actionUninstall_triggered() void PluginSelectDialog::on_actionUninstall_triggered()
{ {
bool error = false; bool error = false;
foreach (QTreeWidgetItem *item, m_ui->pluginsTree->selectedItems()) { for (QTreeWidgetItem *item : asConst(m_ui->pluginsTree->selectedItems())) {
int index = m_ui->pluginsTree->indexOfTopLevelItem(item); int index = m_ui->pluginsTree->indexOfTopLevelItem(item);
Q_ASSERT(index != -1); Q_ASSERT(index != -1);
QString id = item->text(PLUGIN_ID); QString id = item->text(PLUGIN_ID);
@@ -212,7 +212,7 @@ void PluginSelectDialog::on_actionUninstall_triggered()
void PluginSelectDialog::enableSelection(bool enable) void PluginSelectDialog::enableSelection(bool enable)
{ {
foreach (QTreeWidgetItem *item, m_ui->pluginsTree->selectedItems()) { for (QTreeWidgetItem *item : asConst(m_ui->pluginsTree->selectedItems())) {
int index = m_ui->pluginsTree->indexOfTopLevelItem(item); int index = m_ui->pluginsTree->indexOfTopLevelItem(item);
Q_ASSERT(index != -1); Q_ASSERT(index != -1);
QString id = item->text(PLUGIN_ID); QString id = item->text(PLUGIN_ID);
@@ -265,7 +265,7 @@ void PluginSelectDialog::loadSupportedSearchPlugins()
{ {
// Some clean up first // Some clean up first
m_ui->pluginsTree->clear(); m_ui->pluginsTree->clear();
foreach (QString name, m_pluginManager->allPlugins()) for (const QString &name : asConst(m_pluginManager->allPlugins()))
addNewPlugin(name); addNewPlugin(name);
} }
@@ -360,11 +360,11 @@ void PluginSelectDialog::askForPluginUrl()
void PluginSelectDialog::askForLocalPlugin() void PluginSelectDialog::askForLocalPlugin()
{ {
QStringList pathsList = QFileDialog::getOpenFileNames( const QStringList pathsList = QFileDialog::getOpenFileNames(
nullptr, tr("Select search plugins"), QDir::homePath(), nullptr, tr("Select search plugins"), QDir::homePath(),
tr("qBittorrent search plugin") + QLatin1String(" (*.py)") tr("qBittorrent search plugin") + QLatin1String(" (*.py)")
); );
foreach (QString path, pathsList) { for (const QString &path : pathsList) {
startAsyncOp(); startAsyncOp();
m_pluginManager->installPlugin(path); m_pluginManager->installPlugin(path);
} }
@@ -380,7 +380,7 @@ void PluginSelectDialog::iconDownloaded(const QString &url, QString filePath)
QList<QSize> sizes = icon.availableSizes(); QList<QSize> sizes = icon.availableSizes();
bool invalid = (sizes.isEmpty() || icon.pixmap(sizes.first()).isNull()); bool invalid = (sizes.isEmpty() || icon.pixmap(sizes.first()).isNull());
if (!invalid) { if (!invalid) {
foreach (QTreeWidgetItem *item, findItemsWithUrl(url)) { for (QTreeWidgetItem *item : asConst(findItemsWithUrl(url))) {
QString id = item->text(PLUGIN_ID); QString id = item->text(PLUGIN_ID);
PluginInfo *plugin = m_pluginManager->pluginInfo(id); PluginInfo *plugin = m_pluginManager->pluginInfo(id);
if (!plugin) continue; if (!plugin) continue;

View File

@@ -37,10 +37,6 @@
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "searchsortmodel.h" #include "searchsortmodel.h"
namespace
{
const char i18nContext[] = "SearchListDelegate";
}
SearchListDelegate::SearchListDelegate(QObject *parent) SearchListDelegate::SearchListDelegate(QObject *parent)
: QItemDelegate(parent) : QItemDelegate(parent)
@@ -63,7 +59,7 @@ void SearchListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
case SearchSortModel::LEECHES: case SearchSortModel::LEECHES:
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
QItemDelegate::drawDisplay(painter, opt, option.rect QItemDelegate::drawDisplay(painter, opt, option.rect
, (index.data().toLongLong() >= 0) ? index.data().toString() : QCoreApplication::translate(i18nContext, "Unknown")); , (index.data().toLongLong() >= 0) ? index.data().toString() : tr("Unknown"));
break; break;
default: default:
QItemDelegate::paint(painter, option, index); QItemDelegate::paint(painter, option, index);

View File

@@ -33,6 +33,8 @@
class SearchListDelegate : public QItemDelegate class SearchListDelegate : public QItemDelegate
{ {
Q_OBJECT
public: public:
explicit SearchListDelegate(QObject *parent); explicit SearchListDelegate(QObject *parent);

View File

@@ -28,6 +28,8 @@
#include "searchsortmodel.h" #include "searchsortmodel.h"
#include "base/global.h"
SearchSortModel::SearchSortModel(QObject *parent) SearchSortModel::SearchSortModel(QObject *parent)
: base(parent) : base(parent)
, m_isNameFilterEnabled(false) , m_isNameFilterEnabled(false)
@@ -126,7 +128,7 @@ bool SearchSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceP
const QAbstractItemModel *const sourceModel = this->sourceModel(); const QAbstractItemModel *const sourceModel = this->sourceModel();
if (m_isNameFilterEnabled && !m_searchTerm.isEmpty()) { if (m_isNameFilterEnabled && !m_searchTerm.isEmpty()) {
QString name = sourceModel->data(sourceModel->index(sourceRow, NAME, sourceParent)).toString(); QString name = sourceModel->data(sourceModel->index(sourceRow, NAME, sourceParent)).toString();
for (const QString &word: m_searchTermWords) { for (const QString &word : asConst(m_searchTermWords)) {
int i = name.indexOf(word, 0, Qt::CaseInsensitive); int i = name.indexOf(word, 0, Qt::CaseInsensitive);
if (i == -1) { if (i == -1) {
return false; return false;

View File

@@ -49,6 +49,7 @@
#include <QTreeView> #include <QTreeView>
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/global.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/search/searchpluginmanager.h" #include "base/search/searchpluginmanager.h"
#include "base/search/searchhandler.h" #include "base/search/searchhandler.h"
@@ -166,11 +167,11 @@ void SearchWidget::fillCatCombobox()
using QStrPair = QPair<QString, QString>; using QStrPair = QPair<QString, QString>;
QList<QStrPair> tmpList; QList<QStrPair> tmpList;
foreach (const QString &cat, SearchPluginManager::instance()->getPluginCategories(selectedPlugin())) for (const QString &cat : asConst(SearchPluginManager::instance()->getPluginCategories(selectedPlugin())))
tmpList << qMakePair(SearchPluginManager::categoryFullName(cat), cat); tmpList << qMakePair(SearchPluginManager::categoryFullName(cat), cat);
std::sort(tmpList.begin(), tmpList.end(), [](const QStrPair &l, const QStrPair &r) { return (QString::localeAwareCompare(l.first, r.first) < 0); }); std::sort(tmpList.begin(), tmpList.end(), [](const QStrPair &l, const QStrPair &r) { return (QString::localeAwareCompare(l.first, r.first) < 0); });
foreach (const QStrPair &p, tmpList) { for (const QStrPair &p : asConst(tmpList)) {
qDebug("Supported category: %s", qUtf8Printable(p.second)); qDebug("Supported category: %s", qUtf8Printable(p.second));
m_ui->comboCategory->addItem(p.first, QVariant(p.second)); m_ui->comboCategory->addItem(p.first, QVariant(p.second));
} }
@@ -188,11 +189,11 @@ void SearchWidget::fillPluginComboBox()
using QStrPair = QPair<QString, QString>; using QStrPair = QPair<QString, QString>;
QList<QStrPair> tmpList; QList<QStrPair> tmpList;
foreach (const QString &name, SearchPluginManager::instance()->enabledPlugins()) for (const QString &name : asConst(SearchPluginManager::instance()->enabledPlugins()))
tmpList << qMakePair(SearchPluginManager::instance()->pluginFullName(name), name); tmpList << qMakePair(SearchPluginManager::instance()->pluginFullName(name), name);
std::sort(tmpList.begin(), tmpList.end(), [](const QStrPair &l, const QStrPair &r) { return (l.first < r.first); } ); std::sort(tmpList.begin(), tmpList.end(), [](const QStrPair &l, const QStrPair &r) { return (l.first < r.first); } );
foreach (const QStrPair &p, tmpList) for (const QStrPair &p : asConst(tmpList))
m_ui->selectPlugin->addItem(p.first, QVariant(p.second)); m_ui->selectPlugin->addItem(p.first, QVariant(p.second));
if (m_ui->selectPlugin->count() > 3) if (m_ui->selectPlugin->count() > 3)

View File

@@ -32,6 +32,7 @@
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/sessionstatus.h" #include "base/bittorrent/sessionstatus.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/global.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/string.h" #include "base/utils/string.h"
#include "ui_statsdialog.h" #include "ui_statsdialog.h"
@@ -89,7 +90,7 @@ void StatsDialog::update()
// num_peers is not reliable (adds up peers, which didn't even overcome tcp handshake) // num_peers is not reliable (adds up peers, which didn't even overcome tcp handshake)
quint32 peers = 0; quint32 peers = 0;
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) for (BitTorrent::TorrentHandle *const torrent : asConst(BitTorrent::Session::instance()->torrents()))
peers += torrent->peersCount(); peers += torrent->peersCount();
m_ui->labelWriteStarve->setText(QString("%1%") m_ui->labelWriteStarve->setText(QString("%1%")

View File

@@ -33,6 +33,7 @@
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/global.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
namespace namespace
@@ -236,7 +237,7 @@ void TagFilterModel::torrentAdded(BitTorrent::TorrentHandle *const torrent)
if (items.isEmpty()) if (items.isEmpty())
untaggedItem()->increaseTorrentsCount(); untaggedItem()->increaseTorrentsCount();
foreach (TagModelItem *item, items) for (TagModelItem *item : items)
item->increaseTorrentsCount(); item->increaseTorrentsCount();
} }
@@ -247,7 +248,7 @@ void TagFilterModel::torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const to
if (torrent->tags().isEmpty()) if (torrent->tags().isEmpty())
untaggedItem()->decreaseTorrentsCount(); untaggedItem()->decreaseTorrentsCount();
foreach (TagModelItem *item, findItems(torrent->tags())) for (TagModelItem *item : asConst(findItems(torrent->tags())))
item->decreaseTorrentsCount(); item->decreaseTorrentsCount();
} }
@@ -274,7 +275,7 @@ void TagFilterModel::populate()
[](Torrent *torrent) { return torrent->tags().isEmpty(); }); [](Torrent *torrent) { return torrent->tags().isEmpty(); });
addToModel(getSpecialUntaggedTag(), untaggedCount); addToModel(getSpecialUntaggedTag(), untaggedCount);
foreach (const QString &tag, session->tags()) { for (const QString &tag : asConst(session->tags())) {
const int count = std::count_if(torrents.begin(), torrents.end(), const int count = std::count_if(torrents.begin(), torrents.end(),
[tag](Torrent *torrent) { return torrent->hasTag(tag); }); [tag](Torrent *torrent) { return torrent->hasTag(tag); });
addToModel(tag, count); addToModel(tag, count);
@@ -313,7 +314,7 @@ QVector<TagModelItem *> TagFilterModel::findItems(const QSet<QString> &tags)
{ {
QVector<TagModelItem *> items; QVector<TagModelItem *> items;
items.reserve(tags.size()); items.reserve(tags.size());
foreach (const QString &tag, tags) { for (const QString &tag : tags) {
TagModelItem *item = findItem(tag); TagModelItem *item = findItem(tag);
if (item) if (item)
items.push_back(item); items.push_back(item);

View File

@@ -35,6 +35,7 @@
#include <QMessageBox> #include <QMessageBox>
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/global.h"
#include "autoexpandabledialog.h" #include "autoexpandabledialog.h"
#include "guiiconprovider.h" #include "guiiconprovider.h"
#include "tagfiltermodel.h" #include "tagfiltermodel.h"
@@ -222,7 +223,7 @@ void TagFilterWidget::removeTag()
void TagFilterWidget::removeUnusedTags() void TagFilterWidget::removeUnusedTags()
{ {
auto session = BitTorrent::Session::instance(); auto session = BitTorrent::Session::instance();
foreach (const QString &tag, session->tags()) for (const QString &tag : asConst(session->tags()))
if (model()->data(static_cast<TagFilterProxyModel *>(model())->index(tag), Qt::UserRole) == 0) if (model()->data(static_cast<TagFilterProxyModel *>(model())->index(tag), Qt::UserRole) == 0)
session->removeTag(tag); session->removeTag(tag);
updateGeometry(); updateGeometry();

Some files were not shown because too many files have changed in this diff Show More