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
- osx
dist: xenial
env:
matrix:
# 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:
- $HOME/hombebrew_cache
# opt-in Ubuntu Trusty
dist: trusty
# container-based builds
sudo: false
addons:
coverity_scan:
project:
@@ -53,34 +50,30 @@ addons:
notification_email: sledgehammer999@qbittorrent.org
apt:
sources:
# sources list: https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
- ubuntu-toolchain-r-test
#- boost-latest
# sources list: https://github.com/travis-ci/apt-source-safelist/blob/master/ubuntu.json
- sourceline: 'ppa:qbittorrent-team/qbittorrent-stable'
- sourceline: 'ppa:beineri/opt-qt551-trusty'
- sourceline: 'ppa:adrozdoff/cmake'
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]
- [cmake, ninja-build]
- [ninja-build]
- libssl-dev
- [libboost-dev, libboost-system-dev]
- libtorrent-rasterbar-dev
- [qt55base, qt55svg, qt55tools]
- [gcc-6, g++-6]
- [qtbase5-dev, qttools5-dev-tools, libqt5svg5-dev]
before_install:
# 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
- 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"
- |
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
else
qbtconf="$qbtconf --prefix="$qbt_path""
CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedefs -Wno-inconsistent-missing-override"
fi
# options for specific branches
@@ -89,14 +82,6 @@ before_install:
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
# setup virtual display for after_success target
if [ "$gui" = true ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi ;
# 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
# print settings
@@ -137,6 +122,7 @@ install:
- |
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
export use_ccache=true
ccache -M 512M
ccache -V && ccache --show-stats && ccache --zero-stats
fi
@@ -155,16 +141,7 @@ script:
BUILD_TOOL="ninja"
fi
if [ "$build_system" = "qmake" ]; then
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
# 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
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$CXXFLAGS"
BUILD_TOOL="make"
fi
- $BUILD_TOOL && $BUILD_TOOL install

View File

@@ -10,10 +10,18 @@ type = QT
minimum_perc = 23
mode = developer
[qbittorrent.qbittorrentdesktop_master]
source_file = dist/unix/qbittorrent.desktop
source_lang = en
type = DESKTOP
minimum_perc = 23
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
- FEATURE: Recognize *.ts files as previewable (silver)
- FEATURE: Allow to disable speed graphs (dzmat)

View File

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

476
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# 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>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='qbittorrent'
PACKAGE_TARNAME='qbittorrent'
PACKAGE_VERSION='v4.1.4'
PACKAGE_STRING='qbittorrent v4.1.4'
PACKAGE_VERSION='v4.1.5'
PACKAGE_STRING='qbittorrent v4.1.5'
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
PACKAGE_URL='https://www.qbittorrent.org/'
@@ -595,6 +595,8 @@ QBT_REMOVE_CONFIG
QBT_ADD_CONFIG
QBT_CONF_EXTRA_CFLAGS
QBT_CONF_INCLUDES
QBT_CXX
QBT_CC
EXPAND_MANDIR
EXPAND_DATADIR
EXPAND_BINDIR
@@ -626,7 +628,6 @@ am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
am__quote
am__include
DEPDIR
am__untar
@@ -709,7 +710,8 @@ PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
SHELL
am__quote'
ac_subst_files=''
ac_user_opts='
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.
# This message is too long to be a string in the A/UX 3.1 sh.
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]...
@@ -1368,7 +1370,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of qbittorrent v4.1.4:";;
short | recursive ) echo "Configuration of qbittorrent v4.1.5:";;
esac
cat <<\_ACEOF
@@ -1503,7 +1505,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
qbittorrent configure v4.1.4
qbittorrent configure v4.1.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1642,7 +1644,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
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
$ $0 $@
@@ -3274,7 +3276,7 @@ IFS=$ac_save_IFS
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),
# 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"
am_make=${MAKE-make}
cat > confinc << 'END'
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
cat > confinc.mk << 'END'
am__doit:
@echo this is the am__doit target
@echo this is the am__doit target >confinc.out
.PHONY: am__doit
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__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
# BSD make does it like this.
echo '.include "confinc.mk" # ignored' > confmf.BSD
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
echo 'include confinc.mk # ignored' > confmf.GNU
_am_result=no
for s in GNU BSD; do
{ echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
(${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }
case $?:`cat confinc.out 2>/dev/null` in #(
'0:this is the am__doit target') :
case $s in #(
BSD) :
am__include='.include' am__quote='"' ;; #(
*) :
am__include='include' am__quote='' ;;
esac ;; #(
*) :
;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
$as_echo "$_am_result" >&6; }
rm -f confinc confmf
esac
if test "$am__include" != "#"; then
_am_result="yes ($s style)"
break
fi
done
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.
if test "${enable_dependency_tracking+set}" = set; then :
@@ -3820,7 +3822,7 @@ fi
# Define the identity of the package.
PACKAGE='qbittorrent'
VERSION='v4.1.4'
VERSION='v4.1.5'
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
# dies out for good. For more background, see:
# <http://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/msg00001.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
mkdir_p='$(MKDIR_P)'
# 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.
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
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@@ -4170,7 +4172,9 @@ END
fi
# use compiler from env variables if available
QBT_CC="$CC"
QBT_CXX="$CXX"
# 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
# execute ACTION-IF-FOUND (if present):
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\"
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
$as_echo "$as_me: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\"
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&5
$as_echo "$as_me: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
$as_echo "$as_me: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
fi
CPPFLAGS="$CPPFLAGS_SAVED"
@@ -5011,16 +5015,10 @@ fi
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
# 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
@@ -5041,12 +5039,6 @@ else
QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"
fi
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
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS"
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
LIBS="$libtorrent_LIBS $LIBS"
fi
@@ -5493,10 +5485,116 @@ else
zlib_LIBS=$pkg_cv_zlib_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CPPFLAGS="$zlib_CFLAGS $CPPFLAGS"
CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
LIBS="$zlib_LIBS $LIBS"
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**
# vars automatically. And qmake cannot autoexpand them.
@@ -5583,15 +5681,15 @@ extract() {
for i in $string; do
case "$(echo "$i" | cut -c1)" in
'') ;;
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";;
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";;
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";;
D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
*) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
esac
done
IFS=$SAVEIFS
}
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
extract "$CFLAGS $CXXFLAGS"
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
# 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"
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
# values after options handling.
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
CONFIG_FILES = $CONFIG_FILES
@@ -6232,7 +6332,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
qbittorrent config.status v4.1.4
qbittorrent config.status v4.1.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -6340,7 +6440,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
#
# INIT-COMMANDS
#
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
_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
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
# TODO: see whether this extra hack can be removed once we start
# requiring Autoconf 2.70 or later.
case $CONFIG_FILES in #(
*\'*) :
eval set x "$CONFIG_FILES" ;; #(
*) :
set x $CONFIG_FILES ;; #(
*) :
;;
esac
shift
for mf
# Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named 'Makefile.in', but
# some people rename them; so instead we look at the file content.
# 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
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile which includes
# dependency-tracking related rules and includes.
# Grep'ing the whole file directly is not great: AIX grep has a line
# 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
dirpart=`$as_dirname -- "$mf" ||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$mf" : 'X\(//\)[^/]' \| \
X"$mf" : 'X\(//\)$' \| \
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$mf" |
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|| continue
am_dirpart=`$as_dirname -- "$am_mf" ||
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$am_mf" : 'X\(//\)[^/]' \| \
X"$am_mf" : 'X\(//\)$' \| \
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$am_mf" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6825,53 +6931,48 @@ $as_echo X"$mf" |
q
}
s/.*/./; q'`
else
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running 'make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
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\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
am_filepart=`$as_basename -- "$am_mf" ||
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
X"$am_mf" : 'X\(//\)$' \| \
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$am_mf" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
as_dir=$dirpart/$fdir; as_fn_mkdir_p
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles" >&5
(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
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
# values after options handling.
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
CONFIG_FILES = $CONFIG_FILES
@@ -7547,7 +7648,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
qbittorrent config.status v4.1.4
qbittorrent config.status v4.1.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -7655,7 +7756,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
#
# INIT-COMMANDS
#
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
_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
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
# TODO: see whether this extra hack can be removed once we start
# requiring Autoconf 2.70 or later.
case $CONFIG_FILES in #(
*\'*) :
eval set x "$CONFIG_FILES" ;; #(
*) :
set x $CONFIG_FILES ;; #(
*) :
;;
esac
shift
for mf
# Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named 'Makefile.in', but
# some people rename them; so instead we look at the file content.
# 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
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile which includes
# dependency-tracking related rules and includes.
# Grep'ing the whole file directly is not great: AIX grep has a line
# 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
dirpart=`$as_dirname -- "$mf" ||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$mf" : 'X\(//\)[^/]' \| \
X"$mf" : 'X\(//\)$' \| \
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$mf" |
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|| continue
am_dirpart=`$as_dirname -- "$am_mf" ||
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$am_mf" : 'X\(//\)[^/]' \| \
X"$am_mf" : 'X\(//\)$' \| \
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$am_mf" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -8141,53 +8248,48 @@ $as_echo X"$mf" |
q
}
s/.*/./; q'`
else
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running 'make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
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\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
am_filepart=`$as_basename -- "$am_mf" ||
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
X"$am_mf" : 'X\(//\)$' \| \
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$am_mf" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
as_dir=$dirpart/$fdir; as_fn_mkdir_p
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles" >&5
(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
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_MACRO_DIR([m4])
AC_PROG_CC
@@ -8,7 +8,9 @@ AC_LANG(C++)
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE
# use compiler from env variables if available
QBT_CC="$CC"
QBT_CXX="$CXX"
# Define --wth-* and --enable-* arguments
@@ -162,14 +164,13 @@ AS_CASE(["x$enable_qt_dbus"],
AX_BOOST_BASE([1.35],
[AC_MSG_NOTICE([Boost CPPFLAGS: "$BOOST_CPPFLAGS"
Boost LDFLAGS: "$BOOST_LDFLAGS"])],
[AC_MSG_NOTICE([Boost CXXFLAGS: "$BOOST_CPPFLAGS"])
AC_MSG_NOTICE([Boost LDFLAGS: "$BOOST_LDFLAGS"])],
[AC_MSG_ERROR([Could not find Boost])])
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
# add workaround for problematic boost version
AC_LANG_PUSH(C++)
# taken from ax_boost_base.m4
m4_define([DETECT_BOOST_VERSION_PROGRAM],
[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)], [],
[QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"])
AC_LANG_POP([C++])
AX_BOOST_SYSTEM()
AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"])
@@ -196,14 +196,46 @@ AS_CASE(["x$with_qtsingleapplication"],
PKG_CHECK_MODULES(libtorrent,
[libtorrent-rasterbar >= 1.0.6],
[CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS"
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
LIBS="$libtorrent_LIBS $LIBS"])
PKG_CHECK_MODULES(zlib,
[zlib >= 1.2.5.2],
[CPPFLAGS="$zlib_CFLAGS $CPPFLAGS"
[CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
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**
# vars automatically. And qmake cannot autoexpand them.
AX_DEFINE_DIR([EXPAND_PREFIX], [prefix])
@@ -230,18 +262,20 @@ extract() {
for i in $string; do
case "$(echo "$i" | cut -c1)" in
'') ;;
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";;
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";;
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";;
D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
*) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
esac
done
IFS=$SAVEIFS
}
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
extract "$CFLAGS $CXXFLAGS"
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
# 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_EXTRA_CFLAGS)
AC_SUBST(QBT_ADD_CONFIG)

2
dist/mac/Info.plist vendored
View File

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

Binary file not shown.

View File

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

View File

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

View File

@@ -41,6 +41,7 @@
#include <QMessageBox>
#endif
#include "base/global.h"
#include "base/utils/misc.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;
}
@@ -497,7 +498,7 @@ QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN
QStringList lines = {words.first()};
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) {
lines.last().append(' ' + word);
}

View File

@@ -33,6 +33,7 @@
#include <QFile>
#include <QTextStream>
#include "base/global.h"
#include "base/logger.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);
const Logger *const logger = Logger::instance();
foreach (const Log::Msg &msg, logger->getMessages())
for (const Log::Msg &msg : asConst(logger->getMessages()))
addLogMessage(msg);
connect(logger, &Logger::newLogMessage, this, &FileLogger::addLogMessage);
@@ -87,7 +88,7 @@ void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
QDateTime date = QDateTime::currentDateTime();
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();
switch (ageType) {
case DAYS:

View File

@@ -202,7 +202,7 @@ int main(int argc, char *argv[])
// this is the default in Qt6
app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
#endif
#endif
#endif // Q_OS_WIN
#if defined(Q_OS_MAC)
// 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));
if (msgBox.exec() == QMessageBox::Ok)
return true;
#endif
#endif // DISABLE_GUI
return false;
}
@@ -179,9 +179,9 @@ bool upgrade(bool ask = true)
// ****************************************************************************************
// 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);
foreach (const QString &backupFile, backupFiles_3_3)
for (const QString &backupFile : backupFiles_3_3)
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
// ****************************************************************************************
@@ -197,10 +197,10 @@ bool upgrade(bool ask = true)
if (ask && !userAcceptsUpgrade()) return false;
QStringList backupFiles = backupFolderDir.entryList(
const QStringList backupFiles = backupFolderDir.entryList(
QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted);
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);
if (rxMatch.hasMatch()) {
const QString hashStr = rxMatch.captured(1);
@@ -265,7 +265,7 @@ void migratePlistToIni(const QString &application)
plistFile->setFallbacksEnabled(false);
const QStringList plist = plistFile->allKeys();
if (!plist.isEmpty()) {
foreach (const QString &key, plist)
for (const QString &key : plist)
iniFile.setValue(key, plistFile->value(key));
plistFile->clear();
}

View File

@@ -4,6 +4,7 @@ add_library(qbt_base STATIC
# headers
bittorrent/addtorrentparams.h
bittorrent/cachestatus.h
bittorrent/filepriority.h
bittorrent/infohash.h
bittorrent/magneturi.h
bittorrent/peerinfo.h
@@ -76,6 +77,7 @@ types.h
unicodestrings.h
# sources
bittorrent/filepriority.cpp
bittorrent/infohash.cpp
bittorrent/magneturi.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")))
{
if (!m_storageDir.mkpath(m_storageDir.absolutePath()))
throw AsyncFileStorageError(
QString("Could not create directory '%1'.").arg(m_storageDir.absolutePath()));
throw AsyncFileStorageError {tr("Could not create directory '%1'.")
.arg(m_storageDir.absolutePath())};
// TODO: This folder locking approach does not work for UNIX systems. Implement it.
if (!m_lockFile.open(QFile::WriteOnly))
throw AsyncFileStorageError(m_lockFile.errorString());
throw AsyncFileStorageError {m_lockFile.errorString()};
}
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
#include <stdexcept>
#include <QDir>
#include <QFile>
#include <QObject>
class AsyncFileStorageError : public std::runtime_error
#include "base/exceptions.h"
class AsyncFileStorageError : public RuntimeError
{
public:
explicit AsyncFileStorageError(const QString &message);
QString message() const;
using RuntimeError::RuntimeError;
};
class AsyncFileStorage : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(AsyncFileStorage)
public:
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);

View File

@@ -3,6 +3,7 @@ HEADERS += \
$$PWD/asyncfilestorage.h \
$$PWD/bittorrent/addtorrentparams.h \
$$PWD/bittorrent/cachestatus.h \
$$PWD/bittorrent/filepriority.h \
$$PWD/bittorrent/infohash.h \
$$PWD/bittorrent/magneturi.h \
$$PWD/bittorrent/peerinfo.h \
@@ -75,6 +76,7 @@ HEADERS += \
SOURCES += \
$$PWD/asyncfilestorage.cpp \
$$PWD/bittorrent/filepriority.cpp \
$$PWD/bittorrent/infohash.cpp \
$$PWD/bittorrent/magneturi.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_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));
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()));
}

View File

@@ -1,6 +1,6 @@
/*
* 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
* 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);
QString filepath = m_resumeDataDir.absoluteFilePath(filename);
const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
qDebug() << "Saving resume data in" << filepath;
QSaveFile resumeFile(filepath);
if (resumeFile.open(QIODevice::WriteOnly)) {
resumeFile.write(data);
if (!resumeFile.commit()) {
Logger::instance()->addMessage(QString("Couldn't save resume data in %1. Error: %2")
.arg(filepath, resumeFile.errorString()), Log::WARNING);
QSaveFile file {filepath};
if (file.open(QIODevice::WriteOnly)) {
file.write(data);
if (!file.commit()) {
Logger::instance()->addMessage(QString("Couldn't save data in '%1'. Error: %2")
.arg(filepath, file.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.
* 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
* modify it under the terms of the GNU General Public License
@@ -26,8 +26,7 @@
* exception statement from your version.
*/
#ifndef RESUMEDATASAVINGMANAGER_H
#define RESUMEDATASAVINGMANAGER_H
#pragma once
#include <QByteArray>
#include <QDir>
@@ -36,15 +35,15 @@
class ResumeDataSavingManager : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(ResumeDataSavingManager)
public:
explicit ResumeDataSavingManager(const QString &resumeFolderPath);
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:
QDir m_resumeDataDir;
};
#endif // RESUMEDATASAVINGMANAGER_H

View File

@@ -69,6 +69,8 @@
#endif
#include "base/algorithm.h"
#include "base/exceptions.h"
#include "base/global.h"
#include "base/logger.h"
#include "base/net/downloadhandler.h"
#include "base/net/downloadmanager.h"
@@ -198,7 +200,7 @@ namespace
for (auto i = categories.cbegin(); i != categories.cend(); ++i) {
const QString &category = i.key();
foreach (const QString &subcat, Session::expandCategory(category)) {
for (const QString &subcat : asConst(Session::expandCategory(category))) {
if (!expanded.contains(subcat))
expanded[subcat] = "";
}
@@ -275,6 +277,7 @@ Session::Session(QObject *parent)
, m_announceToAllTrackers(BITTORRENT_SESSION_KEY("AnnounceToAllTrackers"), false)
, m_announceToAllTiers(BITTORRENT_SESSION_KEY("AnnounceToAllTiers"), true)
, m_asyncIOThreads(BITTORRENT_SESSION_KEY("AsyncIOThreadsCount"), 4)
, m_checkingMemUsage(BITTORRENT_SESSION_KEY("CheckingMemUsageSize"), 16)
, m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), 64)
, m_diskCacheTTL(BITTORRENT_SESSION_KEY("DiskCacheTTL"), 60)
, m_useOSCache(BITTORRENT_SESSION_KEY("UseOSCache"), true)
@@ -468,7 +471,7 @@ Session::Session(QObject *parent)
});
configurePeerClasses();
#endif
#endif // LIBTORRENT_VERSION_NUM < 10100
// Enabling plugins
//m_nativeSession->add_extension(&libt::create_metadata_plugin);
@@ -532,7 +535,7 @@ Session::Session(QObject *parent)
connect(&m_networkManager, &QNetworkConfigurationManager::configurationChanged, this, &Session::networkConfigurationChange);
m_ioThread = new QThread(this);
m_resumeDataSavingManager = new ResumeDataSavingManager(m_resumeFolderPath);
m_resumeDataSavingManager = new ResumeDataSavingManager {m_resumeFolderPath};
m_resumeDataSavingManager->moveToThread(m_ioThread);
connect(m_ioThread, &QThread::finished, m_resumeDataSavingManager, &QObject::deleteLater);
m_ioThread->start();
@@ -609,7 +612,7 @@ void Session::setTempPathEnabled(bool enabled)
{
if (enabled != isTempPathEnabled()) {
m_isTempPathEnabled = enabled;
foreach (TorrentHandle *const torrent, m_torrents)
for (TorrentHandle *const torrent : asConst(m_torrents))
torrent->handleTempPathChanged();
}
}
@@ -623,7 +626,7 @@ void Session::setAppendExtensionEnabled(bool enabled)
{
if (isAppendExtensionEnabled() != enabled) {
// append or remove .!qB extension for incomplete files
foreach (TorrentHandle *const torrent, m_torrents)
for (TorrentHandle *const torrent : asConst(m_torrents))
torrent->handleAppendExtensionToggled();
m_isAppendExtensionEnabled = enabled;
@@ -751,7 +754,7 @@ bool Session::addCategory(const QString &name, const QString &savePath)
return false;
if (isSubcategoriesEnabled()) {
foreach (const QString &parent, expandCategory(name)) {
for (const QString &parent : asConst(expandCategory(name))) {
if ((parent != name) && !m_categories.contains(parent)) {
m_categories[parent] = "";
emit categoryAdded(parent);
@@ -774,12 +777,12 @@ bool Session::editCategory(const QString &name, const QString &savePath)
m_categories[name] = savePath;
m_storedCategories = map_cast(m_categories);
if (isDisableAutoTMMWhenCategorySavePathChanged()) {
foreach (TorrentHandle *const torrent, torrents())
for (TorrentHandle *const torrent : asConst(torrents()))
if (torrent->category() == name)
torrent->setAutoTMMEnabled(false);
}
else {
foreach (TorrentHandle *const torrent, torrents())
for (TorrentHandle *const torrent : asConst(torrents()))
if (torrent->category() == name)
torrent->handleCategorySavePathChanged();
}
@@ -789,7 +792,7 @@ bool Session::editCategory(const QString &name, const QString &savePath)
bool Session::removeCategory(const QString &name)
{
foreach (TorrentHandle *const torrent, torrents())
for (TorrentHandle *const torrent : asConst(torrents()))
if (torrent->belongsToCategory(name))
torrent->setCategory("");
@@ -876,7 +879,7 @@ bool Session::addTag(const QString &tag)
bool Session::removeTag(const QString &tag)
{
if (m_tags.remove(tag)) {
foreach (TorrentHandle *const torrent, torrents())
for (TorrentHandle *const torrent : asConst(torrents()))
torrent->removeTag(tag);
m_storedTags = m_tags.toList();
emit tagRemoved(tag);
@@ -1084,7 +1087,7 @@ void Session::configure()
void Session::processBannedIPs(libt::ip_filter &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;
libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
Q_ASSERT(!ec);
@@ -1203,7 +1206,7 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
const ushort port = this->port();
std::pair<int, int> ports(port, port);
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;
std::string interfacesStr;
@@ -1252,7 +1255,7 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
}
#else
settingsPack.set_str(libt::settings_pack::outgoing_interfaces, networkInterface().toStdString());
#endif
#endif // Q_OS_WIN
m_listenInterfaceChanged = false;
}
@@ -1317,6 +1320,9 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
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;
settingsPack.set_int(libt::settings_pack::cache_size, cacheSize);
settingsPack.set_int(libt::settings_pack::cache_expiry, diskCacheTTL());
@@ -1461,7 +1467,7 @@ void Session::configurePeerClasses()
, 1 << libt::session::global_peer_class_id);
}
catch (std::exception &) {}
#endif
#endif // TORRENT_USE_IPV6
if (ignoreLimitsOnLAN()) {
// local networks
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);
}
catch (std::exception &) {}
#endif
#endif // TORRENT_USE_IPV6
}
m_nativeSession->set_peer_class_filter(f);
@@ -1517,7 +1523,7 @@ void Session::configurePeerClasses()
m_nativeSession->set_peer_class_type_filter(peerClassTypeFilter);
}
#else
#else // LIBTORRENT_VERSION_NUM >= 10100
void Session::adjustLimits(libt::session_settings &sessionSettings)
{
@@ -1734,7 +1740,7 @@ void Session::configure(libtorrent::session_settings &sessionSettings)
break;
}
}
#endif
#endif // LIBTORRENT_VERSION_NUM >= 10100
void Session::enableTracker(bool enable)
{
@@ -1769,7 +1775,7 @@ void Session::enableBandwidthScheduler()
void Session::populateAdditionalTrackers()
{
m_additionalTrackerList.clear();
foreach (QString tracker, additionalTrackers().split('\n')) {
for (QString tracker : asConst(additionalTrackers().split('\n'))) {
tracker = tracker.trimmed();
if (!tracker.isEmpty())
m_additionalTrackerList << tracker;
@@ -1780,7 +1786,7 @@ void Session::processShareLimits()
{
qDebug("Processing share limits...");
foreach (TorrentHandle *const torrent, m_torrents) {
for (TorrentHandle *const torrent : asConst(torrents())) {
if (torrent->isSeed() && !torrent->isForced()) {
if (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT) {
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);
#endif
// Remove unwanted and incomplete files
foreach (const QString &unwantedFile, unwantedFiles) {
for (const QString &unwantedFile : asConst(unwantedFiles)) {
qDebug("Removing unwanted file: %s", qUtf8Printable(unwantedFile));
Utils::Fs::forceRemove(unwantedFile);
const QString parentFolder = Utils::Fs::branchPath(unwantedFile);
@@ -1947,7 +1953,7 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
QStringList filters;
filters << QString("%1.*").arg(torrent->hash());
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));
delete torrent;
@@ -1978,12 +1984,12 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
void Session::increaseTorrentsPriority(const QStringList &hashes)
{
std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >,
std::greater<QPair<int, TorrentHandle *> > > torrentQueue;
std::vector<QPair<int, TorrentHandle *>>,
std::greater<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority
foreach (const InfoHash &hash, hashes) {
TorrentHandle *const torrent = m_torrents.value(hash);
for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
torrentQueue.push(qMakePair(torrent->queuePosition(), torrent));
}
@@ -1995,18 +2001,18 @@ void Session::increaseTorrentsPriority(const QStringList &hashes)
torrentQueue.pop();
}
handleTorrentsPrioritiesChanged();
saveTorrentsQueue();
}
void Session::decreaseTorrentsPriority(const QStringList &hashes)
{
std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >,
std::less<QPair<int, TorrentHandle *> > > torrentQueue;
std::vector<QPair<int, TorrentHandle *>>,
std::less<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority
foreach (const InfoHash &hash, hashes) {
TorrentHandle *const torrent = m_torrents.value(hash);
for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
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)
torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key()));
handleTorrentsPrioritiesChanged();
saveTorrentsQueue();
}
void Session::topTorrentsPriority(const QStringList &hashes)
{
std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >,
std::greater<QPair<int, TorrentHandle *> > > torrentQueue;
std::vector<QPair<int, TorrentHandle *>>,
std::greater<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority
foreach (const InfoHash &hash, hashes) {
TorrentHandle *const torrent = m_torrents.value(hash);
for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
torrentQueue.push(qMakePair(torrent->queuePosition(), torrent));
}
@@ -2044,18 +2050,18 @@ void Session::topTorrentsPriority(const QStringList &hashes)
torrentQueue.pop();
}
handleTorrentsPrioritiesChanged();
saveTorrentsQueue();
}
void Session::bottomTorrentsPriority(const QStringList &hashes)
{
std::priority_queue<QPair<int, TorrentHandle *>,
std::vector<QPair<int, TorrentHandle *> >,
std::less<QPair<int, TorrentHandle *> > > torrentQueue;
std::vector<QPair<int, TorrentHandle *>>,
std::less<QPair<int, TorrentHandle *>>> torrentQueue;
// Sort torrents by priority
foreach (const InfoHash &hash, hashes) {
TorrentHandle *const torrent = m_torrents.value(hash);
for (const InfoHash infoHash : hashes) {
TorrentHandle *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
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)
torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key()));
handleTorrentsPrioritiesChanged();
saveTorrentsQueue();
}
QHash<InfoHash, TorrentHandle *> Session::torrents() const
@@ -2366,7 +2372,7 @@ void Session::exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolde
void Session::generateResumeData(bool final)
{
foreach (TorrentHandle *const torrent, m_torrents) {
for (TorrentHandle *const torrent : asConst(m_torrents)) {
if (!torrent->isValid()) continue;
if (torrent->isChecking() || torrent->isPaused()) continue;
if (!final && !torrent->needSaveResumeData()) continue;
@@ -2379,11 +2385,13 @@ void Session::generateResumeData(bool final)
// Called on exit
void Session::saveResumeData()
{
qDebug("Saving fast resume data...");
qDebug("Saving resume data...");
// Pause session
m_nativeSession->pause();
if (isQueueingSystemEnabled())
saveTorrentsQueue();
generateResumeData(true);
while (m_numResumeData > 0) {
@@ -2394,7 +2402,7 @@ void Session::saveResumeData()
break;
}
for (const auto a: alerts) {
for (const auto a : alerts) {
switch (a->type()) {
case libt::save_resume_data_failed_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)
{
path = normalizeSavePath(path);
@@ -2416,10 +2449,10 @@ void Session::setDefaultSavePath(QString path)
m_defaultSavePath = path;
if (isDisableAutoTMMWhenDefaultSavePathChanged())
foreach (TorrentHandle *const torrent, torrents())
for (TorrentHandle *const torrent : asConst(torrents()))
torrent->setAutoTMMEnabled(false);
else
foreach (TorrentHandle *const torrent, torrents())
for (TorrentHandle *const torrent : asConst(torrents()))
torrent->handleCategorySavePathChanged();
}
@@ -2430,7 +2463,7 @@ void Session::setTempPath(QString path)
m_tempPath = path;
foreach (TorrentHandle *const torrent, m_torrents)
for (TorrentHandle *const torrent : asConst(m_torrents))
torrent->handleTempPathChanged();
}
@@ -2504,7 +2537,7 @@ const QStringList Session::getListeningIPs()
QHostAddress ip;
QString ipString;
QAbstractSocket::NetworkLayerProtocol protocol;
foreach (const QNetworkAddressEntry &entry, addresses) {
for (const QNetworkAddressEntry &entry : addresses) {
ip = entry.ip();
ipString = ip.toString();
protocol = ip.protocol();
@@ -2550,7 +2583,7 @@ void Session::configureListeningInterface()
libt::error_code ec;
const QStringList IPs = getListeningIPs();
foreach (const QString ip, IPs) {
for (const QString ip : IPs) {
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);
m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port);
@@ -2570,7 +2603,7 @@ void Session::configureListeningInterface()
#else
m_listenInterfaceChanged = true;
configureDeferred();
#endif
#endif // LIBTORRENT_VERSION_NUM < 10100
}
int Session::globalDownloadSpeedLimit() const
@@ -2983,7 +3016,7 @@ void Session::setMaxConnectionsPerTorrent(int max)
m_maxConnectionsPerTorrent = max;
// 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;
try {
handle.set_max_connections(max);
@@ -3005,7 +3038,7 @@ void Session::setMaxUploadsPerTorrent(int max)
m_maxUploadsPerTorrent = max;
// 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;
try {
handle.set_max_uploads(max);
@@ -3055,6 +3088,22 @@ void Session::setAsyncIOThreads(const int num)
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 size = m_diskCacheSize;
@@ -3213,6 +3262,11 @@ void Session::setQueueingSystemEnabled(bool enabled)
if (enabled != m_isQueueingEnabled) {
m_isQueueingEnabled = enabled;
configureDeferred();
if (enabled)
saveTorrentsQueue();
else
removeTorrentsQueue();
}
}
@@ -3543,18 +3597,6 @@ void Session::handleTorrentShareLimitChanged(TorrentHandle *const torrent)
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)
{
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)
{
if (!torrent->hasError() && !torrent->hasMissingFiles()) {
if (!torrent->hasError() && !torrent->hasMissingFiles())
saveTorrentResumeData(torrent);
if (isQueueingSystemEnabled())
handleTorrentsPrioritiesChanged();
}
emit torrentFinished(torrent);
qDebug("Checking if the torrent contains torrent files to download");
@@ -3724,8 +3763,9 @@ void Session::handleTorrentResumeDataReady(TorrentHandle *const torrent, const l
QByteArray out;
libt::bencode(std::back_inserter(out), data);
QMetaObject::invokeMethod(m_resumeDataSavingManager, "saveResumeData",
Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out));
const QString filename = QString("%1.fastresume").arg(torrent->hash());
QMetaObject::invokeMethod(m_resumeDataSavingManager, "save",
Q_ARG(QString, filename), Q_ARG(QByteArray, out));
}
void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent)
@@ -3757,7 +3797,7 @@ void Session::handleTorrentTrackerWarning(TorrentHandle *const torrent, const QS
bool Session::hasPerTorrentRatioLimit() const
{
foreach (TorrentHandle *const torrent, m_torrents)
for (TorrentHandle *const torrent : asConst(m_torrents))
if (torrent->ratioLimit() >= 0) return true;
return false;
@@ -3765,7 +3805,7 @@ bool Session::hasPerTorrentRatioLimit() const
bool Session::hasPerTorrentSeedingTimeLimit() const
{
foreach (TorrentHandle *const torrent, m_torrents)
for (TorrentHandle *const torrent : asConst(m_torrents))
if (torrent->seedingTimeLimit() >= 0) return true;
return false;
@@ -3778,11 +3818,11 @@ void Session::initResumeFolder()
if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) {
m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock"));
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 {
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;
};
qDebug("Starting up torrents");
qDebug("Starting up torrents...");
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$"));
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);
if (!rxMatch.hasMatch()) continue;
QString hash = rxMatch.captured(1);
QString fastresumePath = resumeDataDir.absoluteFilePath(fastresumeName);
const QString hash = rxMatch.captured(1);
const 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 (readFile(fastresumePath, data)
&& loadTorrentResumeData(data, torrentParams, queuePosition, magnetUri)) {
startupTorrent({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
@@ -4035,7 +4116,7 @@ void Session::readAlerts()
std::vector<libt::alert *> alerts;
getPendingAlerts(alerts);
for (const auto a: alerts) {
for (const auto a : alerts) {
handleAlert(a);
#if LIBTORRENT_VERSION_NUM < 10100
delete a;
@@ -4442,7 +4523,7 @@ void Session::handleSessionStatsAlert(libt::session_stats_alert *p)
emit statsUpdated();
}
#else
#else // LIBTORRENT_VERSION_NUM >= 10100
void Session::updateStats()
{
libt::session_status ss = m_nativeSession->status();
@@ -4479,7 +4560,7 @@ void Session::updateStats()
emit statsUpdated();
}
#endif
#endif // LIBTORRENT_VERSION_NUM >= 10100
void Session::handleStateUpdateAlert(libt::state_update_alert *p)
{
@@ -4487,14 +4568,14 @@ void Session::handleStateUpdateAlert(libt::state_update_alert *p)
updateStats();
#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);
if (torrent)
torrent->handleStateUpdate(status);
}
m_torrentStatusReport = TorrentStatusReport();
foreach (TorrentHandle *const torrent, m_torrents) {
for (TorrentHandle *const torrent : asConst(m_torrents)) {
if (torrent->isDownloading())
++m_torrentStatusReport.nbDownloading;
if (torrent->isUploading())
@@ -4530,7 +4611,7 @@ namespace
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.restored = true;

View File

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

View File

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

View File

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

View File

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

View File

@@ -247,7 +247,7 @@ QList<TrackerEntry> TorrentInfo::trackers() const
if (!isValid()) return QList<TrackerEntry>();
QList<TrackerEntry> trackers;
foreach (const libt::announce_entry &tracker, m_nativeInfo->trackers())
for (const libt::announce_entry &tracker : m_nativeInfo->trackers())
trackers.append(tracker);
return trackers;
@@ -258,7 +258,7 @@ QList<QUrl> TorrentInfo::urlSeeds() const
if (!isValid()) return QList<QUrl>();
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)
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());
}
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
// 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
{
return ip + ':' + QString::number(port);
return ip.toString() + ':' + QString::number(port);
}
libtorrent::entry Peer::toEntry(bool noPeerId) const
@@ -68,7 +68,7 @@ libtorrent::entry Peer::toEntry(bool noPeerId) const
libtorrent::entry::dictionary_type peerMap;
if (!noPeerId)
peerMap["id"] = libtorrent::entry(peerId.toStdString());
peerMap["ip"] = libtorrent::entry(ip.toStdString());
peerMap["ip"] = libtorrent::entry(ip.toString().toStdString());
peerMap["port"] = libtorrent::entry(port);
return libtorrent::entry(peerMap);
@@ -136,7 +136,7 @@ void Tracker::respondToAnnounceRequest()
QMap<QString, QByteArray> queryParams;
// Parse GET parameters
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('=');
if (sepPos <= 0) continue; // ignores params without name
@@ -145,10 +145,12 @@ void Tracker::respondToAnnounceRequest()
queryParams[paramName] = paramValue;
}
TrackerAnnounceRequest annonceReq;
TrackerAnnounceRequest announceReq;
// 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
if (!queryParams.contains("info_hash")) {
@@ -156,7 +158,7 @@ void Tracker::respondToAnnounceRequest()
status(101, "Missing info_hash");
return;
}
annonceReq.infoHash = queryParams.value("info_hash");
announceReq.infoHash = queryParams.value("info_hash");
// info_hash cannot be longer than 20 bytes
/*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());
@@ -170,7 +172,7 @@ void Tracker::respondToAnnounceRequest()
status(102, "Missing peer_id");
return;
}
annonceReq.peer.peerId = queryParams.value("peer_id");
announceReq.peer.peerId = queryParams.value("peer_id");
// peer_id cannot be longer than 20 bytes
/*if (annonce_req.peer.peer_id.length() > 20) {
qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id));
@@ -185,52 +187,52 @@ void Tracker::respondToAnnounceRequest()
return;
}
bool ok = false;
annonceReq.peer.port = queryParams.value("port").toInt(&ok);
if (!ok || (annonceReq.peer.port < 0) || (annonceReq.peer.port > 65535)) {
qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port);
announceReq.peer.port = queryParams.value("port").toInt(&ok);
if (!ok || (announceReq.peer.port < 0) || (announceReq.peer.port > 65535)) {
qDebug("Tracker: Invalid port number (%d)", announceReq.peer.port);
status(103, "Missing port");
return;
}
// 4. Get event
annonceReq.event = "";
announceReq.event = "";
if (queryParams.contains("event")) {
annonceReq.event = queryParams.value("event");
qDebug("Tracker: event is %s", qUtf8Printable(annonceReq.event));
announceReq.event = queryParams.value("event");
qDebug("Tracker: event is %s", qUtf8Printable(announceReq.event));
}
// 5. Get numwant
annonceReq.numwant = 50;
announceReq.numwant = 50;
if (queryParams.contains("numwant")) {
int tmp = queryParams.value("numwant").toInt();
if (tmp > 0) {
qDebug("Tracker: numwant = %d", tmp);
annonceReq.numwant = tmp;
announceReq.numwant = tmp;
}
}
// 6. no_peer_id (extension)
annonceReq.noPeerId = false;
announceReq.noPeerId = false;
if (queryParams.contains("no_peer_id"))
annonceReq.noPeerId = true;
announceReq.noPeerId = true;
// 7. TODO: support "compact" extension
// Done parsing, now let's reply
if (annonceReq.event == "stopped") {
unregisterPeer(annonceReq);
if (announceReq.event == "stopped") {
unregisterPeer(announceReq);
}
else {
registerPeer(annonceReq);
replyWithPeerList(annonceReq);
registerPeer(announceReq);
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
if (m_torrents.size() == MAX_TORRENTS) {
// Reached max size, remove a random torrent
@@ -239,34 +241,34 @@ void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
}
// Register the user
PeerList &peers = m_torrents[annonceReq.infoHash];
if (!peers.contains(annonceReq.peer.uid())) {
PeerList &peers = m_torrents[announceReq.infoHash];
if (!peers.contains(announceReq.peer.uid())) {
// Unknown peer
if (peers.size() == MAX_PEERS_PER_TORRENT) {
// Too many peers, remove a random one
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");
}
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &announceReq)
{
// Prepare the entry for bencoding
libtorrent::entry::dictionary_type replyDict;
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
libtorrent::entry::list_type peerList;
for (const Peer &p : m_torrents.value(annonceReq.infoHash))
peerList.push_back(p.toEntry(annonceReq.noPeerId));
for (const Peer &p : m_torrents.value(announceReq.infoHash))
peerList.push_back(p.toEntry(announceReq.noPeerId));
replyDict["peers"] = libtorrent::entry(peerList);
const libtorrent::entry replyEntry(replyDict);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,16 +33,13 @@
const char C_TORRENT_FILE_EXTENSION[] = ".torrent";
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
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>
void qAsConst(const T &&) = delete;
#endif
constexpr typename std::add_const<T>::type asConst(T &&t) noexcept { return std::move(t); }
// returns a const object copy
// Prevent const rvalue arguments
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
{
foreach (const QString &str, list) {
for (const QString &str : list) {
if (!str.startsWith(encoding))
continue;

View File

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

View File

@@ -52,6 +52,7 @@ namespace Http
const char HEADER_HOST[] = "host";
const char HEADER_ORIGIN[] = "origin";
const char HEADER_REFERER[] = "referer";
const char HEADER_REFERRER_POLICY[] = "referrer-policy";
const char HEADER_SET_COOKIE[] = "set-cookie";
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options";
const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host";
@@ -107,7 +108,7 @@ namespace Http
uint code;
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
@@ -116,7 +117,7 @@ namespace Http
QStringMap headers;
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 <QUrl>
#include "base/global.h"
#include "base/preferences.h"
#include "downloadhandler.h"
#include "proxyconfigurationmanager.h"
@@ -56,7 +57,7 @@ namespace
{
QDateTime now = QDateTime::currentDateTime();
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))
cookies.removeAll(cookie);
}
@@ -68,7 +69,7 @@ namespace
{
QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = allCookies();
foreach (const QNetworkCookie &cookie, allCookies()) {
for (const QNetworkCookie &cookie : asConst(allCookies())) {
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
@@ -83,7 +84,7 @@ namespace
{
QDateTime now = QDateTime::currentDateTime();
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))
cookies.removeAll(cookie);
}
@@ -95,7 +96,7 @@ namespace
{
QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = cookieList;
foreach (const QNetworkCookie &cookie, cookieList) {
for (const QNetworkCookie &cookie : cookieList) {
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}

View File

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

View File

@@ -43,6 +43,7 @@
#include <QTcpSocket>
#endif
#include "base/global.h"
#include "base/logger.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 (!value.contains("=?") && latin1->canEncode(value)) {
bool firstWord = true;
foreach (const QByteArray& word, value.toLatin1().split(' ')) {
for (const QByteArray &word : asConst(value.toLatin1().split(' '))) {
if (line.size() > 78) {
rv = rv + line + "\r\n";
line.clear();

View File

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

View File

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

View File

@@ -435,13 +435,13 @@ namespace
if (leapSecond)
second = 59; // apparently a leap second - validate below, once time zone is known
int month = 0;
for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month);
for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month);
int dayOfWeek = -1;
if (!parts[nwday].isEmpty()) {
// Look up the weekday name
while (++dayOfWeek < 7 && (shortDay[dayOfWeek] != parts[nwday]));
while ((++dayOfWeek < 7) && (shortDay[dayOfWeek] != parts[nwday]));
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
@@ -450,7 +450,7 @@ namespace
int i = parts[nyear].size();
if (i < 4) {
// 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
@@ -473,17 +473,17 @@ namespace
else {
// Check for an obsolete time zone name
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'
}
else if (zone != "UT" && zone != "GMT") { // treated as '+0000'
else if ((zone != "UT") && (zone != "GMT")) { // treated as '+0000'
offset = (zone == "EDT")
? -4 * 3600
: ((zone == "EST") || (zone == "CDT"))
? -5 * 3600
: ((zone == "CST") || (zone == "MDT"))
? -6 * 3600
: (zone == "MST" || zone == "PDT")
: ((zone == "MST") || (zone == "PDT"))
? -7 * 3600
: (zone == "PST")
? -8 * 3600
@@ -502,12 +502,12 @@ namespace
}
}
QDate qdate(year, month + 1, day); // convert date, and check for out-of-range
if (!qdate.isValid())
QDate qDate(year, month + 1, day); // convert date, and check for out-of-range
if (!qDate.isValid())
return QDateTime::currentDateTime();
QTime qTime(hour, minute, second);
QDateTime result(qdate, qTime, Qt::UTC);
QDateTime result(qDate, qTime, Qt::UTC);
if (offset)
result = result.addSecs(-offset);
if (!result.isValid())

View File

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

View File

@@ -126,7 +126,7 @@ namespace RSS
bool smartFilter = false;
QStringList previouslyMatchedEpisodes;
mutable QString lastComputedEpisode;
mutable QStringList lastComputedEpisodes;
mutable QHash<QString, QRegularExpression> cachedRegexes;
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.
// 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
if (matchesExpression(articleTitle, expression))
return true;
@@ -246,14 +246,14 @@ bool AutoDownloadRule::matchesMustContainExpression(const QString &articleTitle)
return false;
}
bool AutoDownloadRule::matchesMustNotContainExpression(const QString& articleTitle) const
bool AutoDownloadRule::matchesMustNotContainExpression(const QString &articleTitle) const
{
if (m_dataPtr->mustNotContain.empty())
return true;
// Each expression is either a regex, or a set of wildcards separated by whitespace.
// 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
if (matchesExpression(articleTitle, expression))
return false;
@@ -262,10 +262,10 @@ bool AutoDownloadRule::matchesMustNotContainExpression(const QString& articleTit
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
m_dataPtr->lastComputedEpisode.clear();
m_dataPtr->lastComputedEpisodes.clear();
if (m_dataPtr->episodeFilter.isEmpty())
return true;
@@ -332,7 +332,7 @@ bool AutoDownloadRule::matchesEpisodeFilterExpression(const QString& articleTitl
return false;
}
bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString& articleTitle) const
bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString &articleTitle) const
{
if (!useSmartFilter())
return true;
@@ -343,11 +343,35 @@ bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString& articleTitle) co
// See if this episode has been downloaded before
const bool previouslyMatched = m_dataPtr->previouslyMatchedEpisodes.contains(episodeStr);
const bool isRepack = articleTitle.contains("REPACK", Qt::CaseInsensitive) || articleTitle.contains("PROPER", Qt::CaseInsensitive);
if (previouslyMatched && (!isRepack || !AutoDownloader::instance()->downloadRepacks()))
return false;
if (previouslyMatched) {
if (!AutoDownloader::instance()->downloadRepacks())
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;
}
@@ -379,10 +403,10 @@ bool AutoDownloadRule::accepts(const QVariantHash &articleData)
setLastMatch(articleData[Article::KeyDate].toDateTime());
if (!m_dataPtr->lastComputedEpisode.isEmpty()) {
// TODO: probably need to add a marker for PROPER/REPACK to avoid duplicate downloads
m_dataPtr->previouslyMatchedEpisodes.append(m_dataPtr->lastComputedEpisode);
m_dataPtr->lastComputedEpisode.clear();
// If there's a matched episode string, add that to the previously matched list
if (!m_dataPtr->lastComputedEpisodes.isEmpty()) {
m_dataPtr->previouslyMatchedEpisodes.append(m_dataPtr->lastComputedEpisodes);
m_dataPtr->lastComputedEpisodes.clear();
}
return true;
@@ -442,7 +466,7 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
QStringList feedURLs;
if (feedsVal.isString())
feedURLs << feedsVal.toString();
else foreach (const QJsonValue &urlVal, feedsVal.toArray())
else for (const QJsonValue &urlVal : asConst(feedsVal.toArray()))
feedURLs << urlVal.toString();
rule.setFeedURLs(feedURLs);
@@ -452,7 +476,7 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
previouslyMatched << previouslyMatchedVal.toString();
}
else {
foreach (const QJsonValue &val, previouslyMatchedVal.toArray())
for (const QJsonValue &val : asConst(previouslyMatchedVal.toArray()))
previouslyMatched << val.toString();
}
rule.setPreviouslyMatchedEpisodes(previouslyMatched);

View File

@@ -109,7 +109,7 @@ QList<Article *> Feed::articles() const
void Feed::markAsRead()
{
auto oldUnreadCount = m_unreadCount;
foreach (Article *article, m_articles) {
for (Article *article : asConst(m_articles)) {
if (!article->isRead()) {
article->disconnect(this);
article->markAsRead();
@@ -282,9 +282,9 @@ void Feed::loadArticles(const QByteArray &data)
return;
}
QJsonArray jsonArr = jsonDoc.array();
const QJsonArray jsonArr = jsonDoc.array();
int i = -1;
foreach (const QJsonValue &jsonVal, jsonArr) {
for (const QJsonValue &jsonVal : jsonArr) {
++i;
if (!jsonVal.isObject()) {
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()
{
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();
// update legacy keys
hash[Article::KeyLink] = hash.take(QLatin1String("news_link"));
@@ -329,7 +329,7 @@ void Feed::store()
m_savingTimer.stop();
QJsonArray jsonArr;
foreach (Article *article, m_articles)
for (Article *article :asConst(m_articles))
jsonArr << article->toJsonObject();
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);
});
if (sortData.size() > m_session->maxArticlesPerFeed())
if (sortData.size() > static_cast<uint>(m_session->maxArticlesPerFeed()))
sortData.resize(m_session->maxArticlesPerFeed());
int newArticlesCount = 0;
@@ -507,7 +507,7 @@ QJsonValue Feed::toJsonValue(bool withData) const
jsonObj.insert(KEY_HASERROR, hasError());
QJsonArray jsonArr;
for (Article *article : qAsConst(m_articles))
for (Article *article : asConst(m_articles))
jsonArr << article->toJsonObject();
jsonObj.insert(KEY_ARTICLES, jsonArr);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,6 +33,7 @@
#include <QFile>
#include <QHash>
#include "global.h"
#include "logger.h"
#include "profile.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
// 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.
foreach (const QString &key, settings->allKeys())
for (const QString &key : asConst(settings->allKeys()))
data.insert(key, settings->value(key));
return settings->fileName();

View File

@@ -229,7 +229,7 @@ namespace
return QString();
}
#endif
#endif // Q_OS_WIN
}
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()
, [](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
for (const QString &f : deleteFilesList) {
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~`
QDir dir(p);
QStringList tmpFileList = dir.entryList(QDir::Files);
const QStringList tmpFileList = dir.entryList(QDir::Files);
for (const QString &f : tmpFileList) {
if (f.endsWith('~'))
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)
|| (strncmp(buf.f_fstypename, "nfs", sizeof(buf.f_fstypename)) == 0)
|| (strncmp(buf.f_fstypename, "smbfs", sizeof(buf.f_fstypename)) == 0));
#else
#else // Q_OS_WIN
QString file = path;
if (!file.endsWith('/'))
file += '/';
@@ -351,6 +351,6 @@ bool Utils::Fs::isNetworkFileSystem(const QString &path)
default:
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)
#include "base/utils/version.h"
#endif
#endif
#endif // DISABLE_GUI
#include "base/logger.h"
#include "base/unicodestrings.h"
@@ -391,7 +391,7 @@ QString Utils::Misc::getUserIDString()
QStringList Utils::Misc::toStringList(const QList<bool> &l)
{
QStringList ret;
foreach (const bool &b, l)
for (const bool b : l)
ret << (b ? "1" : "0");
return ret;
}
@@ -399,7 +399,7 @@ QStringList Utils::Misc::toStringList(const QList<bool> &l)
QList<int> Utils::Misc::intListfromStringList(const QStringList &l)
{
QList<int> ret;
foreach (const QString &s, l)
for (const QString &s : l)
ret << s.toInt();
return ret;
}
@@ -407,7 +407,7 @@ QList<int> Utils::Misc::intListfromStringList(const QStringList &l)
QList<bool> Utils::Misc::boolListfromStringList(const QStringList &l)
{
QList<bool> ret;
foreach (const QString &s, l)
for (const QString &s : l)
ret << (s == "1");
return ret;
}

View File

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

View File

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

View File

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

View File

@@ -36,6 +36,7 @@
#include <QNetworkInterface>
#include "base/bittorrent/session.h"
#include "base/global.h"
#include "base/preferences.h"
#include "base/unicodestrings.h"
#include "app/application.h"
@@ -83,6 +84,7 @@ enum AdvSettingsRows
#if LIBTORRENT_VERSION_NUM >= 10100
ASYNC_IO_THREADS,
#endif
CHECKING_MEM_USAGE,
// cache
DISK_CACHE,
DISK_CACHE_TTL,
@@ -152,6 +154,8 @@ void AdvancedSettings::saveAdvancedSettings()
// Async IO threads
session->setAsyncIOThreads(spinBoxAsyncIOThreads.value());
#endif
// Checking Memory Usage
session->setCheckingMemUsage(spinBoxCheckingMemUsage.value());
// Disk write cache
session->setDiskCacheSize(spinBoxCache.value());
session->setDiskCacheTTL(spinBoxCacheTTL.value());
@@ -286,13 +290,13 @@ void AdvancedSettings::updateInterfaceAddressCombo()
};
if (ifaceName.isEmpty()) {
foreach (const QHostAddress &ip, QNetworkInterface::allAddresses())
for (const QHostAddress &ip : asConst(QNetworkInterface::allAddresses()))
populateCombo(ip.toString(), ip.protocol());
}
else {
const QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName);
const QList<QNetworkAddressEntry> addresses = iface.addressEntries();
foreach (const QNetworkAddressEntry &entry, addresses) {
for (const QNetworkAddressEntry &entry : addresses) {
const QHostAddress ip = entry.ip();
populateCombo(ip.toString(), ip.protocol());
}
@@ -325,6 +329,13 @@ void AdvancedSettings::loadAdvancedSettings()
spinBoxAsyncIOThreads.setValue(session->asyncIOThreads());
addRow(ASYNC_IO_THREADS, tr("Asynchronous I/O threads"), &spinBoxAsyncIOThreads);
#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
spinBoxCache.setMinimum(-1);
// 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();
bool interfaceExists = currentInterface.isEmpty();
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
// Tested in Qt 5.6.0. For more info see:
// 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);
QLabel labelQbtLink, labelLibtorrentLink;
QSpinBox spinBoxAsyncIOThreads, spinBoxCache, spinBoxSaveResumeDataInterval, spinBoxOutgoingPortsMin, spinBoxOutgoingPortsMax, spinBoxListRefresh, spinBoxMaxHalfOpen,
QSpinBox spinBoxAsyncIOThreads, spinBoxCheckingMemUsage, spinBoxCache, spinBoxSaveResumeDataInterval, spinBoxOutgoingPortsMin, spinBoxOutgoingPortsMax, spinBoxListRefresh, spinBoxMaxHalfOpen,
spinBoxTrackerPort, spinBoxCacheTTL, spinBoxSendBufferWatermark, spinBoxSendBufferLowWatermark,
spinBoxSendBufferWatermarkFactor, spinBoxSavePathHistoryLength;
QCheckBox checkBoxOsCache, checkBoxRecheckCompleted, checkBoxResolveCountries, checkBoxResolveHosts, checkBoxSuperSeeding,

View File

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

View File

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

View File

@@ -231,7 +231,7 @@ void CategoryFilterWidget::removeCategory()
void CategoryFilterWidget::removeUnusedCategories()
{
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)
session->removeCategory(category);
}

View File

@@ -30,6 +30,7 @@
#include <algorithm>
#include "base/global.h"
#include "base/net/downloadmanager.h"
#include "base/settingsstorage.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());
}

View File

@@ -32,6 +32,7 @@
#include <QDateTime>
#include <QPalette>
#include "base/global.h"
#include "guiiconprovider.h"
#include "loglistwidget.h"
#include "ui_executionlogwidget.h"
@@ -52,9 +53,9 @@ ExecutionLogWidget::ExecutionLogWidget(QWidget *parent, const Log::MsgTypes &typ
m_ui->tabBan->layout()->addWidget(m_peerList);
const Logger *const logger = Logger::instance();
foreach (const Log::Msg &msg, logger->getMessages())
for (const Log::Msg &msg : asConst(logger->getMessages()))
addLogMessage(msg);
foreach (const Log::Peer &peer, logger->getPeers())
for (const Log::Peer &peer : asConst(logger->getPeers()))
addPeerMessage(peer);
connect(logger, &Logger::newLogMessage, this, &ExecutionLogWidget::addLogMessage);
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));
}
void FileSystemPathComboEdit::insertItem(int index, const QString& text)
void FileSystemPathComboEdit::insertItem(int index, const QString &text)
{
editWidget<WidgetType>()->insertItem(index, Utils::Fs::toNativePath(text));
}

View File

@@ -1,6 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License
@@ -46,7 +46,7 @@ IPSubnetWhitelistOptionsDialog::IPSubnetWhitelistOptionsDialog(QWidget *parent)
m_ui->setupUi(this);
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);
m_model = new QStringListModel(authSubnetWhitelistStringList, this);
@@ -99,7 +99,7 @@ void IPSubnetWhitelistOptionsDialog::on_buttonWhitelistIPSubnet_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_modified = true;

View File

@@ -1,6 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License

View File

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

View File

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

View File

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

View File

@@ -941,7 +941,7 @@
<item row="3" column="0">
<widget class="QLabel" name="labelCategoryChanged">
<property name="text">
<string>When Category changed:</string>
<string>When Category Save Path changed:</string>
</property>
</widget>
</item>
@@ -2944,28 +2944,6 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</item>
</layout>
</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>
<widget class="QCheckBox" name="checkWebUIUPnP">
<property name="text">
@@ -3177,17 +3155,60 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
</widget>
</item>
<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>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Security</string>
</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>
</item>
<item>

View File

@@ -141,7 +141,7 @@ bool ProgramUpdater::isVersionMoreRecent(const QString &remoteVersion) const
qDebug() << Q_FUNC_INFO << "local version:" << localVersion << "/" << QBT_VERSION;
QStringList remoteParts = remoteVersion.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())
return true;
if (remoteParts[i].toInt() < localParts[i].toInt())

View File

@@ -103,7 +103,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
hideColumn(PeerListDelegate::COUNTRY);
// Ensure that at least one column is visible at all times
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)) {
atLeastOne = true;
break;
@@ -114,7 +114,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
// 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
// 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))
resizeColumnToContents(i);
// Context menu
@@ -169,7 +169,7 @@ void PeerListWidget::displayToggleColumnsMenu(const QPoint &)
actions.append(myAct);
}
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))
++visibleCols;
@@ -248,9 +248,9 @@ void PeerListWidget::showPeerListMenu(const QPoint &)
if (!act) return;
if (act == addPeerAct) {
QList<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this);
const QList<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this);
int peerCount = 0;
foreach (const BitTorrent::PeerAddress &addr, peersList) {
for (const BitTorrent::PeerAddress &addr : peersList) {
if (torrent->connectPeer(addr)) {
qDebug("Adding peer %s...", qUtf8Printable(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);
if (ret) return;
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
foreach (const QModelIndex &index, selectedIndexes) {
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
for (const QModelIndex &index : selectedIndexes) {
int row = m_proxyModel->mapToSource(index).row();
QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString();
qDebug("Banning peer %s...", ip.toLocal8Bit().data());
@@ -298,9 +298,9 @@ void PeerListWidget::banSelectedPeers()
void PeerListWidget::copySelectedPeers()
{
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
QStringList selectedPeers;
foreach (const QModelIndex &index, selectedIndexes) {
for (const QModelIndex &index : selectedIndexes) {
int row = m_proxyModel->mapToSource(index).row();
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();
@@ -321,7 +321,7 @@ void PeerListWidget::clear()
int nbrows = m_listModel->rowCount();
if (nbrows > 0) {
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;
QList<BitTorrent::PeerInfo> peers = torrent->peers();
const QList<BitTorrent::PeerInfo> peers = torrent->peers();
QSet<QString> oldPeersSet = m_peerItems.keys().toSet();
foreach (const BitTorrent::PeerInfo &peer, peers) {
for (const BitTorrent::PeerInfo &peer : peers) {
BitTorrent::PeerAddress addr = peer.address();
if (addr.ip.isNull()) continue;

View File

@@ -31,6 +31,7 @@
#include <QHostAddress>
#include <QMessageBox>
#include "base/global.h"
#include "ui_peersadditiondialog.h"
PeersAdditionDialog::PeersAdditionDialog(QWidget *parent)
@@ -61,7 +62,7 @@ void PeersAdditionDialog::validateInput()
QMessageBox::Ok);
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);
if (!addr.ip.isNull()) {
m_peersList.append(addr);

View File

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

View File

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

View File

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

View File

@@ -33,6 +33,7 @@
#include <QPushButton>
#include <QSpacerItem>
#include "base/global.h"
#include "guiiconprovider.h"
PropTabBar::PropTabBar(QWidget *parent)
@@ -102,7 +103,7 @@ PropTabBar::PropTabBar(QWidget *parent)
connect(m_btnGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked)
, this, &PropTabBar::setCurrentIndex);
// Disable buttons focus
foreach (QAbstractButton *btn, m_btnGroup->buttons())
for (QAbstractButton *btn : asConst(m_btnGroup->buttons()))
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
// draw Y axis speed labels
QVector<QString> speedLabels = {
const QVector<QString> speedLabels = {
formatLabel(niceScale.arg, niceScale.unit),
formatLabel((0.75 * niceScale.arg), niceScale.unit),
formatLabel((0.50 * niceScale.arg), niceScale.unit),
@@ -348,7 +348,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
double legendHeight = 0;
int legendWidth = 0;
for (const auto &property : qAsConst(m_properties)) {
for (const auto &property : asConst(m_properties)) {
if (!property.enable)
continue;
@@ -363,7 +363,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
painter.fillRect(legendBackgroundRect, legendBackgroundColor);
i = 0;
for (const auto &property : qAsConst(m_properties)) {
for (const auto &property : asConst(m_properties)) {
if (!property.enable)
continue;

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,7 @@
#include <QListWidgetItem>
#include "base/global.h"
#include "base/rss/rss_article.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::articleAboutToBeRemoved, this, &ArticleListWidget::handleArticleAboutToBeRemoved);
foreach (auto article, rssItem->articles()) {
for (const auto article : asConst(rssItem->articles())) {
if (!(m_unreadOnly && article->isRead())) {
auto item = createItem(article);
addItem(item);

View File

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

View File

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

View File

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

View File

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

View File

@@ -37,10 +37,6 @@
#include "base/utils/misc.h"
#include "searchsortmodel.h"
namespace
{
const char i18nContext[] = "SearchListDelegate";
}
SearchListDelegate::SearchListDelegate(QObject *parent)
: QItemDelegate(parent)
@@ -63,7 +59,7 @@ void SearchListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
case SearchSortModel::LEECHES:
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
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;
default:
QItemDelegate::paint(painter, option, index);

View File

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

View File

@@ -28,6 +28,8 @@
#include "searchsortmodel.h"
#include "base/global.h"
SearchSortModel::SearchSortModel(QObject *parent)
: base(parent)
, m_isNameFilterEnabled(false)
@@ -126,7 +128,7 @@ bool SearchSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceP
const QAbstractItemModel *const sourceModel = this->sourceModel();
if (m_isNameFilterEnabled && !m_searchTerm.isEmpty()) {
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);
if (i == -1) {
return false;

View File

@@ -49,6 +49,7 @@
#include <QTreeView>
#include "base/bittorrent/session.h"
#include "base/global.h"
#include "base/preferences.h"
#include "base/search/searchpluginmanager.h"
#include "base/search/searchhandler.h"
@@ -166,11 +167,11 @@ void SearchWidget::fillCatCombobox()
using QStrPair = QPair<QString, QString>;
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);
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));
m_ui->comboCategory->addItem(p.first, QVariant(p.second));
}
@@ -188,11 +189,11 @@ void SearchWidget::fillPluginComboBox()
using QStrPair = QPair<QString, QString>;
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);
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));
if (m_ui->selectPlugin->count() > 3)

View File

@@ -32,6 +32,7 @@
#include "base/bittorrent/session.h"
#include "base/bittorrent/sessionstatus.h"
#include "base/bittorrent/torrenthandle.h"
#include "base/global.h"
#include "base/utils/misc.h"
#include "base/utils/string.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)
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();
m_ui->labelWriteStarve->setText(QString("%1%")

View File

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

View File

@@ -35,6 +35,7 @@
#include <QMessageBox>
#include "base/bittorrent/session.h"
#include "base/global.h"
#include "autoexpandabledialog.h"
#include "guiiconprovider.h"
#include "tagfiltermodel.h"
@@ -222,7 +223,7 @@ void TagFilterWidget::removeTag()
void TagFilterWidget::removeUnusedTags()
{
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)
session->removeTag(tag);
updateGeometry();

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