mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-18 06:28:03 -06:00
Compare commits
54 Commits
release-4.
...
release-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da0b276d5f | ||
|
|
2d73bc9e7d | ||
|
|
fdd54fe568 | ||
|
|
e5ce24e55e | ||
|
|
d90349709b | ||
|
|
adb0fe6582 | ||
|
|
5ed81580c9 | ||
|
|
86d6fb86d7 | ||
|
|
ddec247d4f | ||
|
|
d431ecbe00 | ||
|
|
be929ed88c | ||
|
|
2e1f9bf8be | ||
|
|
7fff393b0e | ||
|
|
a669ec49ad | ||
|
|
1880082017 | ||
|
|
0cbd15890a | ||
|
|
7fe7c6c277 | ||
|
|
e4c177fec7 | ||
|
|
77f4e6c2cf | ||
|
|
4563b11a2e | ||
|
|
cb477f9a29 | ||
|
|
58ac07667e | ||
|
|
74bf3af41c | ||
|
|
9317071122 | ||
|
|
dab32f2090 | ||
|
|
dc464d4d41 | ||
|
|
e7e3f6a9db | ||
|
|
5a1c4e79b3 | ||
|
|
c6d9ab6810 | ||
|
|
d7afad835e | ||
|
|
8608d7b9da | ||
|
|
72970602af | ||
|
|
86579ca87d | ||
|
|
e55582124c | ||
|
|
bd8b06c607 | ||
|
|
230fedf069 | ||
|
|
7bea10f507 | ||
|
|
7cde969b90 | ||
|
|
a3b8f6880b | ||
|
|
ad79fc8d43 | ||
|
|
fb4bf94a56 | ||
|
|
1c184944fd | ||
|
|
ec420f6617 | ||
|
|
d908227619 | ||
|
|
ac8167410b | ||
|
|
26ce187b30 | ||
|
|
2c4e04e537 | ||
|
|
b418f65c2f | ||
|
|
dd3a8d5d56 | ||
|
|
49e54a55df | ||
|
|
8cd0a7ae85 | ||
|
|
442f0df613 | ||
|
|
f9ee5bdb59 | ||
|
|
b9602cc6ab |
10
.github/workflows/ci.yaml
vendored
10
.github/workflows/ci.yaml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/file_health.sh
vendored
2
.github/workflows/file_health.sh
vendored
@@ -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
1
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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" \
|
||||
./
|
||||
|
||||
@@ -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}")
|
||||
|
||||
18
Changelog
18
Changelog
@@ -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
19
build_dist.sh
Executable 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"
|
||||
@@ -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>
|
||||
|
||||
44
configure.ac
44
configure.ac
@@ -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
4
dist/mac/Info.plist
vendored
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
14
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
14
dist/unix/org.qbittorrent.qBittorrent.desktop
vendored
@@ -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 வாடிக்கையாளர்
|
||||
|
||||
4
dist/windows/options.nsi
vendored
4
dist/windows/options.nsi
vendored
@@ -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}"
|
||||
|
||||
|
||||
@@ -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]],
|
||||
[[]])
|
||||
])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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 ¶ms)
|
||||
}
|
||||
#endif
|
||||
BitTorrent::AddTorrentParams torrentParams;
|
||||
TriStateBool skipTorrentDialog;
|
||||
std::optional<bool> skipTorrentDialog;
|
||||
|
||||
for (QString param : params)
|
||||
{
|
||||
@@ -521,7 +522,7 @@ void Application::processParams(const QStringList ¶ms)
|
||||
|
||||
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 ¶ms)
|
||||
|
||||
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 ¶ms)
|
||||
// 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
|
||||
|
||||
@@ -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 ¶ms);
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <QString>
|
||||
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/version.h"
|
||||
#include "ui_stacktracedialog.h"
|
||||
|
||||
StacktraceDialog::StacktraceDialog(QWidget *parent)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
};
|
||||
|
||||
@@ -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 \
|
||||
|
||||
140
src/base/bittorrent/abstractfilestorage.cpp
Normal file
140
src/base/bittorrent/abstractfilestorage.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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")};
|
||||
|
||||
@@ -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
|
||||
{
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ¶ms)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -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 ¶ms = AddTorrentParams());
|
||||
bool addTorrent(const MagnetUri &magnetUri, const AddTorrentParams ¶ms = AddTorrentParams());
|
||||
bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams ¶ms = 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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 ¶ms);
|
||||
~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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/version.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 "es = 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 "es = 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -223,29 +223,14 @@
|
||||
<string>Torrent &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>&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">
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user