Compare commits

..

54 Commits

Author SHA1 Message Date
sledgehammer999
da0b276d5f Bump to 4.3.3 2021-01-19 00:47:04 +02:00
sledgehammer999
2d73bc9e7d Update Changelog 2021-01-19 00:46:29 +02:00
Chocobo1
fdd54fe568 Simplify code for checking free disk space
`QStorageInfo::bytesAvailable()` is guaranteed to return `-1` for an
invalid path.
https://doc.qt.io/qt-5/qstorageinfo.html#bytesAvailable
2021-01-19 00:45:13 +02:00
Chocobo1
e5ce24e55e Improve detection of file extension string 2021-01-19 00:45:06 +02:00
sledgehammer999
d90349709b Sync translations from Transifex and run lupdate 2021-01-17 23:24:02 +02:00
Vladimir Golovnev (Glassez)
adb0fe6582 WebUI: Correctly represent torrent content structure 2021-01-17 22:50:40 +02:00
Chocobo1
5ed81580c9 Add README.md to searchengine folder 2021-01-17 22:50:39 +02:00
Chocobo1
86d6fb86d7 Unify "github actions" artifacts naming scheme 2021-01-17 22:50:38 +02:00
Chocobo1
ddec247d4f Migrate away from deprecated Qt functions
`QString QDateTime::toString(Qt::DateFormat format = Qt::TextDate)` will
be removed in Qt6.
2021-01-17 22:50:37 +02:00
Chocobo1
d431ecbe00 Disable clang "range loop analysis" compiler warning
See: https://github.com/qbittorrent/qBittorrent/pull/13915#issuecomment-739449084
2021-01-17 22:50:36 +02:00
Chocobo1
be929ed88c Set source character sets to UTF-8
This suppress warning C4819.
https://docs.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-160
2021-01-17 22:50:35 +02:00
Chocobo1
2e1f9bf8be Add script for generating project tarball 2021-01-17 22:50:20 +02:00
lbilli
7fff393b0e On Linux use legacy 'data' directory only as a fallback 2021-01-17 22:47:13 +02:00
sledgehammer999
a669ec49ad Correct copyright attribution
These files were created and edited in their entirety in commit 8db4bde15d
As far as I can tell they were almost entirety rewritten from their original state.
The old copyright attribution is restored and the new author is added too.
2021-01-17 22:47:11 +02:00
Vladimir Golovnev (Glassez)
1880082017 Remove redundant suffix from TorrentHandle class
Originally, it was just a wrapper for libtorrent::torrent_handle class, so it mimicked its name.
It was then transformed into a more complex aggregate, but the name was retained (just by inertia).
Unlike libtorrent::torrent_handle class in whose name "handle" means the pattern used,
it does not matter for qBittorrent classes and just eats up space in the source code.
2021-01-17 22:47:00 +02:00
sledgehammer999
0cbd15890a Merge pull request #14170 from sledgehammer999/use_cxx1z
Use c++1z to enable c++17
2021-01-07 13:40:05 +02:00
sledgehammer999
7fe7c6c277 Use c++1z to enable c++17
It increases compatibility with older qt versions.
2021-01-06 21:54:46 +02:00
jagannatharjun
e4c177fec7 Correctly set items flags in TorrentContentModel
Only set editable flag on item's where editing is handled in the delegate

closes #13515
2021-01-06 21:36:40 +02:00
Chocobo1
77f4e6c2cf Generate version header when configuring project
The basic idea is we create a version header template at
"src/base/version.h.in" and the build systems are expected to replace
strings that are enclosed with @ symbols and generate
"src/base/version.h" for other source files to consume/include.
2021-01-06 21:36:39 +02:00
sledgehammer999
4563b11a2e Bump copyright year 2021-01-06 21:36:37 +02:00
Vladimir Golovnev (Glassez)
cb477f9a29 QMake: Raise minimal macOS target version 2021-01-06 21:36:35 +02:00
Vladimir Golovnev (Glassez)
58ac07667e Use single parameter to accept torrent source 2021-01-06 21:36:34 +02:00
Vladimir Golovnev (Glassez)
74bf3af41c Use std::optional<bool> instead of custom TriStateBool 2021-01-06 21:36:33 +02:00
Vladimir Golovnev (Glassez)
9317071122 Change parseBool() to return optional bool value 2021-01-06 21:36:31 +02:00
Vladimir Golovnev (Glassez)
dab32f2090 Use std::optional instead of boost::optional 2021-01-06 21:36:29 +02:00
Vladimir Golovnev (Glassez)
dc464d4d41 Use nested namespaces definition syntax 2021-01-06 21:36:28 +02:00
Chocobo1
e7e3f6a9db Don't use deprecated locale name 2021-01-06 21:36:27 +02:00
Chocobo1
5a1c4e79b3 Revise store/load state operations of Options Dialog 2021-01-06 21:36:26 +02:00
Chocobo1
c6d9ab6810 Remember dialog sizes
This applies to "About Dialog", "Ban List Options Dialog", "Download From URL Dialog", "IP Subnet
Whitelist Options Dialog", "Search Plugin Select Dialog", "Search Plugin Source Dialog",
"Statistics Dialog", "Speed Limit Dialog" and "Torrent Options Dialog".

Also unifies storing the dialog size under the key "Size".
2021-01-06 21:36:24 +02:00
Chocobo1
d7afad835e Revise SettingsStorage store/load value interface 2021-01-06 21:36:22 +02:00
Chocobo1
8608d7b9da Improve load data behavior of SettingsStorage class
Previously it only handle the case of failed lookup, now it discard
invalid values when deserializing the database from disk.
Also checks whether the data is convertible to the intended type.
2021-01-06 21:36:22 +02:00
Vladimir Golovnev (Glassez)
72970602af Reload "missing files" torrent instead of re-checking 2021-01-06 21:36:20 +02:00
Vladimir Golovnev (Glassez)
86579ca87d Extract torrent reloading logic into separate method 2021-01-06 21:36:19 +02:00
Vladimir Golovnev (Glassez)
e55582124c Drop notification about move storage failed 2021-01-06 21:36:17 +02:00
Vladimir Golovnev (Glassez)
bd8b06c607 Drop notification about move storage finished 2021-01-06 21:36:16 +02:00
Chocobo1
230fedf069 Move parsing of TriStateBool to a static class function 2021-01-06 21:36:14 +02:00
thalieht
7bea10f507 Update "Keep top-level folder" in WebUI options 2021-01-06 21:36:13 +02:00
Chocobo1
7cde969b90 Exclude configure script for "trailing newlines" checking 2021-01-06 21:36:12 +02:00
Chocobo1
a3b8f6880b Migrate away from deprecated AC_OUTPUT macro
The `AC_OUTPUT` has two versions, the deprecated one takes arguments and the other not. Check the
following link for equivalent replacement:
https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.70/html_node/Obsolete-Macros.html#Obsolete-Macros

Also regenerate the configure script with the latest Autoconf 2.70.
2021-01-06 21:35:33 +02:00
Chocobo1
ad79fc8d43 Migrate away from deprecated std::iterator class 2021-01-06 21:31:51 +02:00
Chocobo1
fb4bf94a56 Use function-pointer based signal-slot connection 2021-01-06 21:31:50 +02:00
Chocobo1
1c184944fd Remove unused define 2021-01-06 21:31:49 +02:00
Chocobo1
ec420f6617 Bump project requirement to C++17 2021-01-06 21:31:47 +02:00
Chocobo1
d908227619 Add a thin layer around SettingsStorage class
This new layer would be handy for saving GUI widget states as they don't
need the value cached and they store/load rarely.
2021-01-06 21:31:45 +02:00
sledgehammer999
ac8167410b Add new languages
* Azerbaijani
* Estonian
2021-01-06 21:31:44 +02:00
Vladimir Golovnev (Glassez)
26ce187b30 Don't call non-existent elements
Fixed a regression where the script tries to access elements that no longer
exist on the page, because they were replaced with others by a previous change.
2021-01-06 21:31:43 +02:00
Vladimir Golovnev (Glassez)
2c4e04e537 Don't call non-existent elements
Fixed a regression where the script tries to access elements that no longer
exist on the page, because they were replaced with others by a previous change.
2021-01-06 21:31:42 +02:00
Vladimir Golovnev (Glassez)
b418f65c2f Improve content file/folder names handling
Move files/folders renaming functions to core classes.
Query file/folder for renaming by its current path.
Add ability to rename content folders from WebAPI/WebUI.
2021-01-06 21:31:41 +02:00
Vladimir Golovnev (Glassez)
dd3a8d5d56 Fix folder name extraction functions
It should return empty string if there is no parent folder.
2021-01-06 21:31:39 +02:00
Chocobo1
49e54a55df Capitalize locale names 2021-01-06 21:31:38 +02:00
thalieht
8cd0a7ae85 Group several torrent options into one dialog
Speed limits, share limits and the new options to disable DHT, PeX, LSD per torrent
2021-01-06 21:31:36 +02:00
thalieht
442f0df613 Save fastresume when setting torrent speed limits 2021-01-06 21:31:35 +02:00
thalieht
f9ee5bdb59 Increase maximum global speed limits from ~1 GiB/s to ~2 GiB/s
Closer to the INT_MAX limit of ~2 Billion when multiplied by 1024 for libtorrent
2021-01-06 21:31:33 +02:00
thalieht
b9602cc6ab Convert existing speed dialog to global + alt global limits only 2021-01-06 21:31:25 +02:00
283 changed files with 78562 additions and 43463 deletions

View File

@@ -72,7 +72,7 @@ jobs:
- name: upload artifact as zip
uses: actions/upload-artifact@v2
with:
name: qBittorrent-CI-Ubuntu_${{ matrix.os }}-${{ matrix.qbt_gui }}
name: qBittorrent-CI_${{ matrix.os }}-x64_${{ matrix.qbt_gui }}
path: |
build/compile_commands.json
build/target_graph.dot
@@ -151,7 +151,7 @@ jobs:
- name: upload artifact as zip
uses: actions/upload-artifact@v2
with:
name: qBittorrent-CI-Windows_x64-static-release
name: qBittorrent-CI_Windows-x64
path: |
build/compile_commands.json
build/target_graph.dot
@@ -200,10 +200,10 @@ jobs:
-Value "set(VCPKG_BUILD_TYPE release)","set(VCPKG_OSX_DEPLOYMENT_TARGET 10.15)"
# NOTE: Avoids a libtorrent ABI issue. See https://github.com/arvidn/libtorrent/issues/4965
- name: force AppleClang to compile libtorrent with C++14
- name: force AppleClang to compile libtorrent with C++17
run: |
(Get-Content -path ${{ env.RUNVCPKG_VCPKG_ROOT }}/ports/libtorrent/portfile.cmake).Replace( `
'${FEATURE_OPTIONS}', '${FEATURE_OPTIONS} -DCMAKE_CXX_STANDARD=14') `
'${FEATURE_OPTIONS}', '${FEATURE_OPTIONS} -DCMAKE_CXX_STANDARD=17') `
| Set-Content -Path ${{ env.RUNVCPKG_VCPKG_ROOT }}/ports/libtorrent/portfile.cmake
- name: install dependencies via vcpkg
@@ -236,7 +236,7 @@ jobs:
- name: upload artifact as zip
uses: actions/upload-artifact@v2
with:
name: qBittorrent-CI-macOS_x64-static-release_${{ matrix.qbt_gui }}
name: qBittorrent-CI_macOS_${{ matrix.qbt_gui }}
path: |
build/compile_commands.json
build/target_graph.dot

View File

@@ -12,6 +12,7 @@ regressions=0
exclusions_nonutf8='(.*(7z|gif|ic(ns|o)|png|qm|zip))'
exclusions_bom='src/base/unicodestrings.h'
exclusions_tw='(*.ts)|src/webui/www/private/scripts/lib/mootools-1.2-more.js'
exclusions_trailing_newline='configure'
exclusions_no_lf='(*.ts)|(.*svg)|compile_commands.json|src/webui/www/private/scripts/lib/mootools-1.2-(core-yc.js|more.js)'
echo -e "\n*** Detect files not encoded in UTF-8 ***\n"
@@ -50,6 +51,7 @@ echo -e "\n*** Detect too many trailing newlines ***\n"
find . -path ./build -prune -false -o -path ./.git -prune -false -o -type f -exec file --mime {} \; | sort \
| grep -e "charset=us-ascii" -e "charset=utf-8" | cut -d ":" -f 1 \
| grep -E -v -e "${exclusions_trailing_newline}" \
| xargs -L1 -I my_input bash -c 'test "$(tail -q -c2 "my_input" | hexdump -C | grep "0a 0a")" && echo "my_input"' \
| tee >(echo -e "--> Too many trailing newlines: found" "$(wc -l < /dev/stdin)" "regression(s)\n") \
| xargs -I my_input -0 bash -c 'echo "my_input"; test "$(echo -n "my_input" | wc -l)" -eq 0'

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@ src/qbittorrent
src/qbittorrent-nox
src/release
src/debug
src/base/version.h
CMakeLists.txt.user*
qbittorrent.pro.user*
conf.pri

View File

@@ -129,7 +129,7 @@ install:
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=14 \
-DCMAKE_CXX_STANDARD=17 \
-Ddeprecated-functions=OFF \
-DOPENSSL_ROOT_DIR="$openssl_root_path" \
./
@@ -145,7 +145,7 @@ install:
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=14 \
-DCMAKE_CXX_STANDARD=17 \
-Ddeprecated-functions=ON \
-DOPENSSL_ROOT_DIR="$openssl_root_path" \
./

View File

@@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR) # Policies <= CMP0097 default t
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
project(qBittorrent
VERSION 4.3.2.0
DESCRIPTION "The qBittorrent BitTorrent client"
HOMEPAGE_URL "https://www.qbittorrent.org/"
LANGUAGES CXX
@@ -51,8 +50,6 @@ elseif (MSVC)
feature_option(MSVC_RUNTIME_DYNAMIC "Use MSVC dynamic runtime library (-MD) instead of static (-MT)" ON)
endif()
set(QBT_VER_STATUS "alpha1" CACHE STRING "Project status version. Should be empty for release builds.")
include(GNUInstallDirs)
add_subdirectory(src)
add_subdirectory(dist)
@@ -62,3 +59,7 @@ if (VERBOSE_CONFIGURE)
else()
feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
endif()
# Generate version header
file(READ "src/base/version.h.in" versionHeader)
file(WRITE "src/base/version.h" "${versionHeader}")

View File

@@ -1,3 +1,21 @@
Tue Jan 19 2021 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.3
- FEATURE: New languages: Azerbaijani, Estonian
- BUGFIX: Unify global speed dialogs for normal/alternative speeds (thalieht)
- BUGFIX: Increase maximum global speed limits ~2 GiB/s (thalieht)
- BUGFIX: Save fastresume when setting torrent speed limits (thalieht)
- BUGFIX: Group several torrent options into one dialog (thalieht)
- BUGFIX: Capitalize locale names (Chocobo1)
- BUGFIX: Improve content file/folder names handling (glassez)
- BUGFIX: Drop notification about move storage finished or failed (glassez)
- BUGFIX: Reload "missing files" torrent instead of re-checking (glassez)
- BUGFIX: Remember dialog sizes (Chocobo1)
- BUGFIX: Improve detection of file extension string (Chocobo1)
- WEBUI: Don't call non-existent elements (glassez)
- WEBUI: Update "Keep top-level folder" in WebUI options (thalieht)
- MACOS: QMake: Raise minimal macOS target version to 10.14 (glassez)
- LINUX: Use legacy 'data' directory only as a fallback (lbilli)
- OTHER: Bump project requirement to C++17 (Chocobo1)
Sun Dec 27 2020 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.3.2
- FEATURE: Allow to add root folder to torrent content (glassez)
- FEATURE: "HTTPS tracker validation" option is available on all platforms with latest libtorrent (Chocobo1)

19
build_dist.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
# get version numbers
versionSrc="src/base/version.h.in"
versionMajor="$(grep -Po '(?<=QBT_VERSION_MAJOR )\d+' "$versionSrc")"
versionMinor="$(grep -Po '(?<=QBT_VERSION_MINOR )\d+' "$versionSrc")"
versionBugfix="$(grep -Po '(?<=QBT_VERSION_BUGFIX )\d+' "$versionSrc")"
versionBuild="$(grep -Po '(?<=QBT_VERSION_BUILD )\d+' "$versionSrc")"
versionStatus="$(grep -Po '(?<=QBT_VERSION_STATUS ")\w+' "$versionSrc")"
if [ "$versionBuild" != "0" ]; then
projectVersion="$versionMajor.$versionMinor.$versionBugfix.$versionBuild$versionStatus"
else
projectVersion="$versionMajor.$versionMinor.$versionBugfix$versionStatus"
fi
# pack archives
git archive --format=tar --prefix="qbittorrent-$projectVersion/" HEAD | gzip -9 > "qbittorrent-$projectVersion.tar.gz"
git archive --format=tar --prefix="qbittorrent-$projectVersion/" HEAD | xz -9 > "qbittorrent-$projectVersion.tar.xz"

View File

@@ -7,47 +7,16 @@ macro(qbt_common_config)
# treat value specified by the CXX_STANDARD target property as a requirement by default
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# these definitions are only needed for calls to
# lt::generate_fingerprint and for the qbittorrent.rc file on Windows
add_library(qbt_version_definitions INTERFACE)
target_compile_definitions(qbt_version_definitions INTERFACE
QBT_VERSION_MAJOR=${qBittorrent_VERSION_MAJOR}
QBT_VERSION_MINOR=${qBittorrent_VERSION_MINOR}
QBT_VERSION_BUGFIX=${qBittorrent_VERSION_PATCH}
QBT_VERSION_BUILD=${qBittorrent_VERSION_TWEAK}
)
add_library(qbt_common_cfg INTERFACE)
# Full C++ 14 support is required
# Full C++ 17 support is required
# See also https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html
# for a breakdown of the features that CMake recognizes for each C++ standard
target_compile_features(qbt_common_cfg INTERFACE
cxx_std_14
cxx_aggregate_default_initializers
cxx_attribute_deprecated
cxx_binary_literals
cxx_contextual_conversions
cxx_decltype_auto
cxx_digit_separators
cxx_generic_lambdas
cxx_lambda_init_captures
cxx_relaxed_constexpr
cxx_return_type_deduction
cxx_variable_templates
cxx_std_17
)
set(QBT_PROJECT_VERSION "${qBittorrent_VERSION_MAJOR}.${qBittorrent_VERSION_MINOR}.${qBittorrent_VERSION_PATCH}")
if (NOT ${qBittorrent_VERSION_TWEAK} EQUAL 0)
set(QBT_PROJECT_VERSION "${QBT_PROJECT_VERSION}.${qBittorrent_VERSION_TWEAK}")
endif()
set(QBT_FULL_VERSION "${QBT_PROJECT_VERSION}${QBT_VER_STATUS}")
target_compile_definitions(qbt_common_cfg INTERFACE
QBT_VERSION="v${QBT_FULL_VERSION}"
QBT_VERSION_2="${QBT_FULL_VERSION}"
QT_DEPRECATED_WARNINGS
QT_NO_CAST_TO_ASCII
QT_NO_CAST_FROM_BYTEARRAY
@@ -90,6 +59,12 @@ macro(qbt_common_config)
endif()
endif()
if ((CXX_COMPILER_ID STREQUAL "Clang") OR (CXX_COMPILER_ID STREQUAL "AppleClang"))
target_compile_options(qbt_common_cfg INTERFACE
-Wno-range-loop-analysis
)
endif()
if (MINGW)
target_link_options(qbt_common_cfg INTERFACE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:LINKER:--dynamicbase>)
endif()
@@ -101,8 +76,12 @@ macro(qbt_common_config)
endif()
if (MSVC)
target_compile_options(qbt_common_cfg INTERFACE /guard:cf)
target_link_options(qbt_common_cfg INTERFACE /guard:cf
target_compile_options(qbt_common_cfg INTERFACE
/guard:cf
/utf-8
)
target_link_options(qbt_common_cfg INTERFACE
/guard:cf
$<$<NOT:$<CONFIG:Debug>>:/OPT:REF /OPT:ICF>
# suppress linking warning due to /INCREMENTAL and /OPT:ICF being both ON
$<$<CONFIG:RelWithDebInfo>:/INCREMENTAL:NO>

4906
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
AC_INIT([qbittorrent], [v4.3.2], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_INIT([qbittorrent], [v4.3.3], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
: ${CFLAGS=""}
@@ -194,34 +194,34 @@ PKG_CHECK_MODULES(zlib,
[CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
LIBS="$zlib_LIBS $LIBS"])
# Check if already in >= C++14 mode because of the flags returned by one of the above packages
# Check if already in >= C++17 mode because of the flags returned by one of the above packages
TMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=""
AC_MSG_CHECKING([if compiler defaults to C++14 or later mode])
AC_COMPILE_IFELSE([DETECT_CPP14_PROGRAM()],
AC_MSG_CHECKING([if compiler defaults to C++17 or later mode])
AC_COMPILE_IFELSE([DETECT_CPP17_PROGRAM()],
[AC_MSG_RESULT([yes])
QBT_CXX14_FOUND="yes"],
QBT_CXX17_FOUND="yes"],
[AC_MSG_RESULT([no])
QBT_CXX14_FOUND="no"])
QBT_CXX17_FOUND="no"])
# In case of no, check if the compiler can support at least C++14
# In case of no, check if the compiler can support at least C++17
# and if yes, enable it leaving a warning to the user
AS_IF([test "x$QBT_CXX14_FOUND" = "xno"],
[AC_MSG_CHECKING([if compiler supports C++14])
CXXFLAGS="-std=c++14"
AC_COMPILE_IFELSE([DETECT_CPP14_PROGRAM()],
AS_IF([test "x$QBT_CXX17_FOUND" = "xno"],
[AC_MSG_CHECKING([if compiler supports C++17])
CXXFLAGS="-std=c++17"
AC_COMPILE_IFELSE([DETECT_CPP17_PROGRAM()],
[AC_MSG_RESULT([yes])
AC_MSG_CHECKING([if C++14 is disabled by the set compiler flags])
AC_MSG_CHECKING([if C++17 is disabled by the set compiler flags])
# prepend the flag so it won't override conflicting user defined flags
CXXFLAGS="-std=c++14 $TMP_CXXFLAGS"
AC_COMPILE_IFELSE([DETECT_CPP14_PROGRAM()],
CXXFLAGS="-std=c++17 $TMP_CXXFLAGS"
AC_COMPILE_IFELSE([DETECT_CPP17_PROGRAM()],
[AC_MSG_RESULT([no])
QBT_ADD_CONFIG="$QBT_ADD_CONFIG c++14"
AC_MSG_WARN([C++14 mode is now force enabled. The C++ mode should match the mode that other libraries were built with, otherwise you'll likely get linking errors.])],
QBT_ADD_CONFIG="$QBT_ADD_CONFIG c++1z"
AC_MSG_WARN([C++17 mode is now force enabled. The C++ mode should match the mode that other libraries were built with, otherwise you'll likely get linking errors.])],
[AC_MSG_RESULT([yes])
AC_MSG_ERROR([The compiler supports C++14 but the user or a dependency has explicitly enabled a lower mode.])])],
AC_MSG_ERROR([The compiler supports C++17 but the user or a dependency has explicitly enabled a lower mode.])])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([A compiler supporting C++14 is required.])])
AC_MSG_ERROR([A compiler supporting C++17 is required.])])
])
CXXFLAGS="$TMP_CXXFLAGS"
@@ -272,9 +272,13 @@ AC_SUBST(QBT_REMOVE_CONFIG)
AC_SUBST(QBT_ADD_DEFINES)
AC_SUBST(QBT_REMOVE_DEFINES)
AC_OUTPUT(conf.pri)
QBT_CONFIG_FILES="conf.pri"
AS_IF([test "x$enable_systemd" = "xyes"],
[AC_OUTPUT(dist/unix/systemd/qbittorrent-nox@.service)])
[QBT_CONFIG_FILES="$QBT_CONFIG_FILES dist/unix/systemd/qbittorrent-nox@.service"])
AC_CONFIG_FILES(["$QBT_CONFIG_FILES"])
AC_OUTPUT
AC_MSG_NOTICE([Running qmake to generate the makefile...])
TOPDIR="$(cd "$(dirname "$0")" && pwd)"

4
dist/mac/Info.plist vendored
View File

@@ -55,7 +55,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>4.3.2</string>
<string>4.3.3</string>
<key>CFBundleExecutable</key>
<string>@EXECUTABLE@</string>
<key>CFBundleIdentifier</key>
@@ -67,7 +67,7 @@
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2006-2020 The qBittorrent project</string>
<string>Copyright © 2006-2021 The qBittorrent project</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>

View File

@@ -74,6 +74,6 @@
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
<content_rating type="oars-1.1"/>
<releases>
<release version="4.3.2" date="2020-12-27"/>
<release version="4.3.3" date="2021-01-19"/>
</releases>
</component>

View File

@@ -12,6 +12,9 @@ StartupNotify=false
StartupWMClass=qbittorrent
Keywords=bittorrent;torrent;magnet;download;p2p;
# Translations
# Translations
Comment[oc]=Telecargar e partejar de fichièrs amb BitTorrent
GenericName[oc]=Client BitTorrent
@@ -85,6 +88,9 @@ Name[hr]=qBittorrent
Comment[hu]=Fájlok letöltése és megosztása a BitTorrent hálózaton keresztül
GenericName[hu]=BitTorrent kliens
Name[hu]=qBittorrent
Comment[hy]=Նիշքերի փոխանցում BitTorrent-ի միջոցով
GenericName[hy]=BitTorrent սպասառու
Name[hy]=qBittorrent
Comment[id]=Unduh dan berbagi berkas melalui BitTorrent
GenericName[id]=Klien BitTorrent
Name[id]=qBittorrent
@@ -100,8 +106,8 @@ Name[ja]=qBittorrent
Comment[ka]=ჩამოტვირთე და გააზიარე ფაილები Bittorrent-ის საშუალებით
GenericName[ka]=BitTorrent კლიენტი
Name[ka]=qBittorrent
Comment[ko]=비트토트를 통해 파일을 받고 공유합니다
GenericName[ko]=비트토트 클라이언트
Comment[ko]=비트토트를 통해 파일을 받고 공유합니다
GenericName[ko]=비트토트 클라이언트
Name[ko]=qBittorrent
Comment[zh]=通过 BitTorrent 下载和分享文件
GenericName[zh]=BitTorrent 客户端
@@ -189,8 +195,8 @@ Name[ms_MY]=qBittorrent
Comment[eo]=Elŝutu kaj kunhavigu dosierojn per BitTorrent
GenericName[eo]=BitTorrent-kliento
Name[eo]=qBittorrent
Comment[mn_MN]=BitTorrent ашиглан файлуудыг татаж түгээх
GenericName[mn_MN]=BitTorrent үйлчлүүлэгч
Comment[mn_MN]=BitTorrent-оор файлуудаа тат, түгээ
GenericName[mn_MN]=BitTorrent татагч
Name[mn_MN]=qBittorrent
Comment[ta]=BitTorrent வழியாக கோப்புகளை பதிவிறக்க மற்றும் பகிர
GenericName[ta]=BitTorrent வாடிக்கையாளர்

View File

@@ -28,7 +28,7 @@ XPStyle on
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
; Program specific
!define PROG_VERSION "4.3.2"
!define PROG_VERSION "4.3.3"
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
@@ -51,7 +51,7 @@ XPStyle on
;Installer Version Information
VIAddVersionKey "ProductName" "qBittorrent"
VIAddVersionKey "CompanyName" "The qBittorrent project"
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2020 The qBittorrent project"
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2021 The qBittorrent project"
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
VIAddVersionKey "FileVersion" "${PROG_VERSION}"

View File

@@ -37,15 +37,15 @@ AC_DEFUN([FIND_QTDBUS],
HAVE_QTDBUS=[false]])
])
# DETECT_CPP14_PROGRAM()
# Detects if at least C++14 mode is enabled.
# DETECT_CPP17_PROGRAM()
# Detects if at least C++17 mode is enabled.
# --------------------------------------
AC_DEFUN([DETECT_CPP14_PROGRAM],
AC_DEFUN([DETECT_CPP17_PROGRAM],
[AC_LANG_PROGRAM([[
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201402L
#error "This is not a C++14 compiler"
#elif __cplusplus < 201703L
#error "This is not a C++17 compiler"
#endif]],
[[]])
])

View File

@@ -7,6 +7,8 @@ else {
include(conf.pri)
}
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
LIBS += -framework Carbon -framework IOKit -framework AppKit
QT_LANG_PATH = ../dist/qt-translations

View File

@@ -4,19 +4,6 @@ SUBDIRS += src
include(version.pri)
# Make target to create release tarball. Use 'make tarball'
tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ &&
tarball.commands += git clone . ../$${PROJECT_NAME}-$${PROJECT_VERSION} &&
tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.git &&
tarball.commands += rm -f ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.gitignore &&
tarball.commands += cd .. &&
tarball.commands += tar czf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar.gz $${PROJECT_NAME}-$${PROJECT_VERSION} &&
tarball.commands += tar cf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar $${PROJECT_NAME}-$${PROJECT_VERSION} &&
tarball.commands += xz -f $${PROJECT_NAME}-$${PROJECT_VERSION}.tar &&
tarball.commands += rm -fR $${PROJECT_NAME}-$${PROJECT_VERSION}
QMAKE_EXTRA_TARGETS += tarball
# For Qt Creator beautifier
DISTFILES += \
uncrustify.cfg

View File

@@ -61,7 +61,6 @@ target_sources(qbt_app PRIVATE
target_link_libraries(qbt_app PRIVATE
qbt_base
qbt_version_definitions
)
set_target_properties(qbt_app PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")

View File

@@ -63,7 +63,7 @@
#include "base/bittorrent/infohash.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/torrent.h"
#include "base/exceptions.h"
#include "base/iconprovider.h"
#include "base/logger.h"
@@ -81,6 +81,7 @@
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/utils/string.h"
#include "base/version.h"
#include "applicationinstancemanager.h"
#include "filelogger.h"
@@ -214,7 +215,7 @@ const QBtCommandLineParameters &Application::commandLineArgs() const
bool Application::isFileLoggerEnabled() const
{
return settings()->loadValue(KEY_FILELOGGER_ENABLED, true).toBool();
return settings()->loadValue(KEY_FILELOGGER_ENABLED, true);
}
void Application::setFileLoggerEnabled(const bool value)
@@ -228,8 +229,8 @@ void Application::setFileLoggerEnabled(const bool value)
QString Application::fileLoggerPath() const
{
return settings()->loadValue(KEY_FILELOGGER_PATH,
{specialFolderLocation(SpecialFolder::Data) + LOG_FOLDER}).toString();
return settings()->loadValue(KEY_FILELOGGER_PATH
, QString {specialFolderLocation(SpecialFolder::Data) + LOG_FOLDER});
}
void Application::setFileLoggerPath(const QString &path)
@@ -241,7 +242,7 @@ void Application::setFileLoggerPath(const QString &path)
bool Application::isFileLoggerBackup() const
{
return settings()->loadValue(KEY_FILELOGGER_BACKUP, true).toBool();
return settings()->loadValue(KEY_FILELOGGER_BACKUP, true);
}
void Application::setFileLoggerBackup(const bool value)
@@ -253,7 +254,7 @@ void Application::setFileLoggerBackup(const bool value)
bool Application::isFileLoggerDeleteOld() const
{
return settings()->loadValue(KEY_FILELOGGER_DELETEOLD, true).toBool();
return settings()->loadValue(KEY_FILELOGGER_DELETEOLD, true);
}
void Application::setFileLoggerDeleteOld(const bool value)
@@ -265,7 +266,7 @@ void Application::setFileLoggerDeleteOld(const bool value)
int Application::fileLoggerMaxSize() const
{
const int val = settings()->loadValue(KEY_FILELOGGER_MAXSIZEBYTES, DEFAULT_FILELOG_SIZE).toInt();
const int val = settings()->loadValue(KEY_FILELOGGER_MAXSIZEBYTES, DEFAULT_FILELOG_SIZE);
return std::min(std::max(val, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
}
@@ -279,7 +280,7 @@ void Application::setFileLoggerMaxSize(const int bytes)
int Application::fileLoggerAge() const
{
const int val = settings()->loadValue(KEY_FILELOGGER_AGE, 1).toInt();
const int val = settings()->loadValue(KEY_FILELOGGER_AGE, 1);
return std::min(std::max(val, 1), 365);
}
@@ -290,7 +291,7 @@ void Application::setFileLoggerAge(const int value)
int Application::fileLoggerAgeType() const
{
const int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1).toInt();
const int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1);
return ((val < 0) || (val > 2)) ? 1 : val;
}
@@ -310,7 +311,7 @@ void Application::processMessage(const QString &message)
m_paramsQueue.append(params);
}
void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) const
void Application::runExternalProgram(const BitTorrent::Torrent *torrent) const
{
QString program = Preferences::instance()->getAutoRunProgram().trimmed();
program.replace("%N", torrent->name());
@@ -404,7 +405,7 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
#endif
}
void Application::sendNotificationEmail(const BitTorrent::TorrentHandle *torrent)
void Application::sendNotificationEmail(const BitTorrent::Torrent *torrent)
{
// Prepare mail content
const QString content = tr("Torrent name: %1").arg(torrent->name()) + '\n'
@@ -423,7 +424,7 @@ void Application::sendNotificationEmail(const BitTorrent::TorrentHandle *torrent
content);
}
void Application::torrentFinished(BitTorrent::TorrentHandle *const torrent)
void Application::torrentFinished(BitTorrent::Torrent *const torrent)
{
Preferences *const pref = Preferences::instance();
@@ -505,7 +506,7 @@ void Application::processParams(const QStringList &params)
}
#endif
BitTorrent::AddTorrentParams torrentParams;
TriStateBool skipTorrentDialog;
std::optional<bool> skipTorrentDialog;
for (QString param : params)
{
@@ -521,7 +522,7 @@ void Application::processParams(const QStringList &params)
if (param.startsWith(QLatin1String("@addPaused=")))
{
torrentParams.addPaused = param.midRef(11).toInt() ? TriStateBool::True : TriStateBool::False;
torrentParams.addPaused = (param.midRef(11).toInt() != 0);
continue;
}
@@ -551,7 +552,7 @@ void Application::processParams(const QStringList &params)
if (param.startsWith(QLatin1String("@skipDialog=")))
{
skipTorrentDialog = param.midRef(12).toInt() ? TriStateBool::True : TriStateBool::False;
skipTorrentDialog = (param.midRef(12).toInt() != 0);
continue;
}
@@ -561,9 +562,7 @@ void Application::processParams(const QStringList &params)
// be shown and skipTorrentDialog is undefined. The other is when
// skipTorrentDialog is false, meaning that the application setting
// should be overridden.
const bool showDialogForThisTorrent =
((AddNewTorrentDialog::isEnabled() && skipTorrentDialog == TriStateBool::Undefined)
|| skipTorrentDialog == TriStateBool::False);
const bool showDialogForThisTorrent = !skipTorrentDialog.value_or(!AddNewTorrentDialog::isEnabled());
if (showDialogForThisTorrent)
AddNewTorrentDialog::show(param, torrentParams, m_window);
else

View File

@@ -59,7 +59,7 @@ class FileLogger;
namespace BitTorrent
{
class TorrentHandle;
class Torrent;
}
namespace RSS
@@ -112,7 +112,7 @@ protected:
private slots:
void processMessage(const QString &message);
void torrentFinished(BitTorrent::TorrentHandle *const torrent);
void torrentFinished(BitTorrent::Torrent *const torrent);
void allTorrentsFinished();
void cleanup();
#if (!defined(DISABLE_GUI) && defined(Q_OS_WIN))
@@ -142,6 +142,6 @@ private:
void initializeTranslation();
void processParams(const QStringList &params);
void runExternalProgram(const BitTorrent::TorrentHandle *torrent) const;
void sendNotificationEmail(const BitTorrent::TorrentHandle *torrent);
void runExternalProgram(const BitTorrent::Torrent *torrent) const;
void sendNotificationEmail(const BitTorrent::Torrent *torrent);
};

View File

@@ -254,13 +254,13 @@ namespace
return padUsageText(fullParameter() + QLatin1String("=<true|false>"));
}
TriStateBool value(const QString &arg) const
std::optional<bool> value(const QString &arg) const
{
QStringList parts = arg.split(QLatin1Char('='));
if (parts.size() == 1)
{
return TriStateBool(m_defaultValue);
return m_defaultValue;
}
if (parts.size() == 2)
{
@@ -268,11 +268,11 @@ namespace
if ((val.toUpper() == QLatin1String("TRUE")) || (val == QLatin1String("1")))
{
return TriStateBool::True;
return true;
}
if ((val.toUpper() == QLatin1String("FALSE")) || (val == QLatin1String("0")))
{
return TriStateBool::False;
return false;
}
}
@@ -282,30 +282,30 @@ namespace
.arg(fullParameter(), QLatin1String("<true|false>")));
}
TriStateBool value(const QProcessEnvironment &env) const
std::optional<bool> value(const QProcessEnvironment &env) const
{
const QString val = env.value(envVarName(), "-1");
if (val.isEmpty())
{
return TriStateBool(m_defaultValue);
return m_defaultValue;
}
if (val == QLatin1String("-1"))
{
return TriStateBool::Undefined;
return std::nullopt;
}
if ((val.toUpper() == QLatin1String("TRUE")) || (val == QLatin1String("1")))
{
return TriStateBool::True;
return true;
}
if ((val.toUpper() == QLatin1String("FALSE")) || (val == QLatin1String("0")))
{
return TriStateBool::False;
return false;
}
qDebug() << QObject::tr("Expected %1 in environment variable '%2', but got '%3'")
.arg(QLatin1String("true|false"), envVarName(), val);
return TriStateBool::Undefined;
return std::nullopt;
}
bool m_defaultValue;
@@ -374,14 +374,8 @@ QStringList QBtCommandLineParameters::paramList() const
if (!savePath.isEmpty())
result.append(QLatin1String("@savePath=") + savePath);
if (addPaused == TriStateBool::True)
{
result.append(QLatin1String("@addPaused=1"));
}
else if (addPaused == TriStateBool::False)
{
result.append(QLatin1String("@addPaused=0"));
}
if (addPaused.has_value())
result.append(*addPaused ? QLatin1String {"@addPaused=1"} : QLatin1String {"@addPaused=0"});
if (skipChecking)
result.append(QLatin1String("@skipChecking"));
@@ -395,14 +389,8 @@ QStringList QBtCommandLineParameters::paramList() const
if (firstLastPiecePriority)
result.append(QLatin1String("@firstLastPiecePriority"));
if (skipDialog == TriStateBool::True)
{
result.append(QLatin1String("@skipDialog=1"));
}
else if (skipDialog == TriStateBool::False)
{
result.append(QLatin1String("@skipDialog=0"));
}
if (skipDialog.has_value())
result.append(*skipDialog ? QLatin1String {"@skipDialog=1"} : QLatin1String {"@skipDialog=0"});
result += torrents;
return result;

View File

@@ -30,13 +30,12 @@
#pragma once
#include <optional>
#include <stdexcept>
#include <QString>
#include <QStringList>
#include "base/tristatebool.h"
class QProcessEnvironment;
struct QBtCommandLineParameters
@@ -55,8 +54,8 @@ struct QBtCommandLineParameters
bool shouldDaemonize;
#endif
int webUiPort;
TriStateBool addPaused;
TriStateBool skipDialog;
std::optional<bool> addPaused;
std::optional<bool> skipDialog;
QStringList torrents;
QString profileDir;
QString configurationName;

View File

@@ -78,6 +78,7 @@ Q_IMPORT_PLUGIN(QICOPlugin)
#include "base/preferences.h"
#include "base/profile.h"
#include "base/version.h"
#include "application.h"
#include "cmdoptions.h"
#include "upgrade.h"

View File

@@ -152,7 +152,7 @@ bool QtLocalPeer::isClient()
#endif
if (!res)
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection);
return false;
}

View File

@@ -32,6 +32,7 @@
#include <QString>
#include "base/utils/misc.h"
#include "base/version.h"
#include "ui_stacktracedialog.h"
StacktraceDialog::StacktraceDialog(QWidget *parent)

View File

@@ -46,8 +46,8 @@ namespace
const auto migrate = [](const QString &oldKey, const QString &newKey, const QString &savePath)
{
SettingsStorage *settingsStorage {SettingsStorage::instance()};
const QByteArray oldData {settingsStorage->loadValue(oldKey).toByteArray()};
const QString newData {settingsStorage->loadValue(newKey).toString()};
const auto oldData {settingsStorage->loadValue<QByteArray>(oldKey)};
const auto newData {settingsStorage->loadValue<QString>(newKey)};
const QString errorMsgFormat {QObject::tr("Migrate preferences failed: WebUI https, file: \"%1\", error: \"%2\"")};
if (!newData.isEmpty() || oldData.isEmpty())
@@ -89,8 +89,8 @@ namespace
const QString newKey {QLatin1String {"BitTorrent/Session/TorrentContentLayout"}};
SettingsStorage *settingsStorage {SettingsStorage::instance()};
const QVariant oldData {settingsStorage->loadValue(oldKey)};
const QString newData {settingsStorage->loadValue(newKey).toString()};
const auto oldData {settingsStorage->loadValue<QVariant>(oldKey)};
const auto newData {settingsStorage->loadValue<QString>(newKey)};
if (!newData.isEmpty() || !oldData.isValid())
return;
@@ -128,7 +128,7 @@ void handleChangedDefaults(const DefaultPreferencesMode mode)
SettingsStorage *settingsStorage {SettingsStorage::instance()};
for (auto it = changedDefaults.cbegin(); it != changedDefaults.cend(); ++it)
{
if (settingsStorage->loadValue(it->name).isNull())
if (settingsStorage->loadValue<QVariant>(it->name).isNull())
settingsStorage->storeValue(it->name, (mode == DefaultPreferencesMode::Legacy ? it->legacy : it->current));
}
}

View File

@@ -2,6 +2,7 @@ add_library(qbt_base STATIC
# headers
algorithm.h
asyncfilestorage.h
bittorrent/abstractfilestorage.h
bittorrent/addtorrentparams.h
bittorrent/bandwidthscheduler.h
bittorrent/cachestatus.h
@@ -24,10 +25,10 @@ add_library(qbt_base STATIC
bittorrent/sessionstatus.h
bittorrent/speedmonitor.h
bittorrent/statistics.h
bittorrent/torrent.h
bittorrent/torrentcontentlayout.h
bittorrent/torrentcreatorthread.h
bittorrent/torrenthandle.h
bittorrent/torrenthandleimpl.h
bittorrent/torrentimpl.h
bittorrent/torrentinfo.h
bittorrent/tracker.h
bittorrent/trackerentry.h
@@ -72,7 +73,6 @@ add_library(qbt_base STATIC
settingsstorage.h
torrentfileguard.h
torrentfilter.h
tristatebool.h
types.h
unicodestrings.h
utils/bytearray.h
@@ -86,9 +86,11 @@ add_library(qbt_base STATIC
utils/random.h
utils/string.h
utils/version.h
version.h
# sources
asyncfilestorage.cpp
bittorrent/abstractfilestorage.cpp
bittorrent/bandwidthscheduler.cpp
bittorrent/customstorage.cpp
bittorrent/downloadpriority.cpp
@@ -105,9 +107,9 @@ add_library(qbt_base STATIC
bittorrent/session.cpp
bittorrent/speedmonitor.cpp
bittorrent/statistics.cpp
bittorrent/torrent.cpp
bittorrent/torrentcreatorthread.cpp
bittorrent/torrenthandle.cpp
bittorrent/torrenthandleimpl.cpp
bittorrent/torrentimpl.cpp
bittorrent/torrentinfo.cpp
bittorrent/tracker.cpp
bittorrent/trackerentry.cpp
@@ -148,7 +150,6 @@ add_library(qbt_base STATIC
settingsstorage.cpp
torrentfileguard.cpp
torrentfilter.cpp
tristatebool.cpp
utils/bytearray.cpp
utils/foreignapps.cpp
utils/fs.cpp
@@ -165,7 +166,6 @@ target_link_libraries(qbt_base
PRIVATE
OpenSSL::Crypto OpenSSL::SSL
ZLIB::ZLIB
qbt_version_definitions
PUBLIC
LibtorrentRasterbar::torrent-rasterbar
Qt5::Core Qt5::Network Qt5::Xml

View File

@@ -32,9 +32,6 @@
namespace Algorithm
{
template <typename ...>
using void_t = void; // replace this with std::void_t in C++17
template <typename T, typename = void>
struct HasMappedType
: std::false_type
@@ -42,7 +39,7 @@ namespace Algorithm
};
template <typename T>
struct HasMappedType<T, void_t<typename T::mapped_type>>
struct HasMappedType<T, std::void_t<typename T::mapped_type>>
: std::true_type
{
};

View File

@@ -1,6 +1,7 @@
HEADERS += \
$$PWD/algorithm.h \
$$PWD/asyncfilestorage.h \
$$PWD/bittorrent/abstractfilestorage.h \
$$PWD/bittorrent/addtorrentparams.h \
$$PWD/bittorrent/bandwidthscheduler.h \
$$PWD/bittorrent/cachestatus.h \
@@ -23,10 +24,10 @@ HEADERS += \
$$PWD/bittorrent/sessionstatus.h \
$$PWD/bittorrent/speedmonitor.h \
$$PWD/bittorrent/statistics.h \
$$PWD/bittorrent/torrent.h \
$$PWD/bittorrent/torrentcontentlayout.h \
$$PWD/bittorrent/torrentcreatorthread.h \
$$PWD/bittorrent/torrenthandle.h \
$$PWD/bittorrent/torrenthandleimpl.h \
$$PWD/bittorrent/torrentimpl.h \
$$PWD/bittorrent/torrentinfo.h \
$$PWD/bittorrent/tracker.h \
$$PWD/bittorrent/trackerentry.h \
@@ -72,7 +73,6 @@ HEADERS += \
$$PWD/settingvalue.h \
$$PWD/torrentfileguard.h \
$$PWD/torrentfilter.h \
$$PWD/tristatebool.h \
$$PWD/types.h \
$$PWD/unicodestrings.h \
$$PWD/utils/bytearray.h \
@@ -85,10 +85,12 @@ HEADERS += \
$$PWD/utils/password.h \
$$PWD/utils/random.h \
$$PWD/utils/string.h \
$$PWD/utils/version.h
$$PWD/utils/version.h \
$$PWD/version.h
SOURCES += \
$$PWD/asyncfilestorage.cpp \
$$PWD/bittorrent/abstractfilestorage.cpp \
$$PWD/bittorrent/bandwidthscheduler.cpp \
$$PWD/bittorrent/customstorage.cpp \
$$PWD/bittorrent/downloadpriority.cpp \
@@ -105,9 +107,9 @@ SOURCES += \
$$PWD/bittorrent/session.cpp \
$$PWD/bittorrent/speedmonitor.cpp \
$$PWD/bittorrent/statistics.cpp \
$$PWD/bittorrent/torrent.cpp \
$$PWD/bittorrent/torrentcreatorthread.cpp \
$$PWD/bittorrent/torrenthandle.cpp \
$$PWD/bittorrent/torrenthandleimpl.cpp \
$$PWD/bittorrent/torrentimpl.cpp \
$$PWD/bittorrent/torrentinfo.cpp \
$$PWD/bittorrent/tracker.cpp \
$$PWD/bittorrent/trackerentry.cpp \
@@ -148,7 +150,6 @@ SOURCES += \
$$PWD/settingsstorage.cpp \
$$PWD/torrentfileguard.cpp \
$$PWD/torrentfilter.cpp \
$$PWD/tristatebool.cpp \
$$PWD/utils/bytearray.cpp \
$$PWD/utils/foreignapps.cpp \
$$PWD/utils/fs.cpp \

View File

@@ -0,0 +1,140 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2020 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#include "abstractfilestorage.h"
#include <QDir>
#include <QHash>
#include <QVector>
#include "base/bittorrent/common.h"
#include "base/exceptions.h"
#include "base/utils/fs.h"
#if defined(Q_OS_WIN)
const Qt::CaseSensitivity CASE_SENSITIVITY {Qt::CaseInsensitive};
#else
const Qt::CaseSensitivity CASE_SENSITIVITY {Qt::CaseSensitive};
#endif
namespace
{
bool areSameFileNames(QString first, QString second)
{
if (first.endsWith(QB_EXT, Qt::CaseInsensitive))
first.chop(QB_EXT.size());
if (second.endsWith(QB_EXT, Qt::CaseInsensitive))
second.chop(QB_EXT.size());
return QString::compare(first, second, CASE_SENSITIVITY) == 0;
}
}
void BitTorrent::AbstractFileStorage::renameFile(const QString &oldPath, const QString &newPath)
{
if (!Utils::Fs::isValidFileSystemName(oldPath, true))
throw RuntimeError {tr("The old path is invalid: '%1'.").arg(oldPath)};
if (!Utils::Fs::isValidFileSystemName(newPath, true))
throw RuntimeError {tr("The new path is invalid: '%1'.").arg(newPath)};
const QString oldFilePath = Utils::Fs::toUniformPath(oldPath);
if (oldFilePath.endsWith(QLatin1Char {'/'}))
throw RuntimeError {tr("Invalid file path: '%1'.").arg(oldFilePath)};
const QString newFilePath = Utils::Fs::toUniformPath(newPath);
if (newFilePath.endsWith(QLatin1Char {'/'}))
throw RuntimeError {tr("Invalid file path: '%1'.").arg(newFilePath)};
if (QDir().isAbsolutePath(newFilePath))
throw RuntimeError {tr("Absolute path isn't allowed: '%1'.").arg(newFilePath)};
int renamingFileIndex = -1;
for (int i = 0; i < filesCount(); ++i)
{
const QString path = filePath(i);
if ((renamingFileIndex < 0) && areSameFileNames(path, oldFilePath))
renamingFileIndex = i;
if (areSameFileNames(path, newFilePath))
throw RuntimeError {tr("The file already exists: '%1'.").arg(newFilePath)};
}
if (renamingFileIndex < 0)
throw RuntimeError {tr("No such file: '%1'.").arg(oldFilePath)};
const auto extAdjusted = [](const QString &path, const bool needExt) -> QString
{
if (path.endsWith(QB_EXT, Qt::CaseInsensitive) == needExt)
return path;
return (needExt ? (path + QB_EXT) : (path.left(path.size() - QB_EXT.size())));
};
renameFile(renamingFileIndex, extAdjusted(newFilePath, filePath(renamingFileIndex).endsWith(QB_EXT, Qt::CaseInsensitive)));
}
void BitTorrent::AbstractFileStorage::renameFolder(const QString &oldPath, const QString &newPath)
{
if (!Utils::Fs::isValidFileSystemName(oldPath, true))
throw RuntimeError {tr("The old path is invalid: '%1'.").arg(oldPath)};
if (!Utils::Fs::isValidFileSystemName(newPath, true))
throw RuntimeError {tr("The new path is invalid: '%1'.").arg(newPath)};
const auto cleanFolderPath = [](const QString &path) -> QString
{
const QString uniformPath = Utils::Fs::toUniformPath(path);
return (uniformPath.endsWith(QLatin1Char {'/'}) ? uniformPath : uniformPath + QLatin1Char {'/'});
};
const QString oldFolderPath = cleanFolderPath(oldPath);
const QString newFolderPath = cleanFolderPath(newPath);
if (QDir().isAbsolutePath(newFolderPath))
throw RuntimeError {tr("Absolute path isn't allowed: '%1'.").arg(newFolderPath)};
QVector<int> renamingFileIndexes;
renamingFileIndexes.reserve(filesCount());
for (int i = 0; i < filesCount(); ++i)
{
const QString path = filePath(i);
if (path.startsWith(oldFolderPath, CASE_SENSITIVITY))
renamingFileIndexes.append(i);
if (path.startsWith(newFolderPath, CASE_SENSITIVITY))
throw RuntimeError {tr("The folder already exists: '%1'.").arg(newFolderPath)};
}
if (renamingFileIndexes.isEmpty())
throw RuntimeError {tr("No such folder: '%1'.").arg(oldFolderPath)};
for (const int index : renamingFileIndexes)
{
const QString newFilePath = newFolderPath + filePath(index).mid(oldFolderPath.size());
renameFile(index, newFilePath);
}
}

View File

@@ -1,7 +1,7 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2011 Christian Kandeler
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2020 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -28,35 +28,26 @@
#pragma once
#include <QDialog>
#include <QtGlobal>
#include <QCoreApplication>
namespace Ui
class QString;
namespace BitTorrent
{
class UpDownRatioDialog;
class AbstractFileStorage
{
Q_DECLARE_TR_FUNCTIONS(AbstractFileStorage)
public:
virtual int filesCount() const = 0;
virtual QString filePath(int index) const = 0;
virtual QString fileName(int index) const = 0;
virtual qlonglong fileSize(int index) const = 0;
virtual void renameFile(int index, const QString &name) = 0;
void renameFile(const QString &oldPath, const QString &newPath);
void renameFolder(const QString &oldPath, const QString &newPath);
};
}
class UpDownRatioDialog final : public QDialog
{
Q_OBJECT
public:
UpDownRatioDialog(bool useDefault, qreal initialValue, qreal maxValue,
int initialTimeValue, int maxTimeValue,
QWidget *parent = nullptr);
~UpDownRatioDialog();
bool useDefault() const;
qreal ratio() const;
int seedingTime() const;
public slots:
void accept() override;
private slots:
void handleRatioTypeChanged();
void enableRatioSpin();
void enableTimeSpin();
private:
Ui::UpDownRatioDialog *m_ui;
};

View File

@@ -28,14 +28,13 @@
#pragma once
#include <boost/optional.hpp>
#include <optional>
#include <QSet>
#include <QString>
#include <QVector>
#include "base/tristatebool.h"
#include "torrenthandle.h"
#include "torrent.h"
#include "torrentcontentlayout.h"
namespace BitTorrent
@@ -51,15 +50,15 @@ namespace BitTorrent
bool disableTempPath = false; // e.g. for imported torrents
bool sequential = false;
bool firstLastPiecePriority = false;
TriStateBool addForced;
TriStateBool addPaused;
bool addForced = false;
std::optional<bool> addPaused;
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
bool skipChecking = false;
boost::optional<BitTorrent::TorrentContentLayout> contentLayout;
TriStateBool useAutoTMM;
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
std::optional<bool> useAutoTMM;
int uploadLimit = -1;
int downloadLimit = -1;
int seedingTimeLimit = TorrentHandle::USE_GLOBAL_SEEDING_TIME;
qreal ratioLimit = TorrentHandle::USE_GLOBAL_RATIO;
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
};
}

View File

@@ -30,5 +30,4 @@
#include <QString>
// TODO: Make it inline in C++17
extern const QString QB_EXT;
inline const QString QB_EXT {QStringLiteral(".!qB")};

View File

@@ -30,9 +30,6 @@
#include <type_traits>
template <typename ...>
using void_t = void; // replace this with std::void_t in C++17
template <typename T, typename = void>
struct HasUnderlyingType
: std::false_type
@@ -40,7 +37,7 @@ struct HasUnderlyingType
};
template <typename T>
struct HasUnderlyingType<T, void_t<typename T::underlying_type>>
struct HasUnderlyingType<T, std::void_t<typename T::underlying_type>>
: std::true_type
{
};

View File

@@ -30,14 +30,14 @@
#include <QBitArray>
#include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/torrent.h"
#include "base/net/geoipmanager.h"
#include "base/unicodestrings.h"
#include "peeraddress.h"
using namespace BitTorrent;
PeerInfo::PeerInfo(const TorrentHandle *torrent, const lt::peer_info &nativeInfo)
PeerInfo::PeerInfo(const Torrent *torrent, const lt::peer_info &nativeInfo)
: m_nativeInfo(nativeInfo)
{
calcRelevance(torrent);
@@ -226,7 +226,7 @@ QString PeerInfo::connectionType() const
: QLatin1String {"Web"};
}
void PeerInfo::calcRelevance(const TorrentHandle *torrent)
void PeerInfo::calcRelevance(const Torrent *torrent)
{
const QBitArray allPieces = torrent->pieces();
const QBitArray peerPieces = pieces();

View File

@@ -36,7 +36,7 @@ class QBitArray;
namespace BitTorrent
{
class TorrentHandle;
class Torrent;
struct PeerAddress;
class PeerInfo
@@ -45,7 +45,7 @@ namespace BitTorrent
public:
PeerInfo() = default;
PeerInfo(const TorrentHandle *torrent, const lt::peer_info &nativeInfo);
PeerInfo(const Torrent *torrent, const lt::peer_info &nativeInfo);
bool fromDHT() const;
bool fromPeX() const;
@@ -92,7 +92,7 @@ namespace BitTorrent
int downloadingPieceIndex() const;
private:
void calcRelevance(const TorrentHandle *torrent);
void calcRelevance(const Torrent *torrent);
void determineFlags();
lt::peer_info m_nativeInfo = {};

View File

@@ -39,7 +39,7 @@ const QString KEY_ENABLED = QStringLiteral("Network/PortForwardingEnabled");
PortForwarderImpl::PortForwarderImpl(lt::session *provider, QObject *parent)
: Net::PortForwarder {parent}
, m_active {SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool()}
, m_active {SettingsStorage::instance()->loadValue(KEY_ENABLED, true)}
, m_provider {provider}
{
if (m_active)

View File

@@ -78,13 +78,13 @@
#include "base/profile.h"
#include "base/torrentfileguard.h"
#include "base/torrentfilter.h"
#include "base/tristatebool.h"
#include "base/unicodestrings.h"
#include "base/utils/bytearray.h"
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/utils/net.h"
#include "base/utils/random.h"
#include "base/version.h"
#include "bandwidthscheduler.h"
#include "common.h"
#include "customstorage.h"
@@ -96,7 +96,7 @@
#include "portforwarderimpl.h"
#include "resumedatasavingmanager.h"
#include "statistics.h"
#include "torrenthandleimpl.h"
#include "torrentimpl.h"
#include "tracker.h"
#include "trackerentry.h"
@@ -291,9 +291,8 @@ namespace
LowerLimited<T> lowerLimited(T limit, T ret) { return LowerLimited<T>(limit, ret); }
template <typename T>
std::function<T (const T&)> clampValue(const T lower, const T upper)
auto clampValue(const T lower, const T upper)
{
// TODO: change return type to `auto` when using C++17
return [lower, upper](const T value) -> T
{
if (value < lower)
@@ -482,7 +481,7 @@ Session::Session(QObject *parent)
m_storedCategories = map_cast(m_categories);
}
m_tags = List::toSet(m_storedTags.value());
m_tags = List::toSet(m_storedTags.get());
enqueueRefresh();
updateSeedingLimitTimer();
@@ -579,7 +578,7 @@ void Session::setTempPathEnabled(const bool enabled)
if (enabled != isTempPathEnabled())
{
m_isTempPathEnabled = enabled;
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->handleTempPathChanged();
}
}
@@ -596,7 +595,7 @@ void Session::setAppendExtensionEnabled(const bool enabled)
m_isAppendExtensionEnabled = enabled;
// append or remove .!qB extension for incomplete files
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->handleAppendExtensionToggled();
}
}
@@ -749,13 +748,13 @@ bool Session::editCategory(const QString &name, const QString &savePath)
m_storedCategories = map_cast(m_categories);
if (isDisableAutoTMMWhenCategorySavePathChanged())
{
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
if (torrent->category() == name)
torrent->setAutoTMMEnabled(false);
}
else
{
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
if (torrent->category() == name)
torrent->handleCategorySavePathChanged();
}
@@ -765,7 +764,7 @@ bool Session::editCategory(const QString &name, const QString &savePath)
bool Session::removeCategory(const QString &name)
{
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
if (torrent->belongsToCategory(name))
torrent->setCategory("");
@@ -859,7 +858,7 @@ bool Session::removeTag(const QString &tag)
{
if (m_tags.remove(tag))
{
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->removeTag(tag);
m_storedTags = m_tags.values();
emit tagRemoved(tag);
@@ -1130,7 +1129,7 @@ void Session::initializeNativeSession()
void Session::processBannedIPs(lt::ip_filter &filter)
{
// First, import current filter
for (const QString &ip : asConst(m_bannedIPs.value()))
for (const QString &ip : asConst(m_bannedIPs.get()))
{
lt::error_code ec;
const lt::address addr = lt::make_address(ip.toLatin1().constData(), ec);
@@ -1619,16 +1618,16 @@ void Session::processShareLimits()
// We shouldn't iterate over `m_torrents` in the loop below
// since `deleteTorrent()` modifies it indirectly
const QHash<InfoHash, TorrentHandleImpl *> torrents {m_torrents};
for (TorrentHandleImpl *const torrent : torrents)
const QHash<InfoHash, TorrentImpl *> torrents {m_torrents};
for (TorrentImpl *const torrent : torrents)
{
if (torrent->isSeed() && !torrent->isForced())
{
if (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT)
if (torrent->ratioLimit() != Torrent::NO_RATIO_LIMIT)
{
const qreal ratio = torrent->realRatio();
qreal ratioLimit = torrent->ratioLimit();
if (ratioLimit == TorrentHandle::USE_GLOBAL_RATIO)
if (ratioLimit == Torrent::USE_GLOBAL_RATIO)
// If Global Max Ratio is really set...
ratioLimit = globalMaxRatio();
@@ -1636,7 +1635,7 @@ void Session::processShareLimits()
{
qDebug("Ratio: %f (limit: %f)", ratio, ratioLimit);
if ((ratio <= TorrentHandle::MAX_RATIO) && (ratio >= ratioLimit))
if ((ratio <= Torrent::MAX_RATIO) && (ratio >= ratioLimit))
{
if (m_maxRatioAction == Remove)
{
@@ -1646,7 +1645,7 @@ void Session::processShareLimits()
else if (m_maxRatioAction == DeleteFiles)
{
LogMsg(tr("'%1' reached the maximum ratio you set. Removed torrent and its files.").arg(torrent->name()));
deleteTorrent(torrent->hash(), TorrentAndFiles);
deleteTorrent(torrent->hash(), DeleteTorrentAndFiles);
}
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
{
@@ -1663,11 +1662,11 @@ void Session::processShareLimits()
}
}
if (torrent->seedingTimeLimit() != TorrentHandle::NO_SEEDING_TIME_LIMIT)
if (torrent->seedingTimeLimit() != Torrent::NO_SEEDING_TIME_LIMIT)
{
const qlonglong seedingTimeInMinutes = torrent->seedingTime() / 60;
int seedingTimeLimit = torrent->seedingTimeLimit();
if (seedingTimeLimit == TorrentHandle::USE_GLOBAL_SEEDING_TIME)
if (seedingTimeLimit == Torrent::USE_GLOBAL_SEEDING_TIME)
{
// If Global Seeding Time Limit is really set...
seedingTimeLimit = globalMaxSeedingMinutes();
@@ -1675,7 +1674,7 @@ void Session::processShareLimits()
if (seedingTimeLimit >= 0)
{
if ((seedingTimeInMinutes <= TorrentHandle::MAX_SEEDING_TIME) && (seedingTimeInMinutes >= seedingTimeLimit))
if ((seedingTimeInMinutes <= Torrent::MAX_SEEDING_TIME) && (seedingTimeInMinutes >= seedingTimeLimit))
{
if (m_maxRatioAction == Remove)
{
@@ -1685,7 +1684,7 @@ void Session::processShareLimits()
else if (m_maxRatioAction == DeleteFiles)
{
LogMsg(tr("'%1' reached the maximum seeding time you set. Removed torrent and its files.").arg(torrent->name()));
deleteTorrent(torrent->hash(), TorrentAndFiles);
deleteTorrent(torrent->hash(), DeleteTorrentAndFiles);
}
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
{
@@ -1724,7 +1723,7 @@ void Session::handleDownloadFinished(const Net::DownloadResult &result)
void Session::fileSearchFinished(const InfoHash &id, const QString &savePath, const QStringList &fileNames)
{
TorrentHandleImpl *torrent = m_torrents.value(id);
TorrentImpl *torrent = m_torrents.value(id);
if (torrent)
{
torrent->fileSearchFinished(savePath, fileNames);
@@ -1748,14 +1747,14 @@ void Session::fileSearchFinished(const InfoHash &id, const QString &savePath, co
}
// Return the torrent handle, given its hash
TorrentHandle *Session::findTorrent(const InfoHash &hash) const
Torrent *Session::findTorrent(const InfoHash &hash) const
{
return m_torrents.value(hash);
}
bool Session::hasActiveTorrents() const
{
return std::any_of(m_torrents.begin(), m_torrents.end(), [](TorrentHandleImpl *torrent)
return std::any_of(m_torrents.begin(), m_torrents.end(), [](TorrentImpl *torrent)
{
return TorrentFilter::ActiveTorrent.match(torrent);
});
@@ -1763,7 +1762,7 @@ bool Session::hasActiveTorrents() const
bool Session::hasUnfinishedTorrents() const
{
return std::any_of(m_torrents.begin(), m_torrents.end(), [](const TorrentHandleImpl *torrent)
return std::any_of(m_torrents.begin(), m_torrents.end(), [](const TorrentImpl *torrent)
{
return (!torrent->isSeed() && !torrent->isPaused());
});
@@ -1771,7 +1770,7 @@ bool Session::hasUnfinishedTorrents() const
bool Session::hasRunningSeed() const
{
return std::any_of(m_torrents.begin(), m_torrents.end(), [](const TorrentHandleImpl *torrent)
return std::any_of(m_torrents.begin(), m_torrents.end(), [](const TorrentImpl *torrent)
{
return (torrent->isSeed() && !torrent->isPaused());
});
@@ -1800,14 +1799,14 @@ void Session::banIP(const QString &ip)
// and from the disk, if the corresponding deleteOption is chosen
bool Session::deleteTorrent(const InfoHash &hash, const DeleteOption deleteOption)
{
TorrentHandleImpl *const torrent = m_torrents.take(hash);
TorrentImpl *const torrent = m_torrents.take(hash);
if (!torrent) return false;
qDebug("Deleting torrent with hash: %s", qUtf8Printable(torrent->hash()));
emit torrentAboutToBeRemoved(torrent);
// Remove it from session
if (deleteOption == Torrent)
if (deleteOption == DeleteTorrent)
{
m_removingTorrents[torrent->hash()] = {torrent->name(), "", deleteOption};
@@ -1888,7 +1887,7 @@ bool Session::cancelDownloadMetadata(const InfoHash &hash)
void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
{
using ElementType = std::pair<int, TorrentHandleImpl *>;
using ElementType = std::pair<int, TorrentImpl *>;
std::priority_queue<ElementType
, std::vector<ElementType>
, std::greater<ElementType>> torrentQueue;
@@ -1896,7 +1895,7 @@ void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
// Sort torrents by queue position
for (const InfoHash &infoHash : hashes)
{
TorrentHandleImpl *const torrent = m_torrents.value(infoHash);
TorrentImpl *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
torrentQueue.emplace(torrent->queuePosition(), torrent);
}
@@ -1904,7 +1903,7 @@ void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
// Increase torrents queue position (starting with the one in the highest queue position)
while (!torrentQueue.empty())
{
const TorrentHandleImpl *torrent = torrentQueue.top().second;
const TorrentImpl *torrent = torrentQueue.top().second;
torrentQueuePositionUp(torrent->nativeHandle());
torrentQueue.pop();
}
@@ -1914,13 +1913,13 @@ void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
void Session::decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
{
using ElementType = std::pair<int, TorrentHandleImpl *>;
using ElementType = std::pair<int, TorrentImpl *>;
std::priority_queue<ElementType> torrentQueue;
// Sort torrents by queue position
for (const InfoHash &infoHash : hashes)
{
TorrentHandleImpl *const torrent = m_torrents.value(infoHash);
TorrentImpl *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
torrentQueue.emplace(torrent->queuePosition(), torrent);
}
@@ -1928,7 +1927,7 @@ void Session::decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
// Decrease torrents queue position (starting with the one in the lowest queue position)
while (!torrentQueue.empty())
{
const TorrentHandleImpl *torrent = torrentQueue.top().second;
const TorrentImpl *torrent = torrentQueue.top().second;
torrentQueuePositionDown(torrent->nativeHandle());
torrentQueue.pop();
}
@@ -1941,13 +1940,13 @@ void Session::decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
void Session::topTorrentsQueuePos(const QVector<InfoHash> &hashes)
{
using ElementType = std::pair<int, TorrentHandleImpl *>;
using ElementType = std::pair<int, TorrentImpl *>;
std::priority_queue<ElementType> torrentQueue;
// Sort torrents by queue position
for (const InfoHash &infoHash : hashes)
{
TorrentHandleImpl *const torrent = m_torrents.value(infoHash);
TorrentImpl *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
torrentQueue.emplace(torrent->queuePosition(), torrent);
}
@@ -1955,7 +1954,7 @@ void Session::topTorrentsQueuePos(const QVector<InfoHash> &hashes)
// Top torrents queue position (starting with the one in the lowest queue position)
while (!torrentQueue.empty())
{
const TorrentHandleImpl *torrent = torrentQueue.top().second;
const TorrentImpl *torrent = torrentQueue.top().second;
torrentQueuePositionTop(torrent->nativeHandle());
torrentQueue.pop();
}
@@ -1965,7 +1964,7 @@ void Session::topTorrentsQueuePos(const QVector<InfoHash> &hashes)
void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
{
using ElementType = std::pair<int, TorrentHandleImpl *>;
using ElementType = std::pair<int, TorrentImpl *>;
std::priority_queue<ElementType
, std::vector<ElementType>
, std::greater<ElementType>> torrentQueue;
@@ -1973,7 +1972,7 @@ void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
// Sort torrents by queue position
for (const InfoHash &infoHash : hashes)
{
TorrentHandleImpl *const torrent = m_torrents.value(infoHash);
TorrentImpl *const torrent = m_torrents.value(infoHash);
if (torrent && !torrent->isSeed())
torrentQueue.emplace(torrent->queuePosition(), torrent);
}
@@ -1981,7 +1980,7 @@ void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
// Bottom torrents queue position (starting with the one in the highest queue position)
while (!torrentQueue.empty())
{
const TorrentHandleImpl *torrent = torrentQueue.top().second;
const TorrentImpl *torrent = torrentQueue.top().second;
torrentQueuePositionBottom(torrent->nativeHandle());
torrentQueue.pop();
}
@@ -1992,17 +1991,17 @@ void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
saveTorrentsQueue();
}
void Session::handleTorrentSaveResumeDataRequested(const TorrentHandleImpl *torrent)
void Session::handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent)
{
qDebug("Saving resume data is requested for torrent '%s'...", qUtf8Printable(torrent->name()));
++m_numResumeData;
}
QVector<TorrentHandle *> Session::torrents() const
QVector<Torrent *> Session::torrents() const
{
QVector<TorrentHandle *> result;
QVector<Torrent *> result;
result.reserve(m_torrents.size());
for (TorrentHandleImpl *torrent : asConst(m_torrents))
for (TorrentImpl *torrent : asConst(m_torrents))
result << torrent;
return result;
@@ -2040,14 +2039,14 @@ bool Session::addTorrent(const MagnetUri &magnetUri, const AddTorrentParams &par
{
if (!magnetUri.isValid()) return false;
return addTorrent_impl(params, magnetUri);
return addTorrent_impl(magnetUri, params);
}
bool Session::addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams &params)
{
if (!torrentInfo.isValid()) return false;
return addTorrent_impl(params, MagnetUri(), torrentInfo);
return addTorrent_impl(torrentInfo, params);
}
LoadTorrentParams Session::initLoadTorrentParams(const AddTorrentParams &addTorrentParams)
@@ -2058,19 +2057,13 @@ LoadTorrentParams Session::initLoadTorrentParams(const AddTorrentParams &addTorr
loadTorrentParams.tags = addTorrentParams.tags;
loadTorrentParams.firstLastPiecePriority = addTorrentParams.firstLastPiecePriority;
loadTorrentParams.hasSeedStatus = addTorrentParams.skipChecking; // do not react on 'torrent_finished_alert' when skipping
loadTorrentParams.contentLayout = (addTorrentParams.contentLayout
? *addTorrentParams.contentLayout
: torrentContentLayout());
loadTorrentParams.forced = (addTorrentParams.addForced == TriStateBool::True);
loadTorrentParams.paused = ((addTorrentParams.addPaused == TriStateBool::Undefined)
? isAddTorrentPaused()
: (addTorrentParams.addPaused == TriStateBool::True));
loadTorrentParams.contentLayout = addTorrentParams.contentLayout.value_or(torrentContentLayout());
loadTorrentParams.forced = addTorrentParams.addForced;
loadTorrentParams.paused = addTorrentParams.addPaused.value_or(isAddTorrentPaused());
loadTorrentParams.ratioLimit = addTorrentParams.ratioLimit;
loadTorrentParams.seedingTimeLimit = addTorrentParams.seedingTimeLimit;
const bool useAutoTMM = ((addTorrentParams.useAutoTMM == TriStateBool::Undefined)
? !isAutoTMMDisabledByDefault()
: (addTorrentParams.useAutoTMM == TriStateBool::True));
const bool useAutoTMM = addTorrentParams.useAutoTMM.value_or(!isAutoTMMDisabledByDefault());
if (useAutoTMM)
loadTorrentParams.savePath = "";
else if (addTorrentParams.savePath.trimmed().isEmpty())
@@ -2088,9 +2081,11 @@ LoadTorrentParams Session::initLoadTorrentParams(const AddTorrentParams &addTorr
}
// Add a torrent to the BitTorrent session
bool Session::addTorrent_impl(const AddTorrentParams &addTorrentParams, const MagnetUri &magnetUri, TorrentInfo metadata)
bool Session::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source, const AddTorrentParams &addTorrentParams)
{
const bool hasMetadata = metadata.isValid();
const bool hasMetadata = std::holds_alternative<TorrentInfo>(source);
TorrentInfo metadata = (hasMetadata ? std::get<TorrentInfo>(source) : TorrentInfo {});
const MagnetUri &magnetUri = (hasMetadata ? MagnetUri {} : std::get<MagnetUri>(source));
const InfoHash hash = (hasMetadata ? metadata.hash() : magnetUri.hash());
// It looks illogical that we don't just use an existing handle,
@@ -2104,7 +2099,7 @@ bool Session::addTorrent_impl(const AddTorrentParams &addTorrentParams, const Ma
if (m_loadingTorrents.contains(hash))
return false;
TorrentHandleImpl *const torrent = m_torrents.value(hash);
TorrentImpl *const torrent = m_torrents.value(hash);
if (torrent)
{ // a duplicate torrent is added
if (torrent->isPrivate() || (hasMetadata && metadata.isPrivate()))
@@ -2298,7 +2293,7 @@ bool Session::downloadMetadata(const MagnetUri &magnetUri)
return true;
}
void Session::exportTorrentFile(const TorrentHandle *torrent, TorrentExportFolder folder)
void Session::exportTorrentFile(const Torrent *torrent, TorrentExportFolder folder)
{
Q_ASSERT(((folder == TorrentExportFolder::Regular) && !torrentExportDirectory().isEmpty()) ||
((folder == TorrentExportFolder::Finished) && !finishedTorrentExportDirectory().isEmpty()));
@@ -2326,7 +2321,7 @@ void Session::exportTorrentFile(const TorrentHandle *torrent, TorrentExportFolde
void Session::generateResumeData()
{
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
{
if (!torrent->isValid()) continue;
@@ -2372,7 +2367,7 @@ void Session::saveTorrentsQueue()
{
// store hash in textual representation
QMap<int, QString> queue; // Use QMap since it should be ordered by key
for (const TorrentHandleImpl *torrent : asConst(m_torrents))
for (const TorrentImpl *torrent : asConst(m_torrents))
{
// We require actual (non-cached) queue position here!
const int queuePos = static_cast<LTUnderlyingType<lt::queue_position_t>>(torrent->nativeHandle().queue_position());
@@ -2414,10 +2409,10 @@ void Session::setDefaultSavePath(QString path)
m_defaultSavePath = path;
if (isDisableAutoTMMWhenDefaultSavePathChanged())
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->setAutoTMMEnabled(false);
else
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->handleCategorySavePathChanged();
}
@@ -2428,7 +2423,7 @@ void Session::setTempPath(QString path)
m_tempPath = path;
for (TorrentHandleImpl *const torrent : asConst(m_torrents))
for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->handleTempPathChanged();
}
@@ -3142,7 +3137,7 @@ void Session::setPeerTurnoverInterval(const int val)
int Session::asyncIOThreads() const
{
return qBound(1, m_asyncIOThreads.value(), 1024);
return qBound(1, m_asyncIOThreads.get(), 1024);
}
void Session::setAsyncIOThreads(const int num)
@@ -3156,7 +3151,7 @@ void Session::setAsyncIOThreads(const int num)
int Session::hashingThreads() const
{
return qBound(1, m_hashingThreads.value(), 1024);
return qBound(1, m_hashingThreads.get(), 1024);
}
void Session::setHashingThreads(const int num)
@@ -3184,7 +3179,7 @@ void Session::setFilePoolSize(const int size)
int Session::checkingMemUsage() const
{
return qMax(1, m_checkingMemUsage.value());
return qMax(1, m_checkingMemUsage.get());
}
void Session::setCheckingMemUsage(int size)
@@ -3201,11 +3196,11 @@ void Session::setCheckingMemUsage(int size)
int Session::diskCacheSize() const
{
#ifdef QBT_APP_64BIT
return qMin(m_diskCacheSize.value(), 33554431); // 32768GiB
return qMin(m_diskCacheSize.get(), 33554431); // 32768GiB
#else
// When build as 32bit binary, set the maximum at less than 2GB to prevent crashes
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
return qMin(m_diskCacheSize.value(), 1536);
return qMin(m_diskCacheSize.get(), 1536);
#endif
}
@@ -3737,7 +3732,7 @@ bool Session::isListening() const
MaxRatioAction Session::maxRatioAction() const
{
return static_cast<MaxRatioAction>(m_maxRatioAction.value());
return static_cast<MaxRatioAction>(m_maxRatioAction.get());
}
void Session::setMaxRatioAction(const MaxRatioAction act)
@@ -3756,8 +3751,8 @@ bool Session::isKnownTorrent(const InfoHash &hash) const
void Session::updateSeedingLimitTimer()
{
if ((globalMaxRatio() == TorrentHandle::NO_RATIO_LIMIT) && !hasPerTorrentRatioLimit()
&& (globalMaxSeedingMinutes() == TorrentHandle::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit())
if ((globalMaxRatio() == Torrent::NO_RATIO_LIMIT) && !hasPerTorrentRatioLimit()
&& (globalMaxSeedingMinutes() == Torrent::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit())
{
if (m_seedingLimitTimer->isActive())
m_seedingLimitTimer->stop();
@@ -3768,48 +3763,48 @@ void Session::updateSeedingLimitTimer()
}
}
void Session::handleTorrentShareLimitChanged(TorrentHandleImpl *const torrent)
void Session::handleTorrentShareLimitChanged(TorrentImpl *const torrent)
{
torrent->saveResumeData();
updateSeedingLimitTimer();
}
void Session::handleTorrentNameChanged(TorrentHandleImpl *const torrent)
void Session::handleTorrentNameChanged(TorrentImpl *const torrent)
{
torrent->saveResumeData();
}
void Session::handleTorrentSavePathChanged(TorrentHandleImpl *const torrent)
void Session::handleTorrentSavePathChanged(TorrentImpl *const torrent)
{
torrent->saveResumeData();
emit torrentSavePathChanged(torrent);
}
void Session::handleTorrentCategoryChanged(TorrentHandleImpl *const torrent, const QString &oldCategory)
void Session::handleTorrentCategoryChanged(TorrentImpl *const torrent, const QString &oldCategory)
{
torrent->saveResumeData();
emit torrentCategoryChanged(torrent, oldCategory);
}
void Session::handleTorrentTagAdded(TorrentHandleImpl *const torrent, const QString &tag)
void Session::handleTorrentTagAdded(TorrentImpl *const torrent, const QString &tag)
{
torrent->saveResumeData();
emit torrentTagAdded(torrent, tag);
}
void Session::handleTorrentTagRemoved(TorrentHandleImpl *const torrent, const QString &tag)
void Session::handleTorrentTagRemoved(TorrentImpl *const torrent, const QString &tag)
{
torrent->saveResumeData();
emit torrentTagRemoved(torrent, tag);
}
void Session::handleTorrentSavingModeChanged(TorrentHandleImpl *const torrent)
void Session::handleTorrentSavingModeChanged(TorrentImpl *const torrent)
{
torrent->saveResumeData();
emit torrentSavingModeChanged(torrent);
}
void Session::handleTorrentTrackersAdded(TorrentHandleImpl *const torrent, const QVector<TrackerEntry> &newTrackers)
void Session::handleTorrentTrackersAdded(TorrentImpl *const torrent, const QVector<TrackerEntry> &newTrackers)
{
torrent->saveResumeData();
@@ -3821,7 +3816,7 @@ void Session::handleTorrentTrackersAdded(TorrentHandleImpl *const torrent, const
emit trackersChanged(torrent);
}
void Session::handleTorrentTrackersRemoved(TorrentHandleImpl *const torrent, const QVector<TrackerEntry> &deletedTrackers)
void Session::handleTorrentTrackersRemoved(TorrentImpl *const torrent, const QVector<TrackerEntry> &deletedTrackers)
{
torrent->saveResumeData();
@@ -3833,27 +3828,27 @@ void Session::handleTorrentTrackersRemoved(TorrentHandleImpl *const torrent, con
emit trackersChanged(torrent);
}
void Session::handleTorrentTrackersChanged(TorrentHandleImpl *const torrent)
void Session::handleTorrentTrackersChanged(TorrentImpl *const torrent)
{
torrent->saveResumeData();
emit trackersChanged(torrent);
}
void Session::handleTorrentUrlSeedsAdded(TorrentHandleImpl *const torrent, const QVector<QUrl> &newUrlSeeds)
void Session::handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QVector<QUrl> &newUrlSeeds)
{
torrent->saveResumeData();
for (const QUrl &newUrlSeed : newUrlSeeds)
LogMsg(tr("URL seed '%1' was added to torrent '%2'").arg(newUrlSeed.toString(), torrent->name()));
}
void Session::handleTorrentUrlSeedsRemoved(TorrentHandleImpl *const torrent, const QVector<QUrl> &urlSeeds)
void Session::handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVector<QUrl> &urlSeeds)
{
torrent->saveResumeData();
for (const QUrl &urlSeed : urlSeeds)
LogMsg(tr("URL seed '%1' was removed from torrent '%2'").arg(urlSeed.toString(), torrent->name()));
}
void Session::handleTorrentMetadataReceived(TorrentHandleImpl *const torrent)
void Session::handleTorrentMetadataReceived(TorrentImpl *const torrent)
{
// Save metadata
const QDir resumeDataDir {m_resumeFolderPath};
@@ -3874,24 +3869,24 @@ void Session::handleTorrentMetadataReceived(TorrentHandleImpl *const torrent)
emit torrentMetadataReceived(torrent);
}
void Session::handleTorrentPaused(TorrentHandleImpl *const torrent)
void Session::handleTorrentPaused(TorrentImpl *const torrent)
{
torrent->saveResumeData();
emit torrentPaused(torrent);
}
void Session::handleTorrentResumed(TorrentHandleImpl *const torrent)
void Session::handleTorrentResumed(TorrentImpl *const torrent)
{
torrent->saveResumeData();
emit torrentResumed(torrent);
}
void Session::handleTorrentChecked(TorrentHandleImpl *const torrent)
void Session::handleTorrentChecked(TorrentImpl *const torrent)
{
emit torrentFinishedChecking(torrent);
}
void Session::handleTorrentFinished(TorrentHandleImpl *const torrent)
void Session::handleTorrentFinished(TorrentImpl *const torrent)
{
if (!torrent->hasError() && !torrent->hasMissingFiles())
torrent->saveResumeData();
@@ -3930,7 +3925,7 @@ void Session::handleTorrentFinished(TorrentHandleImpl *const torrent)
emit allTorrentsFinished();
}
void Session::handleTorrentResumeDataReady(TorrentHandleImpl *const torrent, const std::shared_ptr<lt::entry> &data)
void Session::handleTorrentResumeDataReady(TorrentImpl *const torrent, const std::shared_ptr<lt::entry> &data)
{
--m_numResumeData;
@@ -3947,17 +3942,17 @@ void Session::handleTorrentResumeDataReady(TorrentHandleImpl *const torrent, con
#endif
}
void Session::handleTorrentTrackerReply(TorrentHandleImpl *const torrent, const QString &trackerUrl)
void Session::handleTorrentTrackerReply(TorrentImpl *const torrent, const QString &trackerUrl)
{
emit trackerSuccess(torrent, trackerUrl);
}
void Session::handleTorrentTrackerError(TorrentHandleImpl *const torrent, const QString &trackerUrl)
void Session::handleTorrentTrackerError(TorrentImpl *const torrent, const QString &trackerUrl)
{
emit trackerError(torrent, trackerUrl);
}
bool Session::addMoveTorrentStorageJob(TorrentHandleImpl *torrent, const QString &newPath, const MoveStorageMode mode)
bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const QString &newPath, const MoveStorageMode mode)
{
Q_ASSERT(torrent);
@@ -4014,7 +4009,7 @@ bool Session::addMoveTorrentStorageJob(TorrentHandleImpl *torrent, const QString
void Session::moveTorrentStorage(const MoveStorageJob &job) const
{
const InfoHash infoHash = job.torrentHandle.info_hash();
const TorrentHandleImpl *torrent = m_torrents.value(infoHash);
const TorrentImpl *torrent = m_torrents.value(infoHash);
const QString torrentName = (torrent ? torrent->name() : QString {infoHash});
LogMsg(tr("Moving \"%1\" to \"%2\"...").arg(torrentName, job.path));
@@ -4037,7 +4032,7 @@ void Session::handleMoveTorrentStorageJobFinished()
const bool torrentHasOutstandingJob = (iter != m_moveStorageQueue.cend());
TorrentHandleImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash());
TorrentImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash());
if (torrent)
{
torrent->handleMoveStorageJobFinished(torrentHasOutstandingJob);
@@ -4047,19 +4042,19 @@ void Session::handleMoveTorrentStorageJobFinished()
// Last job is completed for torrent that being removing, so actually remove it
const lt::torrent_handle nativeHandle {finishedJob.torrentHandle};
const RemovingTorrentData &removingTorrentData = m_removingTorrents[nativeHandle.info_hash()];
if (removingTorrentData.deleteOption == Torrent)
if (removingTorrentData.deleteOption == DeleteTorrent)
m_nativeSession->remove_torrent(nativeHandle, lt::session::delete_partfile);
}
}
void Session::handleTorrentTrackerWarning(TorrentHandleImpl *const torrent, const QString &trackerUrl)
void Session::handleTorrentTrackerWarning(TorrentImpl *const torrent, const QString &trackerUrl)
{
emit trackerWarning(torrent, trackerUrl);
}
bool Session::hasPerTorrentRatioLimit() const
{
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentHandleImpl *torrent)
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentImpl *torrent)
{
return (torrent->ratioLimit() >= 0);
});
@@ -4067,7 +4062,7 @@ bool Session::hasPerTorrentRatioLimit() const
bool Session::hasPerTorrentSeedingTimeLimit() const
{
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentHandleImpl *torrent)
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentImpl *torrent)
{
return (torrent->seedingTimeLimit() >= 0);
});
@@ -4148,7 +4143,7 @@ void Session::disableIPFilter()
void Session::recursiveTorrentDownload(const InfoHash &hash)
{
TorrentHandleImpl *const torrent = m_torrents.value(hash);
TorrentImpl *const torrent = m_torrents.value(hash);
if (!torrent) return;
for (int i = 0; i < torrent->filesCount(); ++i)
@@ -4194,7 +4189,7 @@ bool Session::loadTorrentResumeData(const QByteArray &data, const TorrentInfo &m
Utils::Fs::toUniformPath(fromLTString(root.dict_find_string_value("qBt-savePath"))));
torrentParams.hasSeedStatus = root.dict_find_int_value("qBt-seedStatus");
torrentParams.firstLastPiecePriority = root.dict_find_int_value("qBt-firstLastPiecePriority");
torrentParams.seedingTimeLimit = root.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
torrentParams.seedingTimeLimit = root.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
// === BEGIN DEPRECATED CODE === //
@@ -4217,7 +4212,7 @@ bool Session::loadTorrentResumeData(const QByteArray &data, const TorrentInfo &m
const lt::string_view ratioLimitString = root.dict_find_string_value("qBt-ratioLimit");
if (ratioLimitString.empty())
torrentParams.ratioLimit = root.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
torrentParams.ratioLimit = root.dict_find_int_value("qBt-ratioLimit", Torrent::USE_GLOBAL_RATIO * 1000) / 1000.0;
else
torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble();
@@ -4551,7 +4546,7 @@ void Session::handleAlert(const lt::alert *a)
void Session::dispatchTorrentAlert(const lt::alert *a)
{
TorrentHandleImpl *const torrent = m_torrents.value(static_cast<const lt::torrent_alert*>(a)->handle.info_hash());
TorrentImpl *const torrent = m_torrents.value(static_cast<const lt::torrent_alert*>(a)->handle.info_hash());
if (torrent)
{
torrent->handleAlert(a);
@@ -4566,13 +4561,13 @@ void Session::dispatchTorrentAlert(const lt::alert *a)
}
}
void Session::createTorrentHandle(const lt::torrent_handle &nativeHandle)
void Session::createTorrent(const lt::torrent_handle &nativeHandle)
{
Q_ASSERT(m_loadingTorrents.contains(nativeHandle.info_hash()));
const LoadTorrentParams params = m_loadingTorrents.take(nativeHandle.info_hash());
auto *const torrent = new TorrentHandleImpl {this, m_nativeSession, nativeHandle, params};
auto *const torrent = new TorrentImpl {this, m_nativeSession, nativeHandle, params};
m_torrents.insert(torrent->hash(), torrent);
const bool hasMetadata = torrent->hasMetadata();
@@ -4640,7 +4635,7 @@ void Session::handleAddTorrentAlert(const lt::add_torrent_alert *p)
}
else if (m_loadingTorrents.contains(p->handle.info_hash()))
{
createTorrentHandle(p->handle);
createTorrent(p->handle);
}
}
@@ -4651,7 +4646,7 @@ void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
const auto removingTorrentDataIter = m_removingTorrents.find(infoHash);
if (removingTorrentDataIter != m_removingTorrents.end())
{
if (removingTorrentDataIter->deleteOption == Torrent)
if (removingTorrentDataIter->deleteOption == DeleteTorrent)
{
LogMsg(tr("'%1' was removed from the transfer list.", "'xxx.avi' was removed...").arg(removingTorrentDataIter->name));
m_removingTorrents.erase(removingTorrentDataIter);
@@ -4717,7 +4712,7 @@ void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
void Session::handleFileErrorAlert(const lt::file_error_alert *p)
{
TorrentHandleImpl *const torrent = m_torrents.value(p->handle.info_hash());
TorrentImpl *const torrent = m_torrents.value(p->handle.info_hash());
if (!torrent)
return;
@@ -4787,7 +4782,7 @@ void Session::handlePeerBanAlert(const lt::peer_ban_alert *p)
void Session::handleUrlSeedAlert(const lt::url_seed_alert *p)
{
const TorrentHandleImpl *torrent = m_torrents.value(p->handle.info_hash());
const TorrentImpl *torrent = m_torrents.value(p->handle.info_hash());
if (!torrent)
return;
@@ -4925,13 +4920,10 @@ void Session::handleStorageMovedAlert(const lt::storage_moved_alert *p)
Q_ASSERT(newPath == currentJob.path);
const InfoHash infoHash = currentJob.torrentHandle.info_hash();
TorrentHandleImpl *torrent = m_torrents.value(infoHash);
TorrentImpl *torrent = m_torrents.value(infoHash);
const QString torrentName = (torrent ? torrent->name() : QString {infoHash});
LogMsg(tr("\"%1\" is successfully moved to \"%2\".").arg(torrentName, newPath));
if (torrent)
emit torrentStorageMoveFinished(torrent, newPath);
handleMoveTorrentStorageJobFinished();
}
@@ -4943,27 +4935,24 @@ void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert
Q_ASSERT(currentJob.torrentHandle == p->handle);
const InfoHash infoHash = currentJob.torrentHandle.info_hash();
TorrentHandleImpl *torrent = m_torrents.value(infoHash);
TorrentImpl *torrent = m_torrents.value(infoHash);
const QString torrentName = (torrent ? torrent->name() : QString {infoHash});
const QString currentLocation = QString::fromStdString(p->handle.status(lt::torrent_handle::query_save_path).save_path);
const QString errorMessage = QString::fromStdString(p->message());
LogMsg(tr("Failed to move \"%1\" from \"%2\" to \"%3\". Reason: %4.")
.arg(torrentName, currentLocation, currentJob.path, errorMessage), Log::CRITICAL);
if (torrent)
emit torrentStorageMoveFailed(torrent, currentJob.path, errorMessage);
handleMoveTorrentStorageJobFinished();
}
void Session::handleStateUpdateAlert(const lt::state_update_alert *p)
{
QVector<TorrentHandle *> updatedTorrents;
QVector<Torrent *> updatedTorrents;
updatedTorrents.reserve(p->status.size());
for (const lt::torrent_status &status : p->status)
{
TorrentHandleImpl *const torrent = m_torrents.value(status.info_hash);
TorrentImpl *const torrent = m_torrents.value(status.info_hash);
if (!torrent)
continue;

View File

@@ -30,6 +30,7 @@
#pragma once
#include <memory>
#include <variant>
#include <vector>
#include <libtorrent/add_torrent_params.hpp>
@@ -84,8 +85,8 @@ enum MaxRatioAction
enum DeleteOption
{
Torrent,
TorrentAndFiles
DeleteTorrent,
DeleteTorrentAndFiles
};
enum TorrentExportFolder
@@ -103,8 +104,8 @@ namespace BitTorrent
{
class InfoHash;
class MagnetUri;
class TorrentHandle;
class TorrentHandleImpl;
class Torrent;
class TorrentImpl;
class Tracker;
class TrackerEntry;
struct LoadTorrentParams;
@@ -439,8 +440,8 @@ namespace BitTorrent
#endif
void startUpTorrents();
TorrentHandle *findTorrent(const InfoHash &hash) const;
QVector<TorrentHandle *> torrents() const;
Torrent *findTorrent(const InfoHash &hash) const;
QVector<Torrent *> torrents() const;
bool hasActiveTorrents() const;
bool hasUnfinishedTorrents() const;
bool hasRunningSeed() const;
@@ -459,7 +460,7 @@ namespace BitTorrent
bool addTorrent(const QString &source, const AddTorrentParams &params = AddTorrentParams());
bool addTorrent(const MagnetUri &magnetUri, const AddTorrentParams &params = AddTorrentParams());
bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams &params = AddTorrentParams());
bool deleteTorrent(const InfoHash &hash, DeleteOption deleteOption = Torrent);
bool deleteTorrent(const InfoHash &hash, DeleteOption deleteOption = DeleteTorrent);
bool downloadMetadata(const MagnetUri &magnetUri);
bool cancelDownloadMetadata(const InfoHash &hash);
@@ -469,31 +470,31 @@ namespace BitTorrent
void topTorrentsQueuePos(const QVector<InfoHash> &hashes);
void bottomTorrentsQueuePos(const QVector<InfoHash> &hashes);
// TorrentHandle interface
void handleTorrentSaveResumeDataRequested(const TorrentHandleImpl *torrent);
void handleTorrentShareLimitChanged(TorrentHandleImpl *const torrent);
void handleTorrentNameChanged(TorrentHandleImpl *const torrent);
void handleTorrentSavePathChanged(TorrentHandleImpl *const torrent);
void handleTorrentCategoryChanged(TorrentHandleImpl *const torrent, const QString &oldCategory);
void handleTorrentTagAdded(TorrentHandleImpl *const torrent, const QString &tag);
void handleTorrentTagRemoved(TorrentHandleImpl *const torrent, const QString &tag);
void handleTorrentSavingModeChanged(TorrentHandleImpl *const torrent);
void handleTorrentMetadataReceived(TorrentHandleImpl *const torrent);
void handleTorrentPaused(TorrentHandleImpl *const torrent);
void handleTorrentResumed(TorrentHandleImpl *const torrent);
void handleTorrentChecked(TorrentHandleImpl *const torrent);
void handleTorrentFinished(TorrentHandleImpl *const torrent);
void handleTorrentTrackersAdded(TorrentHandleImpl *const torrent, const QVector<TrackerEntry> &newTrackers);
void handleTorrentTrackersRemoved(TorrentHandleImpl *const torrent, const QVector<TrackerEntry> &deletedTrackers);
void handleTorrentTrackersChanged(TorrentHandleImpl *const torrent);
void handleTorrentUrlSeedsAdded(TorrentHandleImpl *const torrent, const QVector<QUrl> &newUrlSeeds);
void handleTorrentUrlSeedsRemoved(TorrentHandleImpl *const torrent, const QVector<QUrl> &urlSeeds);
void handleTorrentResumeDataReady(TorrentHandleImpl *const torrent, const std::shared_ptr<lt::entry> &data);
void handleTorrentTrackerReply(TorrentHandleImpl *const torrent, const QString &trackerUrl);
void handleTorrentTrackerWarning(TorrentHandleImpl *const torrent, const QString &trackerUrl);
void handleTorrentTrackerError(TorrentHandleImpl *const torrent, const QString &trackerUrl);
// Torrent interface
void handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent);
void handleTorrentShareLimitChanged(TorrentImpl *const torrent);
void handleTorrentNameChanged(TorrentImpl *const torrent);
void handleTorrentSavePathChanged(TorrentImpl *const torrent);
void handleTorrentCategoryChanged(TorrentImpl *const torrent, const QString &oldCategory);
void handleTorrentTagAdded(TorrentImpl *const torrent, const QString &tag);
void handleTorrentTagRemoved(TorrentImpl *const torrent, const QString &tag);
void handleTorrentSavingModeChanged(TorrentImpl *const torrent);
void handleTorrentMetadataReceived(TorrentImpl *const torrent);
void handleTorrentPaused(TorrentImpl *const torrent);
void handleTorrentResumed(TorrentImpl *const torrent);
void handleTorrentChecked(TorrentImpl *const torrent);
void handleTorrentFinished(TorrentImpl *const torrent);
void handleTorrentTrackersAdded(TorrentImpl *const torrent, const QVector<TrackerEntry> &newTrackers);
void handleTorrentTrackersRemoved(TorrentImpl *const torrent, const QVector<TrackerEntry> &deletedTrackers);
void handleTorrentTrackersChanged(TorrentImpl *const torrent);
void handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QVector<QUrl> &newUrlSeeds);
void handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVector<QUrl> &urlSeeds);
void handleTorrentResumeDataReady(TorrentImpl *const torrent, const std::shared_ptr<lt::entry> &data);
void handleTorrentTrackerReply(TorrentImpl *const torrent, const QString &trackerUrl);
void handleTorrentTrackerWarning(TorrentImpl *const torrent, const QString &trackerUrl);
void handleTorrentTrackerError(TorrentImpl *const torrent, const QString &trackerUrl);
bool addMoveTorrentStorageJob(TorrentHandleImpl *torrent, const QString &newPath, MoveStorageMode mode);
bool addMoveTorrentStorageJob(TorrentImpl *torrent, const QString &newPath, MoveStorageMode mode);
void findIncompleteFiles(const TorrentInfo &torrentInfo, const QString &savePath) const;
@@ -503,39 +504,37 @@ namespace BitTorrent
void categoryRemoved(const QString &categoryName);
void downloadFromUrlFailed(const QString &url, const QString &reason);
void downloadFromUrlFinished(const QString &url);
void fullDiskError(TorrentHandle *torrent, const QString &msg);
void fullDiskError(Torrent *torrent, const QString &msg);
void IPFilterParsed(bool error, int ruleCount);
void loadTorrentFailed(const QString &error);
void metadataDownloaded(const TorrentInfo &info);
void recursiveTorrentDownloadPossible(TorrentHandle *torrent);
void recursiveTorrentDownloadPossible(Torrent *torrent);
void speedLimitModeChanged(bool alternative);
void statsUpdated();
void subcategoriesSupportChanged();
void tagAdded(const QString &tag);
void tagRemoved(const QString &tag);
void torrentAboutToBeRemoved(TorrentHandle *torrent);
void torrentAdded(TorrentHandle *torrent);
void torrentCategoryChanged(TorrentHandle *torrent, const QString &oldCategory);
void torrentFinished(TorrentHandle *torrent);
void torrentFinishedChecking(TorrentHandle *torrent);
void torrentLoaded(TorrentHandle *torrent);
void torrentMetadataReceived(TorrentHandle *torrent);
void torrentPaused(TorrentHandle *torrent);
void torrentResumed(TorrentHandle *torrent);
void torrentSavePathChanged(TorrentHandle *torrent);
void torrentSavingModeChanged(TorrentHandle *torrent);
void torrentStorageMoveFailed(TorrentHandle *torrent, const QString &targetPath, const QString &error);
void torrentStorageMoveFinished(TorrentHandle *torrent, const QString &newPath);
void torrentsUpdated(const QVector<TorrentHandle *> &torrents);
void torrentTagAdded(TorrentHandle *torrent, const QString &tag);
void torrentTagRemoved(TorrentHandle *torrent, const QString &tag);
void trackerError(TorrentHandle *torrent, const QString &tracker);
void trackerlessStateChanged(TorrentHandle *torrent, bool trackerless);
void trackersAdded(TorrentHandle *torrent, const QVector<TrackerEntry> &trackers);
void trackersChanged(TorrentHandle *torrent);
void trackersRemoved(TorrentHandle *torrent, const QVector<TrackerEntry> &trackers);
void trackerSuccess(TorrentHandle *torrent, const QString &tracker);
void trackerWarning(TorrentHandle *torrent, const QString &tracker);
void torrentAboutToBeRemoved(Torrent *torrent);
void torrentAdded(Torrent *torrent);
void torrentCategoryChanged(Torrent *torrent, const QString &oldCategory);
void torrentFinished(Torrent *torrent);
void torrentFinishedChecking(Torrent *torrent);
void torrentLoaded(Torrent *torrent);
void torrentMetadataReceived(Torrent *torrent);
void torrentPaused(Torrent *torrent);
void torrentResumed(Torrent *torrent);
void torrentSavePathChanged(Torrent *torrent);
void torrentSavingModeChanged(Torrent *torrent);
void torrentsUpdated(const QVector<Torrent *> &torrents);
void torrentTagAdded(Torrent *torrent, const QString &tag);
void torrentTagRemoved(Torrent *torrent, const QString &tag);
void trackerError(Torrent *torrent, const QString &tracker);
void trackerlessStateChanged(Torrent *torrent, bool trackerless);
void trackersAdded(Torrent *torrent, const QVector<TrackerEntry> &trackers);
void trackersChanged(Torrent *torrent);
void trackersRemoved(Torrent *torrent, const QVector<TrackerEntry> &trackers);
void trackerSuccess(Torrent *torrent, const QString &tracker);
void trackerWarning(Torrent *torrent, const QString &tracker);
private slots:
void configureDeferred();
@@ -602,10 +601,10 @@ namespace BitTorrent
bool loadTorrentResumeData(const QByteArray &data, const TorrentInfo &metadata, LoadTorrentParams &torrentParams);
bool loadTorrent(LoadTorrentParams params);
LoadTorrentParams initLoadTorrentParams(const AddTorrentParams &addTorrentParams);
bool addTorrent_impl(const AddTorrentParams &addTorrentParams, const MagnetUri &magnetUri, TorrentInfo torrentInfo = TorrentInfo());
bool addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source, const AddTorrentParams &addTorrentParams);
void updateSeedingLimitTimer();
void exportTorrentFile(const TorrentHandle *torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
void exportTorrentFile(const Torrent *torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
void handleAlert(const lt::alert *a);
void dispatchTorrentAlert(const lt::alert *a);
@@ -630,7 +629,7 @@ namespace BitTorrent
void handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert *p);
void handleSocks5Alert(const lt::socks5_alert *p) const;
void createTorrentHandle(const lt::torrent_handle &nativeHandle);
void createTorrent(const lt::torrent_handle &nativeHandle);
void saveResumeData();
void saveTorrentsQueue();
@@ -772,7 +771,7 @@ namespace BitTorrent
QSet<InfoHash> m_downloadedMetadata;
QHash<InfoHash, TorrentHandleImpl *> m_torrents;
QHash<InfoHash, TorrentImpl *> m_torrents;
QHash<InfoHash, LoadTorrentParams> m_loadingTorrents;
QHash<QString, AddTorrentParams> m_downloadedTorrents;
QHash<InfoHash, RemovingTorrentData> m_removingTorrents;

View File

@@ -27,7 +27,7 @@
* exception statement from your version.
*/
#include "torrenthandle.h"
#include "torrent.h"
#include <type_traits>
@@ -40,33 +40,33 @@ namespace BitTorrent
return ::qHash(static_cast<std::underlying_type_t<TorrentState>>(key), seed);
}
// TorrentHandle
// Torrent
const qreal TorrentHandle::USE_GLOBAL_RATIO = -2.;
const qreal TorrentHandle::NO_RATIO_LIMIT = -1.;
const qreal Torrent::USE_GLOBAL_RATIO = -2.;
const qreal Torrent::NO_RATIO_LIMIT = -1.;
const int TorrentHandle::USE_GLOBAL_SEEDING_TIME = -2;
const int TorrentHandle::NO_SEEDING_TIME_LIMIT = -1;
const int Torrent::USE_GLOBAL_SEEDING_TIME = -2;
const int Torrent::NO_SEEDING_TIME_LIMIT = -1;
const qreal TorrentHandle::MAX_RATIO = 9999.;
const int TorrentHandle::MAX_SEEDING_TIME = 525600;
const qreal Torrent::MAX_RATIO = 9999.;
const int Torrent::MAX_SEEDING_TIME = 525600;
bool TorrentHandle::isResumed() const
bool Torrent::isResumed() const
{
return !isPaused();
}
qlonglong TorrentHandle::remainingSize() const
qlonglong Torrent::remainingSize() const
{
return wantedSize() - completedSize();
}
void TorrentHandle::toggleSequentialDownload()
void Torrent::toggleSequentialDownload()
{
setSequentialDownload(!isSequentialDownload());
}
void TorrentHandle::toggleFirstLastPiecePriority()
void Torrent::toggleFirstLastPiecePriority()
{
setFirstLastPiecePriority(!hasFirstLastPiecePriority());
}

View File

@@ -33,6 +33,8 @@
#include <QString>
#include <QtContainerFwd>
#include "abstractfilestorage.h"
class QBitArray;
class QDateTime;
class QUrl;
@@ -89,7 +91,7 @@ namespace BitTorrent
uint qHash(TorrentState key, uint seed);
class TorrentHandle
class Torrent : public AbstractFileStorage
{
public:
static const qreal USE_GLOBAL_RATIO;
@@ -101,7 +103,7 @@ namespace BitTorrent
static const qreal MAX_RATIO;
static const int MAX_SEEDING_TIME;
virtual ~TorrentHandle() = default;
virtual ~Torrent() = default;
virtual InfoHash hash() const = 0;
virtual QString name() const = 0;
@@ -177,7 +179,6 @@ namespace BitTorrent
virtual bool removeTag(const QString &tag) = 0;
virtual void removeAllTags() = 0;
virtual int filesCount() const = 0;
virtual int piecesCount() const = 0;
virtual int piecesHave() const = 0;
virtual qreal progress() const = 0;
@@ -185,9 +186,6 @@ namespace BitTorrent
virtual qreal ratioLimit() const = 0;
virtual int seedingTimeLimit() const = 0;
virtual QString filePath(int index) const = 0;
virtual QString fileName(int index) const = 0;
virtual qlonglong fileSize(int index) const = 0;
virtual QStringList absoluteFilePaths() const = 0;
virtual QVector<DownloadPriority> filePriorities() const = 0;
@@ -238,6 +236,9 @@ namespace BitTorrent
virtual int downloadLimit() const = 0;
virtual int uploadLimit() const = 0;
virtual bool superSeeding() const = 0;
virtual bool isDHTDisabled() const = 0;
virtual bool isPEXDisabled() const = 0;
virtual bool isLSDDisabled() const = 0;
virtual QVector<PeerInfo> peers() const = 0;
virtual QBitArray pieces() const = 0;
virtual QBitArray downloadingPieces() const = 0;
@@ -270,13 +271,15 @@ namespace BitTorrent
virtual void forceReannounce(int index = -1) = 0;
virtual void forceDHTAnnounce() = 0;
virtual void forceRecheck() = 0;
virtual void renameFile(int index, const QString &name) = 0;
virtual void prioritizeFiles(const QVector<DownloadPriority> &priorities) = 0;
virtual void setRatioLimit(qreal limit) = 0;
virtual void setSeedingTimeLimit(int limit) = 0;
virtual void setUploadLimit(int limit) = 0;
virtual void setDownloadLimit(int limit) = 0;
virtual void setSuperSeeding(bool enable) = 0;
virtual void setDHTDisabled(bool disable) = 0;
virtual void setPEXDisabled(bool disable) = 0;
virtual void setLSDDisabled(bool disable) = 0;
virtual void flushCache() const = 0;
virtual void addTrackers(const QVector<TrackerEntry> &trackers) = 0;
virtual void replaceTrackers(const QVector<TrackerEntry> &trackers) = 0;

View File

@@ -45,6 +45,7 @@
#include "base/utils/fs.h"
#include "base/utils/io.h"
#include "base/utils/string.h"
#include "base/version.h"
#include "ltunderlyingtype.h"
namespace

View File

@@ -46,7 +46,7 @@
#include "infohash.h"
#include "speedmonitor.h"
#include "torrenthandle.h"
#include "torrent.h"
#include "torrentinfo.h"
namespace BitTorrent
@@ -69,8 +69,8 @@ namespace BitTorrent
bool paused = false;
qreal ratioLimit = TorrentHandle::USE_GLOBAL_RATIO;
int seedingTimeLimit = TorrentHandle::USE_GLOBAL_SEEDING_TIME;
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
bool restored = false; // is existing torrent job?
};
@@ -87,15 +87,15 @@ namespace BitTorrent
HandleMetadata
};
class TorrentHandleImpl final : public QObject, public TorrentHandle
class TorrentImpl final : public QObject, public Torrent
{
Q_DISABLE_COPY(TorrentHandleImpl)
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentHandleImpl)
Q_DISABLE_COPY(TorrentImpl)
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentImpl)
public:
TorrentHandleImpl(Session *session, lt::session *nativeSession
TorrentImpl(Session *session, lt::session *nativeSession
, const lt::torrent_handle &nativeHandle, const LoadTorrentParams &params);
~TorrentHandleImpl() override;
~TorrentImpl() override;
bool isValid() const;
@@ -191,6 +191,9 @@ namespace BitTorrent
int downloadLimit() const override;
int uploadLimit() const override;
bool superSeeding() const override;
bool isDHTDisabled() const override;
bool isPEXDisabled() const override;
bool isLSDDisabled() const override;
QVector<PeerInfo> peers() const override;
QBitArray pieces() const override;
QBitArray downloadingPieces() const override;
@@ -217,13 +220,16 @@ namespace BitTorrent
void forceReannounce(int index = -1) override;
void forceDHTAnnounce() override;
void forceRecheck() override;
void renameFile(int index, const QString &name) override;
void renameFile(int index, const QString &path) override;
void prioritizeFiles(const QVector<DownloadPriority> &priorities) override;
void setRatioLimit(qreal limit) override;
void setSeedingTimeLimit(int limit) override;
void setUploadLimit(int limit) override;
void setDownloadLimit(int limit) override;
void setSuperSeeding(bool enable) override;
void setDHTDisabled(bool disable) override;
void setPEXDisabled(bool disable) override;
void setLSDDisabled(bool disable) override;
void flushCache() const override;
void addTrackers(const QVector<TrackerEntry> &trackers) override;
void replaceTrackers(const QVector<TrackerEntry> &trackers) override;
@@ -285,6 +291,7 @@ namespace BitTorrent
void applyFirstLastPiecePriority(bool enabled, const QVector<DownloadPriority> &updatedFilePrio = {});
void endReceivedMetadataHandling(const QString &savePath, const QStringList &fileNames);
void reload();
Session *const m_session;
lt::session *m_nativeSession;

View File

@@ -34,6 +34,7 @@
#include <QtContainerFwd>
#include "base/indexrange.h"
#include "abstractfilestorage.h"
#include "torrentcontentlayout.h"
class QByteArray;
@@ -46,7 +47,7 @@ namespace BitTorrent
class InfoHash;
class TrackerEntry;
class TorrentInfo
class TorrentInfo final : public AbstractFileStorage
{
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
@@ -68,15 +69,15 @@ namespace BitTorrent
QString comment() const;
bool isPrivate() const;
qlonglong totalSize() const;
int filesCount() const;
int filesCount() const override;
int pieceLength() const;
int pieceLength(int index) const;
int piecesCount() const;
QString filePath(int index) const;
QString filePath(int index) const override;
QStringList filePaths() const;
QString fileName(int index) const;
QString fileName(int index) const override;
QString origFilePath(int index) const;
qlonglong fileSize(int index) const;
qlonglong fileSize(int index) const override;
qlonglong fileOffset(int index) const;
QVector<TrackerEntry> trackers() const;
QVector<QUrl> urlSeeds() const;
@@ -91,7 +92,7 @@ namespace BitTorrent
PieceRange filePieces(const QString &file) const;
PieceRange filePieces(int fileIndex) const;
void renameFile(int index, const QString &newPath);
void renameFile(int index, const QString &newPath) override;
QString rootFolder() const;
bool hasRootFolder() const;

View File

@@ -37,8 +37,7 @@ class IndexInterval
public:
using IndexType = Index;
// TODO: add constexpr when using C++17
IndexInterval(const IndexType first, const IndexType last)
constexpr IndexInterval(const IndexType first, const IndexType last)
: m_first {first}
, m_last {last}
{

View File

@@ -34,6 +34,7 @@
#include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/version.h"
using namespace Net;

View File

@@ -64,15 +64,15 @@ ProxyConfigurationManager *ProxyConfigurationManager::m_instance = nullptr;
ProxyConfigurationManager::ProxyConfigurationManager(QObject *parent)
: QObject(parent)
{
m_isProxyOnlyForTorrents = settings()->loadValue(KEY_ONLY_FOR_TORRENTS, false).toBool();
m_isProxyOnlyForTorrents = settings()->loadValue(KEY_ONLY_FOR_TORRENTS, false);
m_config.type = static_cast<ProxyType>(
settings()->loadValue(KEY_TYPE, static_cast<int>(ProxyType::None)).toInt());
settings()->loadValue(KEY_TYPE, static_cast<int>(ProxyType::None)));
if ((m_config.type < ProxyType::None) || (m_config.type > ProxyType::SOCKS4))
m_config.type = ProxyType::None;
m_config.ip = settings()->loadValue(KEY_IP, "0.0.0.0").toString();
m_config.port = static_cast<ushort>(settings()->loadValue(KEY_PORT, 8080).toUInt());
m_config.username = settings()->loadValue(KEY_USERNAME).toString();
m_config.password = settings()->loadValue(KEY_PASSWORD).toString();
m_config.ip = settings()->loadValue<QString>(KEY_IP, "0.0.0.0");
m_config.port = settings()->loadValue<ushort>(KEY_PORT, 8080);
m_config.username = settings()->loadValue<QString>(KEY_USERNAME);
m_config.password = settings()->loadValue<QString>(KEY_PASSWORD);
configureProxy();
}

View File

@@ -1241,26 +1241,6 @@ void Preferences::setMainLastDir(const QString &path)
setValue("MainWindowLastDir", path);
}
QSize Preferences::getPrefSize() const
{
return value("Preferences/State/size").toSize();
}
void Preferences::setPrefSize(const QSize &size)
{
setValue("Preferences/State/size", size);
}
QStringList Preferences::getPrefHSplitterSizes() const
{
return value("Preferences/State/hSplitterSizes").toStringList();
}
void Preferences::setPrefHSplitterSizes(const QStringList &sizes)
{
setValue("Preferences/State/hSplitterSizes", sizes);
}
QByteArray Preferences::getPeerListState() const
{
return value("TorrentProperties/Peers/qt5/PeerListState").toByteArray();

View File

@@ -329,10 +329,6 @@ public:
void setMainVSplitterState(const QByteArray &state);
QString getMainLastDir() const;
void setMainLastDir(const QString &path);
QSize getPrefSize() const;
void setPrefSize(const QSize &size);
QStringList getPrefHSplitterSizes() const;
void setPrefHSplitterSizes(const QStringList &sizes);
QByteArray getPeerListState() const;
void setPeerListState(const QByteArray &state);
QString getPropSplitterSizes() const;

View File

@@ -83,7 +83,7 @@ QString Private::DefaultProfile::dataLocation() const
const QString dataDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ QLatin1Char('/') + profileName() + QLatin1Char('/');
if (QDir(legacyDir).exists())
if (!QDir(dataDir).exists() && QDir(legacyDir).exists())
{
qWarning("The legacy data directory '%s' is used. It is recommended to move its content to '%s'",
qUtf8Printable(legacyDir), qUtf8Printable(dataDir));

View File

@@ -47,7 +47,6 @@
#include "../logger.h"
#include "../profile.h"
#include "../settingsstorage.h"
#include "../tristatebool.h"
#include "../utils/fs.h"
#include "rss_article.h"
#include "rss_autodownloadrule.h"
@@ -105,7 +104,7 @@ QString computeSmartFilterRegex(const QStringList &filters)
}
AutoDownloader::AutoDownloader()
: m_processingEnabled(SettingsStorage::instance()->loadValue(SettingsKey_ProcessingEnabled, false).toBool())
: m_processingEnabled(SettingsStorage::instance()->loadValue(SettingsKey_ProcessingEnabled, false))
, m_processingTimer(new QTimer(this))
, m_ioThread(new QThread(this))
{
@@ -290,7 +289,7 @@ void AutoDownloader::importRulesFromLegacyFormat(const QByteArray &data)
QStringList AutoDownloader::smartEpisodeFilters() const
{
const QVariant filtersSetting = SettingsStorage::instance()->loadValue(SettingsKey_SmartEpisodeFilter);
const auto filtersSetting = SettingsStorage::instance()->loadValue<QVariant>(SettingsKey_SmartEpisodeFilter);
if (filtersSetting.isNull())
{
@@ -323,7 +322,7 @@ void AutoDownloader::setSmartEpisodeFilters(const QStringList &filters)
bool AutoDownloader::downloadRepacks() const
{
return SettingsStorage::instance()->loadValue(SettingsKey_DownloadRepacks, true).toBool();
return SettingsStorage::instance()->loadValue(SettingsKey_DownloadRepacks, true);
}
void AutoDownloader::setDownloadRepacks(const bool downloadRepacks)
@@ -398,7 +397,7 @@ void AutoDownloader::processJob(const QSharedPointer<ProcessingJob> &job)
params.addPaused = rule.addPaused();
params.contentLayout = rule.torrentContentLayout();
if (!rule.savePath().isEmpty())
params.useAutoTMM = TriStateBool::False;
params.useAutoTMM = false;
const auto torrentURL = job->articleData.value(Article::KeyTorrentURL).toString();
BitTorrent::Session::instance()->addTorrent(torrentURL, params);

View File

@@ -42,7 +42,6 @@
#include "base/global.h"
#include "base/preferences.h"
#include "base/tristatebool.h"
#include "base/utils/fs.h"
#include "base/utils/string.h"
#include "rss_article.h"
@@ -51,56 +50,49 @@
namespace
{
TriStateBool jsonValueToTriStateBool(const QJsonValue &jsonVal)
std::optional<bool> toOptionalBool(const QJsonValue &jsonVal)
{
if (jsonVal.isBool())
return TriStateBool(jsonVal.toBool());
return jsonVal.toBool();
if (!jsonVal.isNull())
qDebug() << Q_FUNC_INFO << "Incorrect value" << jsonVal.toVariant();
return TriStateBool::Undefined;
return std::nullopt;
}
QJsonValue triStateBoolToJsonValue(const TriStateBool triStateBool)
QJsonValue toJsonValue(const std::optional<bool> boolValue)
{
switch (static_cast<signed char>(triStateBool))
{
case 0: return false;
case 1: return true;
default: return {};
}
return boolValue.has_value() ? *boolValue : QJsonValue {};
}
TriStateBool addPausedLegacyToTriStateBool(const int val)
std::optional<bool> addPausedLegacyToOptionalBool(const int val)
{
switch (val)
{
case 1: return TriStateBool::True; // always
case 2: return TriStateBool::False; // never
default: return TriStateBool::Undefined; // default
case 1:
return true; // always
case 2:
return false; // never
default:
return std::nullopt; // default
}
}
int triStateBoolToAddPausedLegacy(const TriStateBool triStateBool)
int toAddPausedLegacy(const std::optional<bool> boolValue)
{
switch (static_cast<signed char>(triStateBool))
{
case 0: return 2; // never
case 1: return 1; // always
default: return 0; // default
}
if (!boolValue.has_value())
return 0; // default
return (*boolValue ? 1 /* always */ : 2 /* never */);
}
boost::optional<BitTorrent::TorrentContentLayout> jsonValueToContentLayout(const QJsonValue &jsonVal)
std::optional<BitTorrent::TorrentContentLayout> jsonValueToContentLayout(const QJsonValue &jsonVal)
{
const QString str = jsonVal.toString();
if (str.isEmpty())
return {};
return std::nullopt;
return Utils::String::toEnum(str, BitTorrent::TorrentContentLayout::Original);
}
QJsonValue contentLayoutToJsonValue(const boost::optional<BitTorrent::TorrentContentLayout> contentLayout)
QJsonValue contentLayoutToJsonValue(const std::optional<BitTorrent::TorrentContentLayout> contentLayout)
{
if (!contentLayout)
return {};
@@ -142,8 +134,8 @@ namespace RSS
QString savePath;
QString category;
TriStateBool addPaused = TriStateBool::Undefined;
boost::optional<BitTorrent::TorrentContentLayout> contentLayout;
std::optional<bool> addPaused;
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
bool smartFilter = false;
QStringList previouslyMatchedEpisodes;
@@ -477,7 +469,7 @@ QJsonObject AutoDownloadRule::toJsonObject() const
, {Str_AssignedCategory, assignedCategory()}
, {Str_LastMatch, lastMatch().toString(Qt::RFC2822Date)}
, {Str_IgnoreDays, ignoreDays()}
, {Str_AddPaused, triStateBoolToJsonValue(addPaused())}
, {Str_AddPaused, toJsonValue(addPaused())}
, {Str_ContentLayout, contentLayoutToJsonValue(torrentContentLayout())}
, {Str_SmartFilter, useSmartFilter()}
, {Str_PreviouslyMatched, QJsonArray::fromStringList(previouslyMatchedEpisodes())}};
@@ -494,7 +486,7 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
rule.setEnabled(jsonObj.value(Str_Enabled).toBool(true));
rule.setSavePath(jsonObj.value(Str_SavePath).toString());
rule.setCategory(jsonObj.value(Str_AssignedCategory).toString());
rule.setAddPaused(jsonValueToTriStateBool(jsonObj.value(Str_AddPaused)));
rule.setAddPaused(toOptionalBool(jsonObj.value(Str_AddPaused)));
// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
// === BEGIN DEPRECATED CODE === //
@@ -504,12 +496,14 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
}
else
{
const TriStateBool createSubfolder = jsonValueToTriStateBool(jsonObj.value(Str_CreateSubfolder));
boost::optional<BitTorrent::TorrentContentLayout> contentLayout;
if (createSubfolder == TriStateBool::True)
contentLayout = BitTorrent::TorrentContentLayout::Original;
else if (createSubfolder == TriStateBool::False)
contentLayout = BitTorrent::TorrentContentLayout::NoSubfolder;
const std::optional<bool> createSubfolder = toOptionalBool(jsonObj.value(Str_CreateSubfolder));
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
if (createSubfolder.has_value())
{
contentLayout = (*createSubfolder
? BitTorrent::TorrentContentLayout::Original
: BitTorrent::TorrentContentLayout::NoSubfolder);
}
rule.setTorrentContentLayout(contentLayout);
}
@@ -556,7 +550,7 @@ QVariantHash AutoDownloadRule::toLegacyDict() const
{"enabled", isEnabled()},
{"category_assigned", assignedCategory()},
{"use_regex", useRegex()},
{"add_paused", triStateBoolToAddPausedLegacy(addPaused())},
{"add_paused", toAddPausedLegacy(addPaused())},
{"episode_filter", episodeFilter()},
{"last_match", lastMatch()},
{"ignore_days", ignoreDays()}};
@@ -574,7 +568,7 @@ AutoDownloadRule AutoDownloadRule::fromLegacyDict(const QVariantHash &dict)
rule.setEnabled(dict.value("enabled", false).toBool());
rule.setSavePath(dict.value("save_path").toString());
rule.setCategory(dict.value("category_assigned").toString());
rule.setAddPaused(addPausedLegacyToTriStateBool(dict.value("add_paused").toInt()));
rule.setAddPaused(addPausedLegacyToOptionalBool(dict.value("add_paused").toInt()));
rule.setLastMatch(dict.value("last_match").toDateTime());
rule.setIgnoreDays(dict.value("ignore_days").toInt());
@@ -639,22 +633,22 @@ void AutoDownloadRule::setSavePath(const QString &savePath)
m_dataPtr->savePath = Utils::Fs::toUniformPath(savePath);
}
TriStateBool AutoDownloadRule::addPaused() const
std::optional<bool> AutoDownloadRule::addPaused() const
{
return m_dataPtr->addPaused;
}
void AutoDownloadRule::setAddPaused(const TriStateBool addPaused)
void AutoDownloadRule::setAddPaused(const std::optional<bool> addPaused)
{
m_dataPtr->addPaused = addPaused;
}
boost::optional<BitTorrent::TorrentContentLayout> AutoDownloadRule::torrentContentLayout() const
std::optional<BitTorrent::TorrentContentLayout> AutoDownloadRule::torrentContentLayout() const
{
return m_dataPtr->contentLayout;
}
void AutoDownloadRule::setTorrentContentLayout(const boost::optional<BitTorrent::TorrentContentLayout> contentLayout)
void AutoDownloadRule::setTorrentContentLayout(const std::optional<BitTorrent::TorrentContentLayout> contentLayout)
{
m_dataPtr->contentLayout = contentLayout;
}

View File

@@ -29,7 +29,7 @@
#pragma once
#include <boost/optional.hpp>
#include <optional>
#include <QSharedDataPointer>
#include <QVariant>
@@ -40,8 +40,6 @@ class QDateTime;
class QJsonObject;
class QRegularExpression;
class TriStateBool;
namespace RSS
{
struct AutoDownloadRuleData;
@@ -81,10 +79,10 @@ namespace RSS
QString savePath() const;
void setSavePath(const QString &savePath);
TriStateBool addPaused() const;
void setAddPaused(TriStateBool addPaused);
boost::optional<BitTorrent::TorrentContentLayout> torrentContentLayout() const;
void setTorrentContentLayout(boost::optional<BitTorrent::TorrentContentLayout> contentLayout);
std::optional<bool> addPaused() const;
void setAddPaused(std::optional<bool> addPaused);
std::optional<BitTorrent::TorrentContentLayout> torrentContentLayout() const;
void setTorrentContentLayout(std::optional<BitTorrent::TorrentContentLayout> contentLayout);
QString assignedCategory() const;
void setCategory(const QString &category);

View File

@@ -63,10 +63,10 @@ using namespace RSS;
QPointer<Session> Session::m_instance = nullptr;
Session::Session()
: m_processingEnabled(SettingsStorage::instance()->loadValue(SettingsKey_ProcessingEnabled, false).toBool())
: m_processingEnabled(SettingsStorage::instance()->loadValue(SettingsKey_ProcessingEnabled, false))
, m_workingThread(new QThread(this))
, m_refreshInterval(SettingsStorage::instance()->loadValue(SettingsKey_RefreshInterval, 30).toInt())
, m_maxArticlesPerFeed(SettingsStorage::instance()->loadValue(SettingsKey_MaxArticlesPerFeed, 50).toInt())
, m_refreshInterval(SettingsStorage::instance()->loadValue(SettingsKey_RefreshInterval, 30))
, m_maxArticlesPerFeed(SettingsStorage::instance()->loadValue(SettingsKey_MaxArticlesPerFeed, 50))
{
Q_ASSERT(!m_instance); // only one instance is allowed
m_instance = this;
@@ -362,8 +362,8 @@ void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
void Session::loadLegacy()
{
const QStringList legacyFeedPaths = SettingsStorage::instance()->loadValue("Rss/streamList").toStringList();
const QStringList feedAliases = SettingsStorage::instance()->loadValue("Rss/streamAlias").toStringList();
const auto legacyFeedPaths = SettingsStorage::instance()->loadValue<QStringList>("Rss/streamList");
const auto feedAliases = SettingsStorage::instance()->loadValue<QStringList>("Rss/streamAlias");
if (legacyFeedPaths.size() != feedAliases.size())
{
Logger::instance()->addMessage("Corrupted RSS list, not loading it.", Log::WARNING);

View File

@@ -366,12 +366,12 @@ void ScanFoldersModel::addTorrentsToSession(const QStringList &pathList)
if (downloadInWatchFolder(file))
{
params.savePath = QFileInfo(file).dir().path();
params.useAutoTMM = TriStateBool::False;
params.useAutoTMM = false;
}
else if (!downloadInDefaultFolder(file))
{
params.savePath = downloadPathTorrentFolder(file);
params.useAutoTMM = TriStateBool::False;
params.useAutoTMM = false;
}
if (file.endsWith(".magnet", Qt::CaseInsensitive))

View File

@@ -153,8 +153,7 @@ namespace
SettingsStorage *SettingsStorage::m_instance = nullptr;
SettingsStorage::SettingsStorage()
: m_data{TransactionalSettings(QLatin1String("qBittorrent")).read()}
, m_dirty(false)
: m_data {TransactionalSettings(QLatin1String("qBittorrent")).read()}
{
m_timer.setSingleShot(true);
m_timer.setInterval(5 * 1000);
@@ -200,14 +199,14 @@ bool SettingsStorage::save()
return true;
}
QVariant SettingsStorage::loadValue(const QString &key, const QVariant &defaultValue) const
QVariant SettingsStorage::loadValueImpl(const QString &key, const QVariant &defaultValue) const
{
const QString realKey = mapKey(key);
const QReadLocker locker(&m_lock);
return m_data.value(realKey, defaultValue);
}
void SettingsStorage::storeValue(const QString &key, const QVariant &value)
void SettingsStorage::storeValueImpl(const QString &key, const QVariant &value)
{
const QString realKey = mapKey(key);
const QWriteLocker locker(&m_lock);
@@ -295,7 +294,11 @@ QString TransactionalSettings::deserialize(const QString &name, QVariantHash &da
// 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.
for (const QString &key : asConst(settings->allKeys()))
data.insert(key, settings->value(key));
{
const QVariant value = settings->value(key);
if (value.isValid())
data[key] = value;
}
return settings->fileName();
}

View File

@@ -29,11 +29,15 @@
#pragma once
#include <type_traits>
#include <QObject>
#include <QReadWriteLock>
#include <QTimer>
#include <QVariantHash>
#include "utils/string.h"
class SettingsStorage : public QObject
{
Q_OBJECT
@@ -45,18 +49,48 @@ public:
static void freeInstance();
static SettingsStorage *instance();
QVariant loadValue(const QString &key, const QVariant &defaultValue = {}) const;
void storeValue(const QString &key, const QVariant &value);
template <typename T>
T loadValue(const QString &key, const T &defaultValue = {}) const
{
if constexpr (std::is_enum_v<T>)
{
const auto value = loadValueImpl(key).toString();
return Utils::String::toEnum(value, defaultValue);
}
else if constexpr (std::is_same_v<T, QVariant>)
{
return loadValueImpl(key, defaultValue);
}
else
{
const QVariant value = loadValueImpl(key);
// check if retrieved value is convertible to T
return value.template canConvert<T>() ? value.template value<T>() : defaultValue;
}
}
template <typename T>
void storeValue(const QString &key, const T &value)
{
if constexpr (std::is_enum_v<T>)
storeValueImpl(key, Utils::String::fromEnum(value));
else
storeValueImpl(key, value);
}
void removeValue(const QString &key);
public slots:
bool save();
private:
QVariant loadValueImpl(const QString &key, const QVariant &defaultValue = {}) const;
void storeValueImpl(const QString &key, const QVariant &value);
static SettingsStorage *m_instance;
bool m_dirty = false;
QVariantHash m_data;
bool m_dirty;
QTimer m_timer;
mutable QReadWriteLock m_lock;
};

View File

@@ -28,82 +28,81 @@
#pragma once
#include <type_traits>
#include <QMetaEnum>
#include <QString>
#include "settingsstorage.h"
#include "utils/string.h"
// This is a thin/handy wrapper over `SettingsStorage`. Use it when store/load value
// rarely occurs, otherwise use `CachedSettingValue`.
template <typename T>
class SettingValue
{
public:
explicit SettingValue(const char *keyName)
: m_keyName {QLatin1String {keyName}}
{
}
T get(const T &defaultValue = {}) const
{
return SettingsStorage::instance()->loadValue(m_keyName, defaultValue);
}
operator T() const
{
return get();
}
SettingValue<T> &operator=(const T &value)
{
SettingsStorage::instance()->storeValue(m_keyName, value);
return *this;
}
private:
const QString m_keyName;
};
template <typename T>
class CachedSettingValue
{
public:
explicit CachedSettingValue(const char *keyName, const T &defaultValue = T())
: m_keyName(QLatin1String(keyName))
, m_value(loadValue(defaultValue))
explicit CachedSettingValue(const char *keyName, const T &defaultValue = {})
: m_setting {keyName}
, m_cache {m_setting.get(defaultValue)}
{
}
// The signature of the ProxyFunc should be equivalent to the following:
// T proxyFunc(const T &a);
template <typename ProxyFunc>
explicit CachedSettingValue(const char *keyName, const T &defaultValue
, ProxyFunc &&proxyFunc)
: m_keyName(QLatin1String(keyName))
, m_value(proxyFunc(loadValue(defaultValue)))
explicit CachedSettingValue(const char *keyName, const T &defaultValue, ProxyFunc &&proxyFunc)
: m_setting {keyName}
, m_cache {proxyFunc(m_setting.get(defaultValue))}
{
}
T value() const
T get() const
{
return m_value;
return m_cache;
}
operator T() const
{
return value();
return get();
}
CachedSettingValue<T> &operator=(const T &newValue)
CachedSettingValue<T> &operator=(const T &value)
{
if (m_value == newValue)
if (m_cache == value)
return *this;
m_value = newValue;
storeValue(m_value);
m_setting = value;
m_cache = value;
return *this;
}
private:
// regular load/save pair
template <typename U, typename std::enable_if_t<!std::is_enum<U>::value, int> = 0>
U loadValue(const U &defaultValue)
{
return SettingsStorage::instance()->loadValue(m_keyName, defaultValue).template value<T>();
}
template <typename U, typename std::enable_if_t<!std::is_enum<U>::value, int> = 0>
void storeValue(const U &value)
{
SettingsStorage::instance()->storeValue(m_keyName, value);
}
// load/save pair for an enum
// saves literal value of the enum constant, obtained from QMetaEnum
template <typename U, typename std::enable_if_t<std::is_enum<U>::value, int> = 0>
U loadValue(const U &defaultValue)
{
return Utils::String::toEnum(SettingsStorage::instance()->loadValue(m_keyName).toString(), defaultValue);
}
template <typename U, typename std::enable_if_t<std::is_enum<U>::value, int> = 0>
void storeValue(const U &value)
{
SettingsStorage::instance()->storeValue(m_keyName, Utils::String::fromEnum(value));
}
const QString m_keyName;
T m_value;
SettingValue<T> m_setting;
T m_cache;
};

View File

@@ -73,7 +73,7 @@ void TorrentFileGuard::markAsAddedToSession()
TorrentFileGuard::AutoDeleteMode TorrentFileGuard::autoDeleteMode()
{
return autoDeleteModeSetting();
return autoDeleteModeSetting().get(AutoDeleteMode::Never);
}
void TorrentFileGuard::setAutoDeleteMode(TorrentFileGuard::AutoDeleteMode mode)
@@ -81,8 +81,8 @@ void TorrentFileGuard::setAutoDeleteMode(TorrentFileGuard::AutoDeleteMode mode)
autoDeleteModeSetting() = mode;
}
CachedSettingValue<TorrentFileGuard::AutoDeleteMode> &TorrentFileGuard::autoDeleteModeSetting()
SettingValue<TorrentFileGuard::AutoDeleteMode> &TorrentFileGuard::autoDeleteModeSetting()
{
static CachedSettingValue<AutoDeleteMode> setting("Core/AutoDeleteAddedTorrentFile", AutoDeleteMode::Never);
static SettingValue<AutoDeleteMode> setting {"Core/AutoDeleteAddedTorrentFile"};
return setting;
}

View File

@@ -31,7 +31,7 @@
#include <QObject>
#include <QString>
template <typename T> class CachedSettingValue;
template <typename T> class SettingValue;
/// Utility class to defer file deletion
class FileGuard
@@ -75,7 +75,7 @@ public:
private:
TorrentFileGuard(const QString &path, AutoDeleteMode mode);
static CachedSettingValue<AutoDeleteMode> &autoDeleteModeSetting();
static SettingValue<AutoDeleteMode> &autoDeleteModeSetting();
Q_ENUM(AutoDeleteMode)
AutoDeleteMode m_mode;

View File

@@ -29,7 +29,7 @@
#include "torrentfilter.h"
#include "bittorrent/infohash.h"
#include "bittorrent/torrenthandle.h"
#include "bittorrent/torrent.h"
const QString TorrentFilter::AnyCategory;
const InfoHashSet TorrentFilter::AnyHash {{}};
@@ -47,7 +47,7 @@ const TorrentFilter TorrentFilter::StalledUploadingTorrent(TorrentFilter::Stalle
const TorrentFilter TorrentFilter::StalledDownloadingTorrent(TorrentFilter::StalledDownloading);
const TorrentFilter TorrentFilter::ErroredTorrent(TorrentFilter::Errored);
using BitTorrent::TorrentHandle;
using BitTorrent::Torrent;
TorrentFilter::TorrentFilter(const Type type, const InfoHashSet &hashSet, const QString &category, const QString &tag)
: m_type(type)
@@ -146,14 +146,14 @@ bool TorrentFilter::setTag(const QString &tag)
return false;
}
bool TorrentFilter::match(const TorrentHandle *const torrent) const
bool TorrentFilter::match(const Torrent *const torrent) const
{
if (!torrent) return false;
return (matchState(torrent) && matchHash(torrent) && matchCategory(torrent) && matchTag(torrent));
}
bool TorrentFilter::matchState(const BitTorrent::TorrentHandle *const torrent) const
bool TorrentFilter::matchState(const BitTorrent::Torrent *const torrent) const
{
switch (m_type)
{
@@ -187,21 +187,21 @@ bool TorrentFilter::matchState(const BitTorrent::TorrentHandle *const torrent) c
}
}
bool TorrentFilter::matchHash(const BitTorrent::TorrentHandle *const torrent) const
bool TorrentFilter::matchHash(const BitTorrent::Torrent *const torrent) const
{
if (m_hashSet == AnyHash) return true;
return m_hashSet.contains(torrent->hash());
}
bool TorrentFilter::matchCategory(const BitTorrent::TorrentHandle *const torrent) const
bool TorrentFilter::matchCategory(const BitTorrent::Torrent *const torrent) const
{
if (m_category.isNull()) return true;
return (torrent->belongsToCategory(m_category));
}
bool TorrentFilter::matchTag(const BitTorrent::TorrentHandle *const torrent) const
bool TorrentFilter::matchTag(const BitTorrent::Torrent *const torrent) const
{
// Empty tag is a special value to indicate we're filtering for untagged torrents.
if (m_tag.isNull()) return true;

View File

@@ -35,7 +35,7 @@
namespace BitTorrent
{
class TorrentHandle;
class Torrent;
}
using InfoHashSet = QSet<BitTorrent::InfoHash>;
@@ -88,13 +88,13 @@ public:
bool setCategory(const QString &category);
bool setTag(const QString &tag);
bool match(const BitTorrent::TorrentHandle *torrent) const;
bool match(const BitTorrent::Torrent *torrent) const;
private:
bool matchState(const BitTorrent::TorrentHandle *torrent) const;
bool matchHash(const BitTorrent::TorrentHandle *torrent) const;
bool matchCategory(const BitTorrent::TorrentHandle *torrent) const;
bool matchTag(const BitTorrent::TorrentHandle *torrent) const;
bool matchState(const BitTorrent::Torrent *torrent) const;
bool matchHash(const BitTorrent::Torrent *torrent) const;
bool matchCategory(const BitTorrent::Torrent *torrent) const;
bool matchTag(const BitTorrent::Torrent *torrent) const;
Type m_type {All};
QString m_category;

View File

@@ -1,4 +1,4 @@
/*
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Mike Tzou
*
@@ -28,16 +28,12 @@
#pragma once
// This file must be encoded in "UTF-8 with BOM"
#ifdef _MSC_VER
#pragma execution_character_set("utf-8")
#endif
// Because of the poor handling of UTF-8 characters in MSVC (emits warning C4819),
// we put all problematic UTF-8 chars/strings in this file.
// See issue #3059 for more details (https://github.com/qbittorrent/qBittorrent/issues/3059).
const char C_COPYRIGHT[] = "©";
const char C_INEQUALITY[] = "";
const char C_INFINITY[] = "";
const char C_NON_BREAKING_SPACE[] = " ";
const char C_THIN_SPACE[] = "";
@@ -45,6 +41,7 @@ const char C_UTP[] = "μTP";
const char C_LOCALE_ARABIC[] = "عربي";
const char C_LOCALE_ARMENIAN[] = "Հայերեն";
const char C_LOCALE_AZERBAIJANI[] = "Azərbaycan dili";
const char C_LOCALE_BASQUE[] = "Euskara";
const char C_LOCALE_BULGARIAN[] = "Български";
const char C_LOCALE_BYELORUSSIAN[] = "Беларуская";
@@ -57,9 +54,10 @@ const char C_LOCALE_CZECH[] = "Čeština";
const char C_LOCALE_DANISH[] = "Dansk";
const char C_LOCALE_DUTCH[] = "Nederlands";
const char C_LOCALE_ENGLISH[] = "English";
const char C_LOCALE_ENGLISH_AUSTRALIA[] = "English(Australia)";
const char C_LOCALE_ENGLISH_UNITEDKINGDOM[] = "English(United Kingdom)";
const char C_LOCALE_ENGLISH_AUSTRALIA[] = "English (Australia)";
const char C_LOCALE_ENGLISH_UNITEDKINGDOM[] = "English (United Kingdom)";
const char C_LOCALE_ESPERANTO[] = "Esperanto";
const char C_LOCALE_ESTONIAN[] = "Eesti, eesti keel";
const char C_LOCALE_FINNISH[] = "Suomi";
const char C_LOCALE_FRENCH[] = "Français";
const char C_LOCALE_GALICIAN[] = "Galego";
@@ -74,8 +72,8 @@ const char C_LOCALE_INDONESIAN[] = "Bahasa Indonesia";
const char C_LOCALE_ITALIAN[] = "Italiano";
const char C_LOCALE_JAPANESE[] = "日本語";
const char C_LOCALE_KOREAN[] = "한글";
const char C_LOCALE_LATGALIAN[] = "latgalīšu volūda";
const char C_LOCALE_LATVIAN[] = "latviešu valoda";
const char C_LOCALE_LATGALIAN[] = "Latgalīšu volūda";
const char C_LOCALE_LATVIAN[] = "Latviešu valoda";
const char C_LOCALE_LITHUANIAN[] = "Lietuvių";
const char C_LOCALE_MALAY[] = "بهاس ملايو";
const char C_LOCALE_NORWEGIAN[] = "Norsk";
@@ -93,4 +91,4 @@ const char C_LOCALE_SWEDISH[] = "Svenska";
const char C_LOCALE_TURKISH[] = "Türkçe";
const char C_LOCALE_UKRAINIAN[] = "Українська";
const char C_LOCALE_UZBEK[] = "أۇزبېك‎";
const char C_LOCALE_VIETNAMESE[] = "tiếng Việt";
const char C_LOCALE_VIETNAMESE[] = "Tiếng Việt";

View File

@@ -33,15 +33,12 @@
class QByteArray;
namespace Utils
namespace Utils::ByteArray
{
namespace ByteArray
{
// Mimic QString::splitRef(sep, behavior)
QVector<QByteArray> splitToViews(const QByteArray &in, const QByteArray &sep, const QString::SplitBehavior behavior = QString::KeepEmptyParts);
// Mimic QString::splitRef(sep, behavior)
QVector<QByteArray> splitToViews(const QByteArray &in, const QByteArray &sep, const QString::SplitBehavior behavior = QString::KeepEmptyParts);
// Mimic QByteArray::mid(pos, len) but instead of returning a full-copy,
// we only return a partial view
const QByteArray midView(const QByteArray &in, int pos, int len = -1);
}
// Mimic QByteArray::mid(pos, len) but instead of returning a full-copy,
// we only return a partial view
const QByteArray midView(const QByteArray &in, int pos, int len = -1);
}

View File

@@ -33,21 +33,18 @@
#include "base/utils/version.h"
namespace Utils
namespace Utils::ForeignApps
{
namespace ForeignApps
struct PythonInfo
{
struct PythonInfo
{
using Version = Utils::Version<quint8, 3, 1>;
using Version = Utils::Version<quint8, 3, 1>;
bool isValid() const;
bool isSupportedVersion() const;
bool isValid() const;
bool isSupportedVersion() const;
QString executableName;
Version version;
};
QString executableName;
Version version;
};
PythonInfo pythonInfo();
}
PythonInfo pythonInfo();
}

View File

@@ -55,6 +55,7 @@
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QMimeDatabase>
#include <QStorageInfo>
#include <QRegularExpression>
@@ -76,9 +77,14 @@ QString Utils::Fs::toUniformPath(const QString &path)
*/
QString Utils::Fs::fileExtension(const QString &filename)
{
const QString ext = QString(filename).remove(QB_EXT);
const int pointIndex = ext.lastIndexOf('.');
return (pointIndex >= 0) ? ext.mid(pointIndex + 1) : QString();
const QString name = filename.endsWith(QB_EXT)
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
? filename.chopped(QB_EXT.length())
#else
? filename.left(filename.length() - QB_EXT.length())
#endif
: filename;
return QMimeDatabase().suffixForFileName(name);
}
QString Utils::Fs::fileName(const QString &filePath)
@@ -95,7 +101,7 @@ QString Utils::Fs::folderName(const QString &filePath)
const QString path = toUniformPath(filePath);
const int slashIndex = path.lastIndexOf('/');
if (slashIndex == -1)
return path;
return {};
return path.left(slashIndex);
}
@@ -267,8 +273,6 @@ bool Utils::Fs::isValidFileSystemName(const QString &name, const bool allowSepar
qint64 Utils::Fs::freeDiskSpaceOnPath(const QString &path)
{
if (path.isEmpty()) return -1;
return QStorageInfo(path).bytesAvailable();
}

View File

@@ -34,47 +34,44 @@
#include <QString>
namespace Utils
namespace Utils::Fs
{
namespace Fs
{
/**
* Converts a path to a string suitable for display.
* This function makes sure the directory separator used is consistent
* with the OS being run.
*/
QString toNativePath(const QString &path);
/**
* Converts a path to a string suitable for processing.
* This function makes sure the directory separator used is independent
* from the OS being run so it is the same on all supported platforms.
* Slash ('/') is used as "uniform" directory separator.
*/
QString toUniformPath(const QString &path);
/**
* Converts a path to a string suitable for display.
* This function makes sure the directory separator used is consistent
* with the OS being run.
*/
QString toNativePath(const QString &path);
/**
* Converts a path to a string suitable for processing.
* This function makes sure the directory separator used is independent
* from the OS being run so it is the same on all supported platforms.
* Slash ('/') is used as "uniform" directory separator.
*/
QString toUniformPath(const QString &path);
QString fileExtension(const QString &filename);
QString fileName(const QString &filePath);
QString folderName(const QString &filePath);
qint64 computePathSize(const QString &path);
bool sameFiles(const QString &path1, const QString &path2);
QString toValidFileSystemName(const QString &name, bool allowSeparators = false
, const QString &pad = QLatin1String(" "));
bool isValidFileSystemName(const QString &name, bool allowSeparators = false);
qint64 freeDiskSpaceOnPath(const QString &path);
QString branchPath(const QString &filePath, QString *removed = nullptr);
bool sameFileNames(const QString &first, const QString &second);
QString expandPath(const QString &path);
QString expandPathAbs(const QString &path);
bool isRegularFile(const QString &path);
QString fileExtension(const QString &filename);
QString fileName(const QString &filePath);
QString folderName(const QString &filePath);
qint64 computePathSize(const QString &path);
bool sameFiles(const QString &path1, const QString &path2);
QString toValidFileSystemName(const QString &name, bool allowSeparators = false
, const QString &pad = QLatin1String(" "));
bool isValidFileSystemName(const QString &name, bool allowSeparators = false);
qint64 freeDiskSpaceOnPath(const QString &path);
QString branchPath(const QString &filePath, QString *removed = nullptr);
bool sameFileNames(const QString &first, const QString &second);
QString expandPath(const QString &path);
QString expandPathAbs(const QString &path);
bool isRegularFile(const QString &path);
bool smartRemoveEmptyFolderTree(const QString &path);
bool forceRemove(const QString &filePath);
void removeDirRecursive(const QString &path);
bool smartRemoveEmptyFolderTree(const QString &path);
bool forceRemove(const QString &filePath);
void removeDirRecursive(const QString &path);
QString tempPath();
QString tempPath();
#if !defined Q_OS_HAIKU
bool isNetworkFileSystem(const QString &path);
bool isNetworkFileSystem(const QString &path);
#endif
}
}

View File

@@ -31,11 +31,8 @@
class QByteArray;
namespace Utils
namespace Utils::Gzip
{
namespace Gzip
{
QByteArray compress(const QByteArray &data, int level = 6, bool *ok = nullptr);
QByteArray decompress(const QByteArray &data, bool *ok = nullptr);
}
QByteArray compress(const QByteArray &data, int level = 6, bool *ok = nullptr);
QByteArray decompress(const QByteArray &data, bool *ok = nullptr);
}

View File

@@ -60,18 +60,3 @@ Utils::IO::FileDeviceOutputIterator &Utils::IO::FileDeviceOutputIterator::operat
}
return *this;
}
Utils::IO::FileDeviceOutputIterator &Utils::IO::FileDeviceOutputIterator::operator*()
{
return *this;
}
Utils::IO::FileDeviceOutputIterator &Utils::IO::FileDeviceOutputIterator::operator++()
{
return *this;
}
Utils::IO::FileDeviceOutputIterator &Utils::IO::FileDeviceOutputIterator::operator++(int)
{
return *this;
}

View File

@@ -34,30 +34,44 @@
class QByteArray;
class QFileDevice;
namespace Utils
namespace Utils::IO
{
namespace IO
// A wrapper class that satisfy LegacyOutputIterator requirement
class FileDeviceOutputIterator
{
// A wrapper class that satisfy LegacyOutputIterator requirement
class FileDeviceOutputIterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
public:
// std::iterator_traits
using iterator_category = std::output_iterator_tag;
using difference_type = void;
using value_type = void;
using pointer = void;
using reference = void;
explicit FileDeviceOutputIterator(QFileDevice &device, const int bufferSize = (4 * 1024));
FileDeviceOutputIterator(const FileDeviceOutputIterator &other) = default;
~FileDeviceOutputIterator();
// mimic std::ostream_iterator behavior
FileDeviceOutputIterator &operator=(char c);
constexpr FileDeviceOutputIterator &operator*()
{
public:
explicit FileDeviceOutputIterator(QFileDevice &device, const int bufferSize = (4 * 1024));
FileDeviceOutputIterator(const FileDeviceOutputIterator &other) = default;
~FileDeviceOutputIterator();
return *this;
}
// mimic std::ostream_iterator behavior
FileDeviceOutputIterator &operator=(char c);
// TODO: make these `constexpr` in C++17
FileDeviceOutputIterator &operator*();
FileDeviceOutputIterator &operator++();
FileDeviceOutputIterator &operator++(int);
constexpr FileDeviceOutputIterator &operator++()
{
return *this;
}
private:
QFileDevice *m_device;
std::shared_ptr<QByteArray> m_buffer;
int m_bufferSize;
};
}
constexpr FileDeviceOutputIterator &operator++(int)
{
return *this;
}
private:
QFileDevice *m_device;
std::shared_ptr<QByteArray> m_buffer;
int m_bufferSize;
};
}

View File

@@ -41,69 +41,66 @@ enum class ShutdownDialogAction;
/* Miscellaneous functions that can be useful */
namespace Utils
namespace Utils::Misc
{
namespace Misc
// use binary prefix standards from IEC 60027-2
// see http://en.wikipedia.org/wiki/Kilobyte
enum class SizeUnit
{
// use binary prefix standards from IEC 60027-2
// see http://en.wikipedia.org/wiki/Kilobyte
enum class SizeUnit
{
Byte, // 1024^0,
KibiByte, // 1024^1,
MebiByte, // 1024^2,
GibiByte, // 1024^3,
TebiByte, // 1024^4,
PebiByte, // 1024^5,
ExbiByte // 1024^6,
// int64 is used for sizes and thus the next units can not be handled
// ZebiByte, // 1024^7,
// YobiByte, // 1024^8
};
Byte, // 1024^0,
KibiByte, // 1024^1,
MebiByte, // 1024^2,
GibiByte, // 1024^3,
TebiByte, // 1024^4,
PebiByte, // 1024^5,
ExbiByte // 1024^6,
// int64 is used for sizes and thus the next units can not be handled
// ZebiByte, // 1024^7,
// YobiByte, // 1024^8
};
QString parseHtmlLinks(const QString &rawText);
QString parseHtmlLinks(const QString &rawText);
void shutdownComputer(const ShutdownDialogAction &action);
void shutdownComputer(const ShutdownDialogAction &action);
QString osName();
QString boostVersionString();
QString libtorrentVersionString();
QString opensslVersionString();
QString zlibVersionString();
QString osName();
QString boostVersionString();
QString libtorrentVersionString();
QString opensslVersionString();
QString zlibVersionString();
QString unitString(SizeUnit unit, bool isSpeed = false);
QString unitString(SizeUnit unit, bool isSpeed = false);
// return the best user friendly storage unit (B, KiB, MiB, GiB, TiB)
// value must be given in bytes
QString friendlyUnit(qint64 bytesValue, bool isSpeed = false);
int friendlyUnitPrecision(SizeUnit unit);
qint64 sizeInBytes(qreal size, SizeUnit unit);
// return the best user friendly storage unit (B, KiB, MiB, GiB, TiB)
// value must be given in bytes
QString friendlyUnit(qint64 bytesValue, bool isSpeed = false);
int friendlyUnitPrecision(SizeUnit unit);
qint64 sizeInBytes(qreal size, SizeUnit unit);
bool isPreviewable(const QString &extension);
bool isPreviewable(const QString &extension);
// Take a number of seconds and return a user-friendly
// time duration like "1d 2h 10m".
QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap = -1);
QString getUserIDString();
// Take a number of seconds and return a user-friendly
// time duration like "1d 2h 10m".
QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap = -1);
QString getUserIDString();
#ifdef Q_OS_WIN
QString windowsSystemPath();
QString windowsSystemPath();
template <typename T>
T loadWinAPI(const QString &source, const char *funcName)
{
QString path = windowsSystemPath();
if (!path.endsWith('\\'))
path += '\\';
template <typename T>
T loadWinAPI(const QString &source, const char *funcName)
{
QString path = windowsSystemPath();
if (!path.endsWith('\\'))
path += '\\';
path += source;
path += source;
auto pathWchar = std::make_unique<wchar_t[]>(path.length() + 1);
path.toWCharArray(pathWchar.get());
auto pathWchar = std::make_unique<wchar_t[]>(path.length() + 1);
path.toWCharArray(pathWchar.get());
return reinterpret_cast<T>(
::GetProcAddress(::LoadLibraryW(pathWchar.get()), funcName));
}
#endif // Q_OS_WIN
return reinterpret_cast<T>(
::GetProcAddress(::LoadLibraryW(pathWchar.get()), funcName));
}
#endif // Q_OS_WIN
}

View File

@@ -35,24 +35,21 @@ class QSslCertificate;
class QSslKey;
class QString;
namespace Utils
namespace Utils::Net
{
namespace Net
{
using Subnet = QPair<QHostAddress, int>;
using Subnet = QPair<QHostAddress, int>;
bool isValidIP(const QString &ip);
Subnet parseSubnet(const QString &subnetStr, bool *ok = nullptr);
bool canParseSubnet(const QString &subnetStr);
bool isLoopbackAddress(const QHostAddress &addr);
bool isIPInRange(const QHostAddress &addr, const QVector<Subnet> &subnets);
QString subnetToString(const Subnet &subnet);
QHostAddress canonicalIPv6Addr(const QHostAddress &addr);
bool isValidIP(const QString &ip);
Subnet parseSubnet(const QString &subnetStr, bool *ok = nullptr);
bool canParseSubnet(const QString &subnetStr);
bool isLoopbackAddress(const QHostAddress &addr);
bool isIPInRange(const QHostAddress &addr, const QVector<Subnet> &subnets);
QString subnetToString(const Subnet &subnet);
QHostAddress canonicalIPv6Addr(const QHostAddress &addr);
const int MAX_SSL_FILE_SIZE = 1024 * 1024;
QList<QSslCertificate> loadSSLCertificate(const QByteArray &data);
bool isSSLCertificatesValid(const QByteArray &data);
QSslKey loadSSLKey(const QByteArray &data);
bool isSSLKeyValid(const QByteArray &data);
}
const int MAX_SSL_FILE_SIZE = 1024 * 1024;
QList<QSslCertificate> loadSSLCertificate(const QByteArray &data);
bool isSSLCertificatesValid(const QByteArray &data);
QSslKey loadSSLKey(const QByteArray &data);
bool isSSLKeyValid(const QByteArray &data);
}

View File

@@ -31,21 +31,18 @@
class QByteArray;
class QString;
namespace Utils
namespace Utils::Password
{
namespace Password
// Implements constant-time comparison to protect against timing attacks
// Taken from https://crackstation.net/hashing-security.htm
bool slowEquals(const QByteArray &a, const QByteArray &b);
namespace PBKDF2
{
// Implements constant-time comparison to protect against timing attacks
// Taken from https://crackstation.net/hashing-security.htm
bool slowEquals(const QByteArray &a, const QByteArray &b);
QByteArray generate(const QString &password);
QByteArray generate(const QByteArray &password);
namespace PBKDF2
{
QByteArray generate(const QString &password);
QByteArray generate(const QByteArray &password);
bool verify(const QByteArray &secret, const QString &password);
bool verify(const QByteArray &secret, const QByteArray &password);
}
bool verify(const QByteArray &secret, const QString &password);
bool verify(const QByteArray &secret, const QByteArray &password);
}
}

View File

@@ -31,10 +31,7 @@
#include <cstdint>
#include <limits>
namespace Utils
namespace Utils::Random
{
namespace Random
{
uint32_t rand(uint32_t min = 0, uint32_t max = std::numeric_limits<uint32_t>::max());
}
uint32_t rand(uint32_t min = 0, uint32_t max = std::numeric_limits<uint32_t>::max());
}

View File

@@ -42,8 +42,6 @@
#include <QThreadStorage>
#endif
#include "base/tristatebool.h"
namespace
{
class NaturalCompare
@@ -192,20 +190,14 @@ QString Utils::String::wildcardToRegex(const QString &pattern)
return qt_regexp_toCanonical(pattern, QRegExp::Wildcard);
}
bool Utils::String::parseBool(const QString &string, const bool defaultValue)
{
if (defaultValue)
return (string.compare("false", Qt::CaseInsensitive) == 0) ? false : true;
return (string.compare("true", Qt::CaseInsensitive) == 0) ? true : false;
}
TriStateBool Utils::String::parseTriStateBool(const QString &string)
std::optional<bool> Utils::String::parseBool(const QString &string)
{
if (string.compare("true", Qt::CaseInsensitive) == 0)
return TriStateBool::True;
return true;
if (string.compare("false", Qt::CaseInsensitive) == 0)
return TriStateBool::False;
return TriStateBool::Undefined;
return false;
return std::nullopt;
}
QString Utils::String::join(const QVector<QStringRef> &strings, const QString &separator)

View File

@@ -29,6 +29,8 @@
#pragma once
#include <optional>
#include <QChar>
#include <QMetaEnum>
#include <QString>
@@ -37,62 +39,56 @@
class QStringRef;
class TriStateBool;
namespace Utils
namespace Utils::String
{
namespace String
QString fromDouble(double n, int precision);
int naturalCompare(const QString &left, const QString &right, const Qt::CaseSensitivity caseSensitivity);
template <Qt::CaseSensitivity caseSensitivity>
bool naturalLessThan(const QString &left, const QString &right)
{
QString fromDouble(double n, int precision);
return (naturalCompare(left, right, caseSensitivity) < 0);
}
int naturalCompare(const QString &left, const QString &right, const Qt::CaseSensitivity caseSensitivity);
template <Qt::CaseSensitivity caseSensitivity>
bool naturalLessThan(const QString &left, const QString &right)
QString wildcardToRegex(const QString &pattern);
template <typename T>
T unquote(const T &str, const QString &quotes = QChar('"'))
{
if (str.length() < 2) return str;
for (const QChar quote : quotes)
{
return (naturalCompare(left, right, caseSensitivity) < 0);
if (str.startsWith(quote) && str.endsWith(quote))
return str.mid(1, (str.length() - 2));
}
QString wildcardToRegex(const QString &pattern);
return str;
}
template <typename T>
T unquote(const T &str, const QString &quotes = QChar('"'))
{
if (str.length() < 2) return str;
std::optional<bool> parseBool(const QString &string);
for (const QChar quote : quotes)
{
if (str.startsWith(quote) && str.endsWith(quote))
return str.mid(1, (str.length() - 2));
}
QString join(const QVector<QStringRef> &strings, const QString &separator);
return str;
}
template <typename T, typename std::enable_if_t<std::is_enum_v<T>, int> = 0>
QString fromEnum(const T &value)
{
static_assert(std::is_same_v<int, typename std::underlying_type_t<T>>,
"Enumeration underlying type has to be int.");
bool parseBool(const QString &string, bool defaultValue);
TriStateBool parseTriStateBool(const QString &string);
const auto metaEnum = QMetaEnum::fromType<T>();
return QString::fromLatin1(metaEnum.valueToKey(static_cast<int>(value)));
}
QString join(const QVector<QStringRef> &strings, const QString &separator);
template <typename T, typename std::enable_if_t<std::is_enum_v<T>, int> = 0>
T toEnum(const QString &serializedValue, const T &defaultValue)
{
static_assert(std::is_same_v<int, typename std::underlying_type_t<T>>,
"Enumeration underlying type has to be int.");
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
QString fromEnum(const T &value)
{
static_assert(std::is_same<int, typename std::underlying_type_t<T>>::value,
"Enumeration underlying type has to be int.");
const auto metaEnum = QMetaEnum::fromType<T>();
return QString::fromLatin1(metaEnum.valueToKey(static_cast<int>(value)));
}
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
T toEnum(const QString &serializedValue, const T &defaultValue)
{
static_assert(std::is_same<int, typename std::underlying_type_t<T>>::value,
"Enumeration underlying type has to be int.");
const auto metaEnum = QMetaEnum::fromType<T>();
bool ok = false;
const T value = static_cast<T>(metaEnum.keyToValue(serializedValue.toLatin1().constData(), &ok));
return (ok ? value : defaultValue);
}
const auto metaEnum = QMetaEnum::fromType<T>();
bool ok = false;
const T value = static_cast<T>(metaEnum.keyToValue(serializedValue.toLatin1().constData(), &ok));
return (ok ? value : defaultValue);
}
}

View File

@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2021 Mike Tzou (Chocobo1)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,8 +26,22 @@
* exception statement from your version.
*/
#include "tristatebool.h"
#pragma once
const TriStateBool TriStateBool::Undefined(-1);
const TriStateBool TriStateBool::False(0);
const TriStateBool TriStateBool::True(1);
#define QBT_VERSION_MAJOR 4
#define QBT_VERSION_MINOR 3
#define QBT_VERSION_BUGFIX 3
#define QBT_VERSION_BUILD 0
#define QBT_VERSION_STATUS "" // Should be empty for stable releases!
#define QBT__STRINGIFY(x) #x
#define QBT_STRINGIFY(x) QBT__STRINGIFY(x)
#if (QBT_VERSION_BUILD != 0)
#define PROJECT_VERSION QBT_STRINGIFY(QBT_VERSION_MAJOR.QBT_VERSION_MINOR.QBT_VERSION_BUGFIX.QBT_VERSION_BUILD) QBT_VERSION_STATUS
#else
#define PROJECT_VERSION QBT_STRINGIFY(QBT_VERSION_MAJOR.QBT_VERSION_MINOR.QBT_VERSION_BUGFIX) QBT_VERSION_STATUS
#endif
#define QBT_VERSION "v" PROJECT_VERSION
#define QBT_VERSION_2 PROJECT_VERSION

View File

@@ -67,6 +67,7 @@ add_library(qbt_gui STATIC
torrentcontentmodelitem.h
torrentcontenttreeview.h
torrentcreatordialog.h
torrentoptionsdialog.h
trackerentriesdialog.h
transferlistdelegate.h
transferlistfilterswidget.h
@@ -76,7 +77,6 @@ add_library(qbt_gui STATIC
tristateaction.h
tristatewidget.h
uithememanager.h
updownratiodialog.h
utils.h
# sources
@@ -147,6 +147,7 @@ add_library(qbt_gui STATIC
torrentcontentmodelitem.cpp
torrentcontenttreeview.cpp
torrentcreatordialog.cpp
torrentoptionsdialog.cpp
trackerentriesdialog.cpp
transferlistdelegate.cpp
transferlistfilterswidget.cpp
@@ -156,7 +157,6 @@ add_library(qbt_gui STATIC
tristateaction.cpp
tristatewidget.cpp
uithememanager.cpp
updownratiodialog.cpp
utils.cpp
# forms
@@ -186,8 +186,8 @@ add_library(qbt_gui STATIC
statsdialog.ui
torrentcategorydialog.ui
torrentcreatordialog.ui
torrentoptionsdialog.ui
trackerentriesdialog.ui
updownratiodialog.ui
)
target_sources(qbt_gui INTERFACE about.qrc)

View File

@@ -32,13 +32,17 @@
#include "base/unicodestrings.h"
#include "base/utils/misc.h"
#include "base/version.h"
#include "ui_aboutdialog.h"
#include "uithememanager.h"
#include "utils.h"
#define SETTINGS_KEY(name) "AboutDialog/" name
AboutDialog::AboutDialog(QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::AboutDialog)
, m_storeDialogSize(SETTINGS_KEY("Size"))
{
m_ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
@@ -60,7 +64,7 @@ AboutDialog::AboutDialog(QWidget *parent)
"</table>"
"</p>")
.arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar.")
, tr("Copyright %1 2006-2020 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT))
, tr("Copyright %1 2006-2021 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT))
, tr("Home Page:")
, tr("Forum:")
, tr("Bug Tracker:"));
@@ -107,11 +111,12 @@ AboutDialog::AboutDialog(QWidget *parent)
"The database is licensed under the Creative Commons Attribution 4.0 International License"));
m_ui->labelDBIP->setText(DBIPText);
Utils::Gui::resize(this);
Utils::Gui::resize(this, m_storeDialogSize);
show();
}
AboutDialog::~AboutDialog()
{
m_storeDialogSize = size();
delete m_ui;
}

View File

@@ -30,12 +30,14 @@
#include <QDialog>
#include "base/settingvalue.h"
namespace Ui
{
class AboutDialog;
}
class AboutDialog : public QDialog
class AboutDialog final : public QDialog
{
Q_OBJECT
Q_DISABLE_COPY(AboutDialog)
@@ -46,4 +48,5 @@ public:
private:
Ui::AboutDialog *m_ui;
SettingValue<QSize> m_storeDialogSize;
};

View File

@@ -42,7 +42,7 @@
#include "base/bittorrent/infohash.h"
#include "base/bittorrent/magneturi.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/torrent.h"
#include "base/exceptions.h"
#include "base/global.h"
#include "base/net/downloadmanager.h"
@@ -107,12 +107,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
const auto *session = BitTorrent::Session::instance();
if (m_torrentParams.addPaused == TriStateBool::True)
m_ui->startTorrentCheckBox->setChecked(false);
else if (m_torrentParams.addPaused == TriStateBool::False)
m_ui->startTorrentCheckBox->setChecked(true);
else
m_ui->startTorrentCheckBox->setChecked(!session->isAddTorrentPaused());
m_ui->startTorrentCheckBox->setChecked(!m_torrentParams.addPaused.value_or(session->isAddTorrentPaused()));
m_ui->comboTTM->blockSignals(true); // the TreeView size isn't correct if the slot does it job at this point
m_ui->comboTTM->setCurrentIndex(!session->isAutoTMMDisabledByDefault());
@@ -120,11 +115,11 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
populateSavePathComboBox();
connect(m_ui->savePath, &FileSystemPathEdit::selectedPathChanged, this, &AddNewTorrentDialog::onSavePathChanged);
const bool rememberLastSavePath = settings()->loadValue(KEY_REMEMBERLASTSAVEPATH, false).toBool();
const bool rememberLastSavePath = settings()->loadValue(KEY_REMEMBERLASTSAVEPATH, false);
m_ui->checkBoxRememberLastSavePath->setChecked(rememberLastSavePath);
m_ui->contentLayoutComboBox->setCurrentIndex(
static_cast<int>(m_torrentParams.contentLayout ? *m_torrentParams.contentLayout : session->torrentContentLayout()));
static_cast<int>(m_torrentParams.contentLayout.value_or(session->torrentContentLayout())));
m_ui->sequentialCheckBox->setChecked(m_torrentParams.sequential);
m_ui->firstLastCheckBox->setChecked(m_torrentParams.firstLastPiecePriority);
@@ -135,7 +130,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
// Load categories
QStringList categories = session->categories().keys();
std::sort(categories.begin(), categories.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
QString defaultCategory = settings()->loadValue(KEY_DEFAULTCATEGORY).toString();
auto defaultCategory = settings()->loadValue<QString>(KEY_DEFAULTCATEGORY);
if (!m_torrentParams.category.isEmpty())
m_ui->categoryComboBox->addItem(m_torrentParams.category);
@@ -170,7 +165,7 @@ AddNewTorrentDialog::~AddNewTorrentDialog()
bool AddNewTorrentDialog::isEnabled()
{
return SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool();
return SettingsStorage::instance()->loadValue(KEY_ENABLED, true);
}
void AddNewTorrentDialog::setEnabled(bool value)
@@ -180,7 +175,7 @@ void AddNewTorrentDialog::setEnabled(bool value)
bool AddNewTorrentDialog::isTopLevel()
{
return SettingsStorage::instance()->loadValue(KEY_TOPLEVEL, true).toBool();
return SettingsStorage::instance()->loadValue(KEY_TOPLEVEL, true);
}
void AddNewTorrentDialog::setTopLevel(bool value)
@@ -191,7 +186,7 @@ void AddNewTorrentDialog::setTopLevel(bool value)
int AddNewTorrentDialog::savePathHistoryLength()
{
const int defaultHistoryLength = 8;
const int value = settings()->loadValue(KEY_SAVEPATHHISTORYLENGTH, defaultHistoryLength).toInt();
const int value = settings()->loadValue(KEY_SAVEPATHHISTORYLENGTH, defaultHistoryLength);
return qBound(minPathHistoryLength, value, maxPathHistoryLength);
}
@@ -204,14 +199,14 @@ void AddNewTorrentDialog::setSavePathHistoryLength(int value)
settings()->storeValue(KEY_SAVEPATHHISTORYLENGTH, clampedValue);
settings()->storeValue(KEY_SAVEPATHHISTORY
, QStringList(settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList().mid(0, clampedValue)));
, QStringList(settings()->loadValue<QStringList>(KEY_SAVEPATHHISTORY).mid(0, clampedValue)));
}
void AddNewTorrentDialog::loadState()
{
Utils::Gui::resize(this, m_storeDialogSize);
m_ui->splitter->restoreState(m_storeSplitterState);
m_headerState = settings()->loadValue(KEY_TREEHEADERSTATE).toByteArray();
m_headerState = settings()->loadValue<QByteArray>(KEY_TREEHEADERSTATE);
}
void AddNewTorrentDialog::saveState()
@@ -280,7 +275,7 @@ bool AddNewTorrentDialog::loadTorrentImpl()
// Prevent showing the dialog if download is already present
if (BitTorrent::Session::instance()->isKnownTorrent(infoHash))
{
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
if (torrent)
{
if (torrent->isPrivate() || m_torrentInfo.isPrivate())
@@ -321,7 +316,7 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
// Prevent showing the dialog if download is already present
if (BitTorrent::Session::instance()->isKnownTorrent(infoHash))
{
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
if (torrent)
{
if (torrent->isPrivate())
@@ -371,7 +366,7 @@ void AddNewTorrentDialog::showEvent(QShowEvent *event)
void AddNewTorrentDialog::saveSavePathHistory() const
{
// Get current history
QStringList history = settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList();
auto history = settings()->loadValue<QStringList>(KEY_SAVEPATHHISTORY);
QVector<QDir> historyDirs;
for (const QString &path : asConst(history))
historyDirs << QDir {path};
@@ -489,11 +484,11 @@ void AddNewTorrentDialog::populateSavePathComboBox()
m_ui->savePath->clear();
// Load save path history
const QStringList savePathHistory {settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList()};
const auto savePathHistory {settings()->loadValue<QStringList>(KEY_SAVEPATHHISTORY)};
for (const QString &savePath : savePathHistory)
m_ui->savePath->addItem(savePath);
const bool rememberLastSavePath {settings()->loadValue(KEY_REMEMBERLASTSAVEPATH, false).toBool()};
const bool rememberLastSavePath {settings()->loadValue(KEY_REMEMBERLASTSAVEPATH, false)};
const QString defSavePath {BitTorrent::Session::instance()->defaultSavePath()};
if (!m_torrentParams.savePath.isEmpty())
@@ -573,7 +568,7 @@ void AddNewTorrentDialog::accept()
if (m_contentModel)
m_torrentParams.filePriorities = m_contentModel->model()->getFilePriorities();
m_torrentParams.addPaused = TriStateBool(!m_ui->startTorrentCheckBox->isChecked());
m_torrentParams.addPaused = !m_ui->startTorrentCheckBox->isChecked();
m_torrentParams.contentLayout = static_cast<BitTorrent::TorrentContentLayout>(m_ui->contentLayoutComboBox->currentIndex());
m_torrentParams.sequential = m_ui->sequentialCheckBox->isChecked();
@@ -582,13 +577,13 @@ void AddNewTorrentDialog::accept()
QString savePath = m_ui->savePath->selectedPath();
if (m_ui->comboTTM->currentIndex() != 1)
{ // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
m_torrentParams.useAutoTMM = TriStateBool::False;
m_torrentParams.useAutoTMM = false;
m_torrentParams.savePath = savePath;
saveSavePathHistory();
}
else
{
m_torrentParams.useAutoTMM = TriStateBool::True;
m_torrentParams.useAutoTMM = true;
}
setEnabled(!m_ui->checkBoxNeverShow->isChecked());
@@ -660,7 +655,7 @@ void AddNewTorrentDialog::setupTreeview()
// Set torrent information
m_ui->labelCommentData->setText(Utils::Misc::parseHtmlLinks(m_torrentInfo.comment().toHtmlEscaped()));
m_ui->labelDateData->setText(!m_torrentInfo.creationDate().isNull() ? m_torrentInfo.creationDate().toString(Qt::DefaultLocaleShortDate) : tr("Not available"));
m_ui->labelDateData->setText(!m_torrentInfo.creationDate().isNull() ? QLocale().toString(m_torrentInfo.creationDate(), QLocale::ShortFormat) : tr("Not available"));
// Prepare content tree
m_contentModel = new TorrentContentFilterModel(this);

View File

@@ -118,6 +118,6 @@ private:
std::unique_ptr<TorrentFileGuard> m_torrentGuard;
BitTorrent::AddTorrentParams m_torrentParams;
CachedSettingValue<QSize> m_storeDialogSize;
CachedSettingValue<QByteArray> m_storeSplitterState;
SettingValue<QSize> m_storeDialogSize;
SettingValue<QByteArray> m_storeSplitterState;
};

View File

@@ -715,12 +715,12 @@ void AdvancedSettings::addRow(const int row, const QString &text, T *widget)
setCellWidget(row, PROPERTY, label);
setCellWidget(row, VALUE, widget);
if (std::is_same<T, QCheckBox>::value)
connect(widget, SIGNAL(stateChanged(int)), this, SIGNAL(settingsChanged()));
else if (std::is_same<T, QSpinBox>::value)
connect(widget, SIGNAL(valueChanged(int)), this, SIGNAL(settingsChanged()));
else if (std::is_same<T, QComboBox>::value)
connect(widget, SIGNAL(currentIndexChanged(int)), this, SIGNAL(settingsChanged()));
else if (std::is_same<T, QLineEdit>::value)
connect(widget, SIGNAL(textChanged(QString)), this, SIGNAL(settingsChanged()));
if constexpr (std::is_same_v<T, QCheckBox>)
connect(widget, &QCheckBox::stateChanged, this, &AdvancedSettings::settingsChanged);
else if constexpr (std::is_same_v<T, QSpinBox>)
connect(widget, qOverload<int>(&QSpinBox::valueChanged), this, &AdvancedSettings::settingsChanged);
else if constexpr (std::is_same_v<T, QComboBox>)
connect(widget, qOverload<int>(&QComboBox::currentIndexChanged), this, &AdvancedSettings::settingsChanged);
else if constexpr (std::is_same_v<T, QLineEdit>)
connect(widget, &QLineEdit::textChanged, this, &AdvancedSettings::settingsChanged);
}

View File

@@ -28,6 +28,7 @@
#include "autoexpandabledialog.h"
#include "base/utils/fs.h"
#include "ui_autoexpandabledialog.h"
#include "utils.h"
@@ -57,12 +58,9 @@ QString AutoExpandableDialog::getText(QWidget *parent, const QString &title, con
d.m_ui->textEdit->selectAll();
if (excludeExtension)
{
int lastDotIndex = text.lastIndexOf('.');
if ((lastDotIndex > 3) && (text.mid(lastDotIndex - 4, 4).toLower() == ".tar"))
lastDotIndex -= 4;
// Select file name without extension, except dot files like .gitignore
if (lastDotIndex > 0)
d.m_ui->textEdit->setSelection(0, lastDotIndex);
const QString extension = Utils::Fs::fileExtension(text);
if (!extension.isEmpty())
d.m_ui->textEdit->setSelection(0, (text.length() - extension.length() - 1));
}
bool res = d.exec();

View File

@@ -38,11 +38,13 @@
#include "ui_banlistoptionsdialog.h"
#include "utils.h"
#define SETTINGS_KEY(name) "BanListOptionsDialog/" name
BanListOptionsDialog::BanListOptionsDialog(QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::BanListOptionsDialog)
, m_storeDialogSize(SETTINGS_KEY("Size"))
, m_model(new QStringListModel(BitTorrent::Session::instance()->bannedIPs(), this))
, m_modified(false)
{
m_ui->setupUi(this);
@@ -54,11 +56,12 @@ BanListOptionsDialog::BanListOptionsDialog(QWidget *parent)
m_ui->bannedIPList->sortByColumn(0, Qt::AscendingOrder);
m_ui->buttonBanIP->setEnabled(false);
Utils::Gui::resize(this);
Utils::Gui::resize(this, m_storeDialogSize);
}
BanListOptionsDialog::~BanListOptionsDialog()
{
m_storeDialogSize = size();
delete m_ui;
}

View File

@@ -30,6 +30,8 @@
#include <QDialog>
#include "base/settingvalue.h"
class QSortFilterProxyModel;
class QStringListModel;
@@ -38,13 +40,14 @@ namespace Ui
class BanListOptionsDialog;
}
class BanListOptionsDialog : public QDialog
class BanListOptionsDialog final : public QDialog
{
Q_OBJECT
Q_DISABLE_COPY(BanListOptionsDialog)
public:
explicit BanListOptionsDialog(QWidget *parent = nullptr);
~BanListOptionsDialog();
~BanListOptionsDialog() override;
private slots:
void on_buttonBox_accepted();
@@ -54,7 +57,8 @@ private slots:
private:
Ui::BanListOptionsDialog *m_ui;
SettingValue<QSize> m_storeDialogSize;
QStringListModel *m_model;
QSortFilterProxyModel *m_sortFilter;
bool m_modified;
bool m_modified = false;
};

View File

@@ -32,7 +32,7 @@
#include <QIcon>
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/torrent.h"
#include "base/global.h"
#include "uithememanager.h"
@@ -336,7 +336,7 @@ void CategoryFilterModel::categoryRemoved(const QString &categoryName)
}
}
void CategoryFilterModel::torrentAdded(BitTorrent::TorrentHandle *const torrent)
void CategoryFilterModel::torrentAdded(BitTorrent::Torrent *const torrent)
{
CategoryModelItem *item = findItem(torrent->category());
Q_ASSERT(item);
@@ -345,7 +345,7 @@ void CategoryFilterModel::torrentAdded(BitTorrent::TorrentHandle *const torrent)
m_rootItem->childAt(0)->increaseTorrentsCount();
}
void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent)
void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::Torrent *const torrent)
{
CategoryModelItem *item = findItem(torrent->category());
Q_ASSERT(item);
@@ -354,7 +354,7 @@ void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::TorrentHandle *con
m_rootItem->childAt(0)->decreaseTorrentsCount();
}
void CategoryFilterModel::torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory)
void CategoryFilterModel::torrentCategoryChanged(BitTorrent::Torrent *const torrent, const QString &oldCategory)
{
QModelIndex i;
@@ -403,7 +403,7 @@ void CategoryFilterModel::populate()
m_rootItem->addChild(UID_ALL, new CategoryModelItem(nullptr, tr("All"), torrents.count()));
// Uncategorized torrents
using Torrent = BitTorrent::TorrentHandle;
using Torrent = BitTorrent::Torrent;
m_rootItem->addChild(
UID_UNCATEGORIZED
, new CategoryModelItem(
@@ -411,7 +411,7 @@ void CategoryFilterModel::populate()
, std::count_if(torrents.begin(), torrents.end()
, [](Torrent *torrent) { return torrent->category().isEmpty(); })));
using Torrent = BitTorrent::TorrentHandle;
using Torrent = BitTorrent::Torrent;
for (auto i = session->categories().cbegin(); i != session->categories().cend(); ++i)
{
const QString &category = i.key();

View File

@@ -36,7 +36,7 @@ class CategoryModelItem;
namespace BitTorrent
{
class TorrentHandle;
class Torrent;
}
class CategoryFilterModel final : public QAbstractItemModel
@@ -63,9 +63,9 @@ public:
private slots:
void categoryAdded(const QString &categoryName);
void categoryRemoved(const QString &categoryName);
void torrentAdded(BitTorrent::TorrentHandle *const torrent);
void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
void torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory);
void torrentAdded(BitTorrent::Torrent *const torrent);
void torrentAboutToBeRemoved(BitTorrent::Torrent *const torrent);
void torrentCategoryChanged(BitTorrent::Torrent *const torrent, const QString &oldCategory);
void subcategoriesSupportChanged();
private:

View File

@@ -61,9 +61,9 @@ CookiesDialog::CookiesDialog(QWidget *parent)
m_cookiesModel->index(0, 0),
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
Utils::Gui::resize(this, SettingsStorage::instance()->loadValue(KEY_SIZE).toSize());
Utils::Gui::resize(this, SettingsStorage::instance()->loadValue<QSize>(KEY_SIZE));
m_ui->treeView->header()->restoreState(
SettingsStorage::instance()->loadValue(KEY_COOKIESVIEWSTATE).toByteArray());
SettingsStorage::instance()->loadValue<QByteArray>(KEY_COOKIESVIEWSTATE));
}
CookiesDialog::~CookiesDialog()

View File

@@ -39,6 +39,8 @@
#include "ui_downloadfromurldialog.h"
#include "utils.h"
#define SETTINGS_KEY(name) "DownloadFromURLDialog/" name
namespace
{
bool isDownloadable(const QString &str)
@@ -55,6 +57,7 @@ namespace
DownloadFromURLDialog::DownloadFromURLDialog(QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::DownloadFromURLDialog)
, m_storeDialogSize(SETTINGS_KEY("Size"))
{
m_ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
@@ -82,12 +85,13 @@ DownloadFromURLDialog::DownloadFromURLDialog(QWidget *parent)
}
m_ui->textUrls->setText(uniqueURLs.values().join('\n'));
Utils::Gui::resize(this);
Utils::Gui::resize(this, m_storeDialogSize);
show();
}
DownloadFromURLDialog::~DownloadFromURLDialog()
{
m_storeDialogSize = size();
delete m_ui;
}

View File

@@ -30,19 +30,21 @@
#include <QDialog>
#include "base/settingvalue.h"
namespace Ui
{
class DownloadFromURLDialog;
}
class DownloadFromURLDialog : public QDialog
class DownloadFromURLDialog final : public QDialog
{
Q_OBJECT
Q_DISABLE_COPY(DownloadFromURLDialog)
public:
explicit DownloadFromURLDialog(QWidget *parent);
~DownloadFromURLDialog();
~DownloadFromURLDialog() override;
signals:
void urlsReadyToBeDownloaded(const QStringList &torrentURLs);
@@ -52,4 +54,5 @@ private slots:
private:
Ui::DownloadFromURLDialog *m_ui;
SettingValue<QSize> m_storeDialogSize;
};

View File

@@ -68,6 +68,7 @@ HEADERS += \
$$PWD/torrentcontentmodelitem.h \
$$PWD/torrentcontenttreeview.h \
$$PWD/torrentcreatordialog.h \
$$PWD/torrentoptionsdialog.h \
$$PWD/trackerentriesdialog.h \
$$PWD/transferlistdelegate.h \
$$PWD/transferlistfilterswidget.h \
@@ -77,7 +78,6 @@ HEADERS += \
$$PWD/tristateaction.h \
$$PWD/tristatewidget.h \
$$PWD/uithememanager.h \
$$PWD/updownratiodialog.h \
$$PWD/utils.h
SOURCES += \
@@ -148,6 +148,7 @@ SOURCES += \
$$PWD/torrentcontentmodelitem.cpp \
$$PWD/torrentcontenttreeview.cpp \
$$PWD/torrentcreatordialog.cpp \
$$PWD/torrentoptionsdialog.cpp \
$$PWD/trackerentriesdialog.cpp \
$$PWD/transferlistdelegate.cpp \
$$PWD/transferlistfilterswidget.cpp \
@@ -157,7 +158,6 @@ SOURCES += \
$$PWD/tristateaction.cpp \
$$PWD/tristatewidget.cpp \
$$PWD/uithememanager.cpp \
$$PWD/updownratiodialog.cpp \
$$PWD/utils.cpp
win32|macx {
@@ -207,7 +207,7 @@ FORMS += \
$$PWD/statsdialog.ui \
$$PWD/torrentcategorydialog.ui \
$$PWD/torrentcreatordialog.ui \
$$PWD/trackerentriesdialog.ui \
$$PWD/updownratiodialog.ui
$$PWD/torrentoptionsdialog.ui \
$$PWD/trackerentriesdialog.ui
RESOURCES += $$PWD/about.qrc

View File

@@ -38,10 +38,12 @@
#include "ui_ipsubnetwhitelistoptionsdialog.h"
#include "utils.h"
#define SETTINGS_KEY(name) "IPSubnetWhitelistOptionsDialog/" name
IPSubnetWhitelistOptionsDialog::IPSubnetWhitelistOptionsDialog(QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::IPSubnetWhitelistOptionsDialog)
, m_modified(false)
, m_storeDialogSize(SETTINGS_KEY("Size"))
{
m_ui->setupUi(this);
@@ -58,11 +60,12 @@ IPSubnetWhitelistOptionsDialog::IPSubnetWhitelistOptionsDialog(QWidget *parent)
m_ui->whitelistedIPSubnetList->sortByColumn(0, Qt::AscendingOrder);
m_ui->buttonWhitelistIPSubnet->setEnabled(false);
Utils::Gui::resize(this);
Utils::Gui::resize(this, m_storeDialogSize);
}
IPSubnetWhitelistOptionsDialog::~IPSubnetWhitelistOptionsDialog()
{
m_storeDialogSize = size();
delete m_ui;
}

View File

@@ -30,6 +30,8 @@
#include <QDialog>
#include "base/settingvalue.h"
class QSortFilterProxyModel;
class QStringListModel;
@@ -38,14 +40,14 @@ namespace Ui
class IPSubnetWhitelistOptionsDialog;
}
class IPSubnetWhitelistOptionsDialog : public QDialog
class IPSubnetWhitelistOptionsDialog final : public QDialog
{
Q_OBJECT
Q_DISABLE_COPY(IPSubnetWhitelistOptionsDialog)
public:
explicit IPSubnetWhitelistOptionsDialog(QWidget *parent = nullptr);
~IPSubnetWhitelistOptionsDialog();
~IPSubnetWhitelistOptionsDialog() override;
private slots:
void on_buttonBox_accepted();
@@ -55,7 +57,9 @@ private slots:
private:
Ui::IPSubnetWhitelistOptionsDialog *m_ui;
SettingValue<QSize> m_storeDialogSize;
QStringListModel *m_model;
QSortFilterProxyModel *m_sortFilter;
bool m_modified;
bool m_modified = false;
};

View File

@@ -155,7 +155,7 @@ LogMessageModel::LogMessageModel(QObject *parent)
void LogMessageModel::handleNewMessage(const Log::Msg &message)
{
const QString time = QDateTime::fromMSecsSinceEpoch(message.timestamp).toString(Qt::SystemLocaleShortDate);
const QString time = QLocale::system().toString(QDateTime::fromMSecsSinceEpoch(message.timestamp), QLocale::ShortFormat);
const QString messageText = message.message;
const QColor foreground = m_foregroundForMessageTypes[message.type];
@@ -173,7 +173,7 @@ LogPeerModel::LogPeerModel(QObject *parent)
void LogPeerModel::handleNewMessage(const Log::Peer &peer)
{
const QString time = QDateTime::fromMSecsSinceEpoch(peer.timestamp).toString(Qt::SystemLocaleShortDate);
const QString time = QLocale::system().toString(QDateTime::fromMSecsSinceEpoch(peer.timestamp), QLocale::ShortFormat);
const QString message = peer.blocked
? tr("%1 was blocked. Reason: %2.", "0.0.0.0 was blocked. Reason: reason for blocking.").arg(peer.ip, peer.reason)
: tr("%1 was banned", "0.0.0.0 was banned").arg(peer.ip);

View File

@@ -58,7 +58,7 @@
#include "base/bittorrent/session.h"
#include "base/bittorrent/sessionstatus.h"
#include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/torrent.h"
#include "base/global.h"
#include "base/logger.h"
#include "base/net/downloadmanager.h"
@@ -70,6 +70,7 @@
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/utils/password.h"
#include "base/version.h"
#include "aboutdialog.h"
#include "addnewtorrentdialog.h"
#include "autoexpandabledialog.h"
@@ -172,10 +173,7 @@ MainWindow::MainWindow(QWidget *parent)
m_ui->actionOpen->setIcon(UIThemeManager::instance()->getIcon("list-add"));
m_ui->actionDownloadFromURL->setIcon(UIThemeManager::instance()->getIcon("insert-link"));
m_ui->actionSetUploadLimit->setIcon(UIThemeManager::instance()->getIcon("kt-set-max-upload-speed"));
m_ui->actionSetDownloadLimit->setIcon(UIThemeManager::instance()->getIcon("kt-set-max-download-speed"));
m_ui->actionSetGlobalUploadLimit->setIcon(UIThemeManager::instance()->getIcon("kt-set-max-upload-speed"));
m_ui->actionSetGlobalDownloadLimit->setIcon(UIThemeManager::instance()->getIcon("kt-set-max-download-speed"));
m_ui->actionSetGlobalSpeedLimits->setIcon(UIThemeManager::instance()->getIcon("speedometer"));
m_ui->actionCreateTorrent->setIcon(UIThemeManager::instance()->getIcon("document-edit"));
m_ui->actionAbout->setIcon(UIThemeManager::instance()->getIcon("help-about"));
m_ui->actionStatistics->setIcon(UIThemeManager::instance()->getIcon("view-statistics"));
@@ -211,8 +209,6 @@ MainWindow::MainWindow(QWidget *parent)
connect(BitTorrent::Session::instance(), &BitTorrent::Session::downloadFromUrlFailed, this, &MainWindow::handleDownloadFromUrlFailure);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::speedLimitModeChanged, this, &MainWindow::updateAltSpeedsBtn);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::recursiveTorrentDownloadPossible, this, &MainWindow::askRecursiveTorrentDownloadConfirmation);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentStorageMoveFinished, this, &MainWindow::moveTorrentFinished);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentStorageMoveFailed, this, &MainWindow::moveTorrentFailed);
qDebug("create tabWidget");
m_tabs = new HidableTabWidget(this);
@@ -264,11 +260,11 @@ MainWindow::MainWindow(QWidget *parent)
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerlessStateChanged, m_transferListFiltersWidget, &TransferListFiltersWidget::changeTrackerless);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerSuccess
, m_transferListFiltersWidget, qOverload<const BitTorrent::TorrentHandle *, const QString &>(&TransferListFiltersWidget::trackerSuccess));
, m_transferListFiltersWidget, qOverload<const BitTorrent::Torrent *, const QString &>(&TransferListFiltersWidget::trackerSuccess));
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerError
, m_transferListFiltersWidget, qOverload<const BitTorrent::TorrentHandle *, const QString &>(&TransferListFiltersWidget::trackerError));
, m_transferListFiltersWidget, qOverload<const BitTorrent::Torrent *, const QString &>(&TransferListFiltersWidget::trackerError));
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerWarning
, m_transferListFiltersWidget, qOverload<const BitTorrent::TorrentHandle *, const QString &>(&TransferListFiltersWidget::trackerWarning));
, m_transferListFiltersWidget, qOverload<const BitTorrent::Torrent *, const QString &>(&TransferListFiltersWidget::trackerWarning));
#ifdef Q_OS_MACOS
// Increase top spacing to avoid tab overlapping
@@ -494,7 +490,7 @@ MainWindow::~MainWindow()
bool MainWindow::isExecutionLogEnabled() const
{
return settings()->loadValue(KEY_EXECUTIONLOG_ENABLED, false).toBool();
return settings()->loadValue(KEY_EXECUTIONLOG_ENABLED, false);
}
void MainWindow::setExecutionLogEnabled(bool value)
@@ -506,7 +502,7 @@ int MainWindow::executionLogMsgTypes() const
{
// as default value we need all the bits set
// -1 is considered the portable way to achieve that
return settings()->loadValue(KEY_EXECUTIONLOG_TYPES, -1).toInt();
return settings()->loadValue(KEY_EXECUTIONLOG_TYPES, -1);
}
void MainWindow::setExecutionLogMsgTypes(const int value)
@@ -517,7 +513,7 @@ void MainWindow::setExecutionLogMsgTypes(const int value)
bool MainWindow::isNotificationsEnabled() const
{
return settings()->loadValue(KEY_NOTIFICATIONS_ENABLED, true).toBool();
return settings()->loadValue(KEY_NOTIFICATIONS_ENABLED, true);
}
void MainWindow::setNotificationsEnabled(bool value)
@@ -527,7 +523,7 @@ void MainWindow::setNotificationsEnabled(bool value)
bool MainWindow::isTorrentAddedNotificationsEnabled() const
{
return settings()->loadValue(KEY_NOTIFICATIONS_TORRENTADDED, false).toBool();
return settings()->loadValue(KEY_NOTIFICATIONS_TORRENTADDED, false);
}
void MainWindow::setTorrentAddedNotificationsEnabled(bool value)
@@ -537,7 +533,7 @@ void MainWindow::setTorrentAddedNotificationsEnabled(bool value)
bool MainWindow::isDownloadTrackerFavicon() const
{
return settings()->loadValue(KEY_DOWNLOAD_TRACKER_FAVICON, false).toBool();
return settings()->loadValue(KEY_DOWNLOAD_TRACKER_FAVICON, false);
}
void MainWindow::setDownloadTrackerFavicon(bool value)
@@ -862,30 +858,20 @@ void MainWindow::addTorrentFailed(const QString &error) const
}
// called when a torrent was added
void MainWindow::torrentNew(BitTorrent::TorrentHandle *const torrent) const
void MainWindow::torrentNew(BitTorrent::Torrent *const torrent) const
{
if (isTorrentAddedNotificationsEnabled())
showNotificationBaloon(tr("Torrent added"), tr("'%1' was added.", "e.g: xxx.avi was added.").arg(torrent->name()));
}
// called when a torrent has finished
void MainWindow::finishedTorrent(BitTorrent::TorrentHandle *const torrent) const
void MainWindow::finishedTorrent(BitTorrent::Torrent *const torrent) const
{
showNotificationBaloon(tr("Download completion"), tr("'%1' has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(torrent->name()));
}
void MainWindow::moveTorrentFinished(BitTorrent::TorrentHandle *const torrent, const QString &newPath) const
{
showNotificationBaloon(tr("Torrent moving finished"), tr("'%1' has finished moving files to '%2'.").arg(torrent->name(), newPath));
}
void MainWindow::moveTorrentFailed(BitTorrent::TorrentHandle *const torrent, const QString &targetPath, const QString &error) const
{
showNotificationBaloon(tr("Torrent moving failed"), tr("'%1' has failed moving files to '%2'. Reason: %3").arg(torrent->name(), targetPath, error));
}
// Notification when disk is full
void MainWindow::fullDiskError(BitTorrent::TorrentHandle *const torrent, const QString &msg) const
void MainWindow::fullDiskError(BitTorrent::Torrent *const torrent, const QString &msg) const
{
showNotificationBaloon(tr("I/O Error", "i.e: Input/Output Error")
, tr("An I/O error occurred for torrent '%1'.\n Reason: %2"
@@ -975,7 +961,7 @@ void MainWindow::displayExecutionLogTab()
// End of keyboard shortcuts slots
void MainWindow::askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const torrent)
void MainWindow::askRecursiveTorrentDownloadConfirmation(BitTorrent::Torrent *const torrent)
{
Preferences *const pref = Preferences::instance();
if (pref->recursiveDownloadDisabled()) return;
@@ -1008,36 +994,11 @@ void MainWindow::handleDownloadFromUrlFailure(const QString &url, const QString
, tr("Couldn't download file at URL '%1', reason: %2.").arg(url, reason));
}
void MainWindow::on_actionSetGlobalUploadLimit_triggered()
void MainWindow::on_actionSetGlobalSpeedLimits_triggered()
{
qDebug() << Q_FUNC_INFO;
BitTorrent::Session *const session = BitTorrent::Session::instance();
bool ok = false;
const long newLimit = SpeedLimitDialog::askSpeedLimit(
this, &ok, tr("Global Upload Speed Limit"), session->uploadSpeedLimit());
if (ok)
{
qDebug("Setting global upload rate limit to %.1fKb/s", newLimit / 1024.);
session->setUploadSpeedLimit(newLimit);
}
}
void MainWindow::on_actionSetGlobalDownloadLimit_triggered()
{
qDebug() << Q_FUNC_INFO;
BitTorrent::Session *const session = BitTorrent::Session::instance();
bool ok = false;
const long newLimit = SpeedLimitDialog::askSpeedLimit(
this, &ok, tr("Global Download Speed Limit"), session->downloadSpeedLimit());
if (ok)
{
qDebug("Setting global download rate limit to %.1fKb/s", newLimit / 1024.);
session->setDownloadSpeedLimit(newLimit);
}
auto dialog = new SpeedLimitDialog {this};
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->open();
}
// Necessary if we want to close the window
@@ -1678,7 +1639,7 @@ void MainWindow::reloadSessionStats()
}
}
void MainWindow::reloadTorrentStats(const QVector<BitTorrent::TorrentHandle *> &torrents)
void MainWindow::reloadTorrentStats(const QVector<BitTorrent::Torrent *> &torrents)
{
if (currentTabWidget() == m_transferListWidget)
{
@@ -1808,8 +1769,7 @@ QMenu *MainWindow::trayIconMenu()
updateAltSpeedsBtn(isAltBWEnabled);
m_ui->actionUseAlternativeSpeedLimits->setChecked(isAltBWEnabled);
m_trayIconMenu->addAction(m_ui->actionUseAlternativeSpeedLimits);
m_trayIconMenu->addAction(m_ui->actionSetGlobalDownloadLimit);
m_trayIconMenu->addAction(m_ui->actionSetGlobalUploadLimit);
m_trayIconMenu->addAction(m_ui->actionSetGlobalSpeedLimits);
m_trayIconMenu->addSeparator();
m_trayIconMenu->addAction(m_ui->actionStartAll);
m_trayIconMenu->addAction(m_ui->actionPauseAll);

View File

@@ -58,7 +58,7 @@ class TransferListWidget;
namespace BitTorrent
{
class TorrentHandle;
class Torrent;
}
namespace Net
@@ -110,7 +110,7 @@ private slots:
void balloonClicked();
void writeSettings();
void readSettings();
void fullDiskError(BitTorrent::TorrentHandle *const torrent, const QString &msg) const;
void fullDiskError(BitTorrent::Torrent *const torrent, const QString &msg) const;
void handleDownloadFromUrlFailure(const QString &, const QString &) const;
void tabChanged(int newTab);
bool defineUILockPassword();
@@ -127,14 +127,12 @@ private slots:
void displayExecutionLogTab();
void focusSearchFilter();
void reloadSessionStats();
void reloadTorrentStats(const QVector<BitTorrent::TorrentHandle *> &torrents);
void reloadTorrentStats(const QVector<BitTorrent::Torrent *> &torrents);
void loadPreferences(bool configureSession = true);
void addTorrentFailed(const QString &error) const;
void torrentNew(BitTorrent::TorrentHandle *const torrent) const;
void finishedTorrent(BitTorrent::TorrentHandle *const torrent) const;
void moveTorrentFinished(BitTorrent::TorrentHandle *const torrent, const QString &newPath) const;
void moveTorrentFailed(BitTorrent::TorrentHandle *const torrent, const QString &targetPath, const QString &error) const;
void askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const torrent);
void torrentNew(BitTorrent::Torrent *const torrent) const;
void finishedTorrent(BitTorrent::Torrent *const torrent) const;
void askRecursiveTorrentDownloadConfirmation(BitTorrent::Torrent *const torrent);
void optionsSaved();
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
void handleUpdateCheckFinished(bool updateAvailable, QString newVersion, bool invokedByUser);
@@ -171,8 +169,7 @@ private slots:
void on_actionStatistics_triggered();
void on_actionCreateTorrent_triggered();
void on_actionOptions_triggered();
void on_actionSetGlobalUploadLimit_triggered();
void on_actionSetGlobalDownloadLimit_triggered();
void on_actionSetGlobalSpeedLimits_triggered();
void on_actionDocumentation_triggered() const;
void on_actionOpen_triggered();
void on_actionDownloadFromURL_triggered();

View File

@@ -223,29 +223,14 @@
<string>Torrent &amp;Creator</string>
</property>
</action>
<action name="actionSetUploadLimit">
<property name="text">
<string>Set Upload Limit...</string>
</property>
</action>
<action name="actionSetDownloadLimit">
<property name="text">
<string>Set Download Limit...</string>
</property>
</action>
<action name="actionDocumentation">
<property name="text">
<string>&amp;Documentation</string>
</property>
</action>
<action name="actionSetGlobalDownloadLimit">
<action name="actionSetGlobalSpeedLimits">
<property name="text">
<string>Set Global Download Limit...</string>
</property>
</action>
<action name="actionSetGlobalUploadLimit">
<property name="text">
<string>Set Global Upload Limit...</string>
<string>Set Global Speed Limits...</string>
</property>
</action>
<action name="actionBottomQueuePos">

View File

@@ -68,6 +68,8 @@
#include "uithememanager.h"
#include "utils.h"
#define SETTINGS_KEY(name) "OptionsDialog/" name
namespace
{
QStringList translatedWeekdayNames()
@@ -88,6 +90,7 @@ namespace
{
case QLocale::Arabic: return QString::fromUtf8(C_LOCALE_ARABIC);
case QLocale::Armenian: return QString::fromUtf8(C_LOCALE_ARMENIAN);
case QLocale::Azerbaijani: return QString::fromUtf8(C_LOCALE_AZERBAIJANI);
case QLocale::Basque: return QString::fromUtf8(C_LOCALE_BASQUE);
case QLocale::Bulgarian: return QString::fromUtf8(C_LOCALE_BULGARIAN);
case QLocale::Byelorussian: return QString::fromUtf8(C_LOCALE_BYELORUSSIAN);
@@ -110,6 +113,7 @@ namespace
case QLocale::UnitedKingdom: return QString::fromUtf8(C_LOCALE_ENGLISH_UNITEDKINGDOM);
default: return QString::fromUtf8(C_LOCALE_ENGLISH);
}
case QLocale::Estonian: return QString::fromUtf8(C_LOCALE_ESTONIAN);
case QLocale::Finnish: return QString::fromUtf8(C_LOCALE_FINNISH);
case QLocale::French: return QString::fromUtf8(C_LOCALE_FRENCH);
case QLocale::Galician: return QString::fromUtf8(C_LOCALE_GALICIAN);
@@ -127,7 +131,7 @@ namespace
case QLocale::Latvian: return QString::fromUtf8(C_LOCALE_LATVIAN);
case QLocale::Lithuanian: return QString::fromUtf8(C_LOCALE_LITHUANIAN);
case QLocale::Malay: return QString::fromUtf8(C_LOCALE_MALAY);
case QLocale::Norwegian: return QString::fromUtf8(C_LOCALE_NORWEGIAN);
case QLocale::NorwegianBokmal: return QString::fromUtf8(C_LOCALE_NORWEGIAN);
case QLocale::Occitan: return QString::fromUtf8(C_LOCALE_OCCITAN);
case QLocale::Polish: return QString::fromUtf8(C_LOCALE_POLISH);
case QLocale::Portuguese:
@@ -167,9 +171,10 @@ private:
// Constructor
OptionsDialog::OptionsDialog(QWidget *parent)
: QDialog(parent)
, m_refreshingIpFilter(false)
, m_ui(new Ui::OptionsDialog)
: QDialog {parent}
, m_ui {new Ui::OptionsDialog}
, m_storeDialogSize {SETTINGS_KEY("Size")}
, m_storeHSplitterSize {SETTINGS_KEY("HorizontalSplitterSizes")}
{
qDebug("-> Constructing Options");
m_ui->setupUi(this);
@@ -563,7 +568,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
for (QSpinBox *widget : asConst(findChildren<QSpinBox *>()))
widget->installEventFilter(wheelEventEater);
loadWindowState();
Utils::Gui::resize(this, m_storeDialogSize);
show();
// Have to be called after show(), because splitter width needed
loadSplitterState();
@@ -604,7 +609,13 @@ OptionsDialog::~OptionsDialog()
{
qDebug("-> destructing Options");
saveWindowState();
// save dialog states
m_storeDialogSize = size();
QStringList hSplitterSizes;
for (const int size : asConst(m_ui->hsplitter->sizes()))
hSplitterSizes.append(QString::number(size));
m_storeHSplitterSize = hSplitterSizes;
for (const QString &path : asConst(m_addedScanDirs))
ScanFoldersModel::instance()->removePath(path);
@@ -619,38 +630,18 @@ void OptionsDialog::changePage(QListWidgetItem *current, QListWidgetItem *previo
m_ui->tabOption->setCurrentIndex(m_ui->tabSelection->row(current));
}
void OptionsDialog::loadWindowState()
{
Utils::Gui::resize(this, Preferences::instance()->getPrefSize());
}
void OptionsDialog::loadSplitterState()
{
const QStringList sizesStr = Preferences::instance()->getPrefHSplitterSizes();
// width has been modified, use height as width reference instead
const int width = Utils::Gui::scaledSize(this
, (m_ui->tabSelection->item(TAB_UI)->sizeHint().height() * 2));
QList<int> sizes {width, (m_ui->hsplitter->width() - width)};
if (sizesStr.size() == 2)
sizes = {sizesStr.first().toInt(), sizesStr.last().toInt()};
m_ui->hsplitter->setSizes(sizes);
}
const QStringList defaultSizes = {QString::number(width), QString::number(m_ui->hsplitter->width() - width)};
void OptionsDialog::saveWindowState() const
{
Preferences *const pref = Preferences::instance();
QList<int> splitterSizes;
for (const QString &string : asConst(m_storeHSplitterSize.get(defaultSizes)))
splitterSizes.append(string.toInt());
// window size
pref->setPrefSize(size());
// Splitter size
const QStringList sizesStr =
{
QString::number(m_ui->hsplitter->sizes().first()),
QString::number(m_ui->hsplitter->sizes().last())
};
pref->setPrefHSplitterSizes(sizesStr);
m_ui->hsplitter->setSizes(splitterSizes);
}
void OptionsDialog::saveOptions()
@@ -1612,6 +1603,8 @@ void OptionsDialog::setLocale(const QString &localeStr)
QLocale locale(localeStr);
if (locale.language() == QLocale::Uzbek)
name = "uz@Latn";
else if (locale.language() == QLocale::Azerbaijani)
name = "az@latin";
else
name = locale.name();
}

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