mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-02 13:48:05 -06:00
Compare commits
101 Commits
release-4.
...
v4_0_x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2f3d1ec2c | ||
|
|
bc6e3ae40d | ||
|
|
b02e239f7c | ||
|
|
397cd4bf60 | ||
|
|
409f972ad3 | ||
|
|
267961ffca | ||
|
|
dff753c452 | ||
|
|
ce3bafd30d | ||
|
|
e5538d9f25 | ||
|
|
7a8a32b1c3 | ||
|
|
cac5e0391b | ||
|
|
726790fa93 | ||
|
|
c9c7a5be53 | ||
|
|
1495513cfc | ||
|
|
085afaac14 | ||
|
|
d58a54c758 | ||
|
|
78d9bcb6a1 | ||
|
|
1a43cd329d | ||
|
|
2fe687eeca | ||
|
|
107bd8a54f | ||
|
|
865df3fcf1 | ||
|
|
cbf9c52462 | ||
|
|
171e25e962 | ||
|
|
239d14fd10 | ||
|
|
0b7a175156 | ||
|
|
b37dbb60b5 | ||
|
|
d5acd1f210 | ||
|
|
65eda4a68e | ||
|
|
7209881025 | ||
|
|
a5d0a4b619 | ||
|
|
79276a8786 | ||
|
|
fa2b645a64 | ||
|
|
4d5d6df734 | ||
|
|
2c39b69c18 | ||
|
|
13c0077e95 | ||
|
|
9299e3f371 | ||
|
|
b9ddc6ee86 | ||
|
|
276856a614 | ||
|
|
fbd6a8a0da | ||
|
|
6fc18b4af6 | ||
|
|
44d633fb68 | ||
|
|
eb4bf6cc68 | ||
|
|
6db6c850eb | ||
|
|
02ae1e3734 | ||
|
|
eb887139fd | ||
|
|
84805f7fb8 | ||
|
|
2719131ed2 | ||
|
|
52401bd2b0 | ||
|
|
4834703bc4 | ||
|
|
3ed73244b1 | ||
|
|
97cd430125 | ||
|
|
d202b85d51 | ||
|
|
c51b79e9fc | ||
|
|
4449018207 | ||
|
|
ced8e41473 | ||
|
|
2c66ed6708 | ||
|
|
c7d3d6ac90 | ||
|
|
13210b3e9f | ||
|
|
6e622fc23b | ||
|
|
ae35111b59 | ||
|
|
e1c3d419a7 | ||
|
|
7396b8adba | ||
|
|
c09001545d | ||
|
|
f8d4315f7e | ||
|
|
1fa2957d27 | ||
|
|
ade50d2b53 | ||
|
|
0fa1d35b87 | ||
|
|
6486fc5f4d | ||
|
|
1e059ab1a2 | ||
|
|
15b137211b | ||
|
|
6f8f1d7bad | ||
|
|
a31f0c0a3d | ||
|
|
f977d1293a | ||
|
|
1399be50cb | ||
|
|
52dcf32cc8 | ||
|
|
52b2b807ab | ||
|
|
5cf4f00824 | ||
|
|
faa6fad025 | ||
|
|
9f94bbce3a | ||
|
|
5c49b2486c | ||
|
|
4f6e7f97c6 | ||
|
|
7751c5b75c | ||
|
|
a1a9f3317b | ||
|
|
fb20f59a96 | ||
|
|
a15e3407b0 | ||
|
|
e267c2d37a | ||
|
|
ae32edeb26 | ||
|
|
34d38ef466 | ||
|
|
120ee6b836 | ||
|
|
7d25b6fce2 | ||
|
|
068eff9e9f | ||
|
|
31a55f79f1 | ||
|
|
bac032e01c | ||
|
|
b809941f02 | ||
|
|
77c3758090 | ||
|
|
5758817189 | ||
|
|
acc9f08a05 | ||
|
|
f3b7f17a7c | ||
|
|
dfc3f047e2 | ||
|
|
223ab7de84 | ||
|
|
d2a4027347 |
18
.github/ISSUE_TEMPLATE.md
vendored
18
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,14 +1,20 @@
|
|||||||
**Please provide the following information**
|
**Please provide the following information**
|
||||||
|
|
||||||
### qBittorrent version and Operating System:
|
### qBittorrent version and Operating System
|
||||||
|
(type here)
|
||||||
|
|
||||||
### If on linux, libtorrent and Qt version:
|
### If on linux, libtorrent and Qt version
|
||||||
|
(type here)
|
||||||
|
|
||||||
### What is the problem:
|
### What is the problem
|
||||||
|
(type here)
|
||||||
|
|
||||||
### What is the expected behavior:
|
### What is the expected behavior
|
||||||
|
(type here)
|
||||||
|
|
||||||
### Steps to reproduce:
|
### Steps to reproduce
|
||||||
|
(type here)
|
||||||
|
|
||||||
### Extra info(if any):
|
### Extra info(if any)
|
||||||
|
(type here)
|
||||||
|
|
||||||
|
|||||||
19
.travis.yml
19
.travis.yml
@@ -76,10 +76,13 @@ before_install:
|
|||||||
|
|
||||||
- shopt -s expand_aliases
|
- shopt -s expand_aliases
|
||||||
- alias make="colormake -j3" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
- alias make="colormake -j3" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
||||||
#- libt_path="$HOME/libt_install"
|
|
||||||
#- ltconf="$ltconf --prefix="$libt_path" --disable-geoip"
|
|
||||||
- qbt_path="$HOME/qbt_install"
|
- qbt_path="$HOME/qbt_install"
|
||||||
- qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH="$libt_path/lib/pkgconfig":/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
|
- |
|
||||||
|
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
|
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
else
|
||||||
|
qbtconf="$qbtconf --prefix="$qbt_path""
|
||||||
|
fi
|
||||||
|
|
||||||
# options for specific branches
|
# options for specific branches
|
||||||
- if [ "$gui" = false ]; then qbtconf="$qbtconf --disable-gui" ; fi
|
- if [ "$gui" = false ]; then qbtconf="$qbtconf --disable-gui" ; fi
|
||||||
@@ -131,13 +134,13 @@ install:
|
|||||||
cp "version" $HOME/hombebrew_cache
|
cp "version" $HOME/hombebrew_cache
|
||||||
cd "$HOME/hombebrew_cache"
|
cd "$HOME/hombebrew_cache"
|
||||||
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar.rb
|
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar.rb
|
||||||
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar-1.0.11+git20170910.6d5625e0ea.el_capitan.bottle.tar.gz
|
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar-1.1.6+git20180101.b45acf28a5+patched-configure.el_capitan.bottle.tar.gz
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy custom libtorrent bottle to homebrew's cache so it can find and install it
|
# Copy custom libtorrent bottle to homebrew's cache so it can find and install it
|
||||||
# Also install our custom libtorrent formula by passing the local path to it
|
# Also install our custom libtorrent formula by passing the local path to it
|
||||||
# These 2 files are restored from Travis' cache.
|
# These 2 files are restored from Travis' cache.
|
||||||
cp "$HOME/hombebrew_cache/libtorrent-rasterbar-1.0.11+git20170910.6d5625e0ea.el_capitan.bottle.tar.gz" "$(brew --cache)"
|
cp "$HOME/hombebrew_cache/libtorrent-rasterbar-1.1.6+git20180101.b45acf28a5+patched-configure.el_capitan.bottle.tar.gz" "$(brew --cache)"
|
||||||
brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb"
|
brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb"
|
||||||
|
|
||||||
if [ "$build_system" = "cmake" ]; then
|
if [ "$build_system" = "cmake" ]; then
|
||||||
@@ -168,11 +171,15 @@ script:
|
|||||||
BUILD_TOOL="ninja"
|
BUILD_TOOL="ninja"
|
||||||
fi
|
fi
|
||||||
if [ "$build_system" = "qmake" ]; then
|
if [ "$build_system" = "qmake" ]; then
|
||||||
./bootstrap.sh && ./configure $qbtconf
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||||
|
# For some reason for RC_1_1 we need to also specify the OpenSSL compiler/linker flags
|
||||||
|
# Homebrew doesn't symlink OpenSSL for security reasons
|
||||||
|
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --cflags openssl)" LDFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --libs openssl)"
|
||||||
sed -i "" -e "s/^\(CC.*&&\).*$/\1 $CC/" src/Makefile # workaround for Qt & ccache: https://bugreports.qt.io/browse/QTBUG-31034
|
sed -i "" -e "s/^\(CC.*&&\).*$/\1 $CC/" src/Makefile # workaround for Qt & ccache: https://bugreports.qt.io/browse/QTBUG-31034
|
||||||
sed -i "" -e "s/^\(CXX.*&&\).*$/\1 $CXX/" src/Makefile
|
sed -i "" -e "s/^\(CXX.*&&\).*$/\1 $CXX/" src/Makefile
|
||||||
sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs -Wno-inconsistent-missing-override/' src/Makefile
|
sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs -Wno-inconsistent-missing-override/' src/Makefile
|
||||||
|
else
|
||||||
|
./bootstrap.sh && ./configure $qbtconf
|
||||||
fi
|
fi
|
||||||
BUILD_TOOL="make"
|
BUILD_TOOL="make"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -240,7 +240,23 @@ Example:
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9. Misc. ###
|
### 9. Include guard. ###
|
||||||
|
`#pragma once` should be used instead of "include guard" in new code:
|
||||||
|
```c++
|
||||||
|
// examplewidget.h
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class ExampleWidget : public QWidget
|
||||||
|
{
|
||||||
|
// (some code omitted)
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10. Misc. ###
|
||||||
|
|
||||||
* Line breaks for long lines with operation:
|
* Line breaks for long lines with operation:
|
||||||
|
|
||||||
|
|||||||
73
Changelog
73
Changelog
@@ -1,3 +1,76 @@
|
|||||||
|
* Fri Feb 16 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.0.4
|
||||||
|
- FEATURE: Add source field in Torrent creator. Closes #7965. (Chocobo1)
|
||||||
|
- FEATURE: Torrent creator: raise maximum piece size to 32 MiB (Chocobo1)
|
||||||
|
- FEATURE: Add a force reannounce option in the transfer list context menu. Closes #6448. (Jesse Bryan)
|
||||||
|
- BUGFIX: Fix sorting of country flags column in Peers tab. (sledgehammer999)
|
||||||
|
- BUGFIX: Fix natural sorting when the common part of 2 strings ends partially in a number which continues in the uncommon part. Closes #8080 #6732. (sledgehammer999)
|
||||||
|
- BUGFIX: Fix application of speed limits on LAN and μTP connections. Closes #7745. (sledgehammer999)
|
||||||
|
- BUGFIX: Make peer information flags in peerlist more readable. (thalieht)
|
||||||
|
- BUGFIX: Fix gui issues on high DPI monitor. (Chocobo1)
|
||||||
|
- BUGFIX: Fix dialog and column size on high DPI monitors. (Chocobo1)
|
||||||
|
- BUGFIX: Fix constant status of '[F] Downloading'. Closes #7628. (sledgehammer999)
|
||||||
|
- BUGFIX: Fix translation context. Closes #8211. (sledgehammer999)
|
||||||
|
- BUGFIX: Separate subnet whitelist options into two lines. (Thomas Piccirello)
|
||||||
|
- BUGFIX: Don't set application name twice. (Luís Pereira)
|
||||||
|
- BUGFIX: Set default file log size to 65 KiB and delete backup logs older than 1 month. (sledgehammer999)
|
||||||
|
- WEBUI: Only prepend scheme when it is not present. Closes #8057. (Chocobo1)
|
||||||
|
- WEBUI: Add "Remaining" and "Availability" columns to webui Content tab. (Thomas Piccirello)
|
||||||
|
- WEBUI: Make value formatting consistent with GUI (Thomas Piccirello)
|
||||||
|
- WEBUI: Reposition Total Size column to match gui (Thomas Piccirello)
|
||||||
|
- WEBUI: Add Tags and Time Active columns (Thomas Piccirello)
|
||||||
|
- WEBUI: Use https for www.qbittorrent.org (Thomas Piccirello)
|
||||||
|
- WEBUI: Match webui statuses to gui, closes #7516 (Thomas Piccirello)
|
||||||
|
- WEBUI: Right-align stat values (Thomas Piccirello)
|
||||||
|
- WEBUI: Add missing units. (Thomas Piccirello)
|
||||||
|
- RSS: Fix crash when deleting rule because it tries to update. Closes #8094 (glassez)
|
||||||
|
- RSS: Don't process new/updated RSS rules when disabled (glassez)
|
||||||
|
- RSS: Remove legacy and corrupted RSS settings (glassez)
|
||||||
|
- SEARCH: Search only when category is supported by plugin. Closes #8053. (jan.karberg)
|
||||||
|
- SEARCH: Only add search separators as needed. (Thomas Piccirello)
|
||||||
|
- COSMETIC: Tweak spacing in torrent properties widget and speed widget. (Chocobo1)
|
||||||
|
- WINDOWS: Use standard folder icon for open file behavior on Windows. Closes #7880. (Chocobo1)
|
||||||
|
- WINDOWS: Revert "Run external program" function. Now you will not be able to directly run batch scripts. (Chocobo1)
|
||||||
|
- MACOS: Fix torrent file selection in Finder on mac (vit9696)
|
||||||
|
- MACOS: Fix Finder reveal in preview and torrent contents (vit9696)
|
||||||
|
- MACOS: Fix cmd+w not closing the main window on macOS (vit9696)
|
||||||
|
- OTHER: Fix splitting of compiler flags in configure. Autoconf removes a set of [] during script translation, resulting in a wrong sed command. (sledgehammer999)
|
||||||
|
- OTHER: configure: Parse all compiler related flags together. (sledgehammer999)
|
||||||
|
- OTHER: Update copyright year. (sledgehammer999)
|
||||||
|
|
||||||
|
* Sun Dec 17 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.0.3
|
||||||
|
- BUGFIX: Add height padding to the transfer list icons. Closes #7951. (sledgehammer999)
|
||||||
|
- BUGFIX: Allow to drag-n-drop URLs into mainwindow to initiate download. (Chocobo1)
|
||||||
|
- BUGFIX: Fix crash when fitlering search results. Stable sorting is removed. Closes #7952.(Chocobo1)
|
||||||
|
- WEBUI: Fix missing qbt logo on login page in webUI. Closes #7953. (Chocobo1)
|
||||||
|
- WEBUI: Add check to avoid type error after logout. (Chocobo1)
|
||||||
|
- WEBUI: Use POST for logout command. This is to avoid browser being smart to prefetch the link then logging out the user. (Chocobo1)
|
||||||
|
- WEBUI: Fix WebUI is not reachable via IPv6. (glassez)
|
||||||
|
- WINDOWS: Disable the "?" help button in all dialogs on Windows. Closes #7365. Requires Qt 5.10. (Chocobo1)
|
||||||
|
|
||||||
|
* Fri Dec 01 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.0.2
|
||||||
|
- BUGFIX: Fix crash on some systems when creating address object for 255.255.255.255. Closes #7735. (sledgehammer999)
|
||||||
|
- PERFORMANCE: Change MixedModeAlgorithm default to TCP. This was the v3_3_x default and should sustain higher speeds. Closes #7779. (Chocobo1)
|
||||||
|
- PERFORMANCE: Stop logging IP filter parsing errors after a while, otherwise the GUI freezes or qBittorrent doesn't start. (sledgehammer999)
|
||||||
|
- GUI: Implement stable sort. Rows in transfer list shouldn't flicker anymore. (Chocobo1)
|
||||||
|
- WEBUI: Fix build when webui is disabled. (Heiko Becker)
|
||||||
|
- RSS: Fix build because of missing header. Closes #7805. (thoradia)
|
||||||
|
- RSS: Fix RSS parser. (glassez)
|
||||||
|
- RSS: Implement Import/Export RSS rules in legacy(aka v3_3_x) format. (glassez)
|
||||||
|
- RSS: Implement Import/Export RSS rules in JSON format. (glassez)
|
||||||
|
- WINDOWS: Fixed blurry text under Windows by setting DPI awareness to default. (TheNicker)
|
||||||
|
- LINUX: Fix i386 build. (Evgeny Lensky)
|
||||||
|
|
||||||
|
* Wed Nov 22 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.0.1
|
||||||
|
- BUGFIX: Fix crash on opening torrent/magnet (uninitialized pointer). Closes #7739 #7723. (sledgehammer999)
|
||||||
|
- BUGFIX: Enable preferences Apply button when ip banlist is modified (Thomas Piccirello)
|
||||||
|
- BUGFIX: Allow drag-n-drop magnet links to mainwindow. Closes #7742. (Chocobo1)
|
||||||
|
- BUGFIX: Fix crash when aborting a torrent creation process. Closes #7783. (Chocobo1)
|
||||||
|
- BUGFIX: Correctly check if torrent passed during application start already exists. (sledgehammer999)
|
||||||
|
- WEBUI: Add ip subnet whitelist for bypassing webui auth (Thomas Piccirello)
|
||||||
|
- WEBUI: Fix logo missing in login page (Chocobo1)
|
||||||
|
- COSMETIC: Fix english typo. (sledgehammer999)
|
||||||
|
- OTHER: cmake: qtsingleapplication should always be built statically (luigino)
|
||||||
|
|
||||||
* Mon Nov 20 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.0.0
|
* Mon Nov 20 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.0.0
|
||||||
- FEATURE: Change qbittorrent logo. Issue #6467. (HVS, Atif Afzal, sledgehammer999)
|
- FEATURE: Change qbittorrent logo. Issue #6467. (HVS, Atif Afzal, sledgehammer999)
|
||||||
- FEATURE: New icon theme with SVG source, so we can scale it appropriately in the future. (Bert Verhelst)
|
- FEATURE: New icon theme with SVG source, so we can scale it appropriately in the future. (Bert Verhelst)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ You can also download it from [here](https://github.com/qbittorrent/qBittorrent/
|
|||||||
|
|
||||||
### Misc:
|
### Misc:
|
||||||
For more information please visit:
|
For more information please visit:
|
||||||
http://www.qbittorrent.org
|
https://www.qbittorrent.org
|
||||||
|
|
||||||
or our wiki here:
|
or our wiki here:
|
||||||
http://wiki.qbittorrent.org
|
http://wiki.qbittorrent.org
|
||||||
|
|||||||
40
configure
vendored
40
configure
vendored
@@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for qbittorrent v3.2.0alpha.
|
# Generated by GNU Autoconf 2.69 for qbittorrent v4.0.4.
|
||||||
#
|
#
|
||||||
# Report bugs to <bugs.qbittorrent.org>.
|
# Report bugs to <bugs.qbittorrent.org>.
|
||||||
#
|
#
|
||||||
@@ -580,10 +580,10 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='qbittorrent'
|
PACKAGE_NAME='qbittorrent'
|
||||||
PACKAGE_TARNAME='qbittorrent'
|
PACKAGE_TARNAME='qbittorrent'
|
||||||
PACKAGE_VERSION='v3.2.0alpha'
|
PACKAGE_VERSION='v4.0.4'
|
||||||
PACKAGE_STRING='qbittorrent v3.2.0alpha'
|
PACKAGE_STRING='qbittorrent v4.0.4'
|
||||||
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
||||||
PACKAGE_URL='http://www.qbittorrent.org/'
|
PACKAGE_URL='https://www.qbittorrent.org/'
|
||||||
|
|
||||||
ac_subst_vars='am__EXEEXT_FALSE
|
ac_subst_vars='am__EXEEXT_FALSE
|
||||||
am__EXEEXT_TRUE
|
am__EXEEXT_TRUE
|
||||||
@@ -1296,7 +1296,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures qbittorrent v3.2.0alpha to adapt to many kinds of systems.
|
\`configure' configures qbittorrent v4.0.4 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1367,7 +1367,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of qbittorrent v3.2.0alpha:";;
|
short | recursive ) echo "Configuration of qbittorrent v4.0.4:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1438,7 +1438,7 @@ Use these variables to override the choices made by `configure' or to help
|
|||||||
it to find libraries and programs with nonstandard names/locations.
|
it to find libraries and programs with nonstandard names/locations.
|
||||||
|
|
||||||
Report bugs to <bugs.qbittorrent.org>.
|
Report bugs to <bugs.qbittorrent.org>.
|
||||||
qbittorrent home page: <http://www.qbittorrent.org/>.
|
qbittorrent home page: <https://www.qbittorrent.org/>.
|
||||||
_ACEOF
|
_ACEOF
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
fi
|
fi
|
||||||
@@ -1501,7 +1501,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
qbittorrent configure v3.2.0alpha
|
qbittorrent configure v4.0.4
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@@ -1640,7 +1640,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by qbittorrent $as_me v3.2.0alpha, which was
|
It was created by qbittorrent $as_me v4.0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -3818,7 +3818,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='qbittorrent'
|
PACKAGE='qbittorrent'
|
||||||
VERSION='v3.2.0alpha'
|
VERSION='v4.0.4'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@@ -4705,9 +4705,8 @@ fi
|
|||||||
libsubdirs="lib64 libx32 lib lib64" ;; #(
|
libsubdirs="lib64 libx32 lib lib64" ;; #(
|
||||||
ppc64|s390x|sparc64|aarch64|ppc64le) :
|
ppc64|s390x|sparc64|aarch64|ppc64le) :
|
||||||
libsubdirs="lib64 lib lib64" ;; #(
|
libsubdirs="lib64 lib lib64" ;; #(
|
||||||
libsubdirs="lib") :
|
|
||||||
;; #(
|
|
||||||
*) :
|
*) :
|
||||||
|
libsubdirs="lib"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -5502,7 +5501,7 @@ extract() {
|
|||||||
new_line='
|
new_line='
|
||||||
'
|
'
|
||||||
# Convert " -" to "\n" if not between quotes and remove possible leading white spaces
|
# Convert " -" to "\n" if not between quotes and remove possible leading white spaces
|
||||||
string=$(echo " $*" | $SED -e "s: -:\\${new_line}:g" -e 's:"\(.*\)\n\(.*\)":\"\1 -\2":g' -e "s:'\(.*\)\n\(.*\)':\'\1 -\2':g" -e 's/^[:space:]*//')
|
string=$(echo " $*" | $SED -e "s: -:\\${new_line}:g" -e 's:"\(.*\)\n\(.*\)":\"\1 -\2":g' -e "s:'\(.*\)\n\(.*\)':\'\1 -\2':g" -e 's/^[[:space:]]*//')
|
||||||
SAVEIFS=$IFS
|
SAVEIFS=$IFS
|
||||||
IFS=$(printf "\n\b")
|
IFS=$(printf "\n\b")
|
||||||
for i in $string; do
|
for i in $string; do
|
||||||
@@ -5516,9 +5515,8 @@ extract() {
|
|||||||
IFS=$SAVEIFS
|
IFS=$SAVEIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
extract $CPPFLAGS
|
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
|
||||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||||
QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS $CXXFLAGS"
|
|
||||||
|
|
||||||
# Substitute the values of these vars in conf.pri.in
|
# Substitute the values of these vars in conf.pri.in
|
||||||
|
|
||||||
@@ -6100,7 +6098,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by qbittorrent $as_me v3.2.0alpha, which was
|
This file was extended by qbittorrent $as_me v4.0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -6152,13 +6150,13 @@ Configuration commands:
|
|||||||
$config_commands
|
$config_commands
|
||||||
|
|
||||||
Report bugs to <bugs.qbittorrent.org>.
|
Report bugs to <bugs.qbittorrent.org>.
|
||||||
qbittorrent home page: <http://www.qbittorrent.org/>."
|
qbittorrent home page: <https://www.qbittorrent.org/>."
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
qbittorrent config.status v3.2.0alpha
|
qbittorrent config.status v4.0.4
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
@@ -7415,7 +7413,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by qbittorrent $as_me v3.2.0alpha, which was
|
This file was extended by qbittorrent $as_me v4.0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -7467,13 +7465,13 @@ Configuration commands:
|
|||||||
$config_commands
|
$config_commands
|
||||||
|
|
||||||
Report bugs to <bugs.qbittorrent.org>.
|
Report bugs to <bugs.qbittorrent.org>.
|
||||||
qbittorrent home page: <http://www.qbittorrent.org/>."
|
qbittorrent home page: <https://www.qbittorrent.org/>."
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
qbittorrent config.status v3.2.0alpha
|
qbittorrent config.status v4.0.4
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([qbittorrent], [v3.2.0alpha], [bugs.qbittorrent.org], [], [http://www.qbittorrent.org/])
|
AC_INIT([qbittorrent], [v4.0.4], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
@@ -190,7 +190,7 @@ extract() {
|
|||||||
new_line='
|
new_line='
|
||||||
'
|
'
|
||||||
# Convert " -" to "\n" if not between quotes and remove possible leading white spaces
|
# Convert " -" to "\n" if not between quotes and remove possible leading white spaces
|
||||||
string=$(echo " $*" | $SED -e "s: -:\\${new_line}:g" -e 's:"\(.*\)\n\(.*\)":\"\1 -\2":g' -e "s:'\(.*\)\n\(.*\)':\'\1 -\2':g" -e 's/^[[:space:]]*//')
|
string=$(echo " $*" | $SED -e "s: -:\\${new_line}:g" -e 's:"\(.*\)\n\(.*\)":\"\1 -\2":g' -e "s:'\(.*\)\n\(.*\)':\'\1 -\2':g" -e 's/^[[[:space:]]]*//')
|
||||||
SAVEIFS=$IFS
|
SAVEIFS=$IFS
|
||||||
IFS=$(printf "\n\b")
|
IFS=$(printf "\n\b")
|
||||||
for i in $string; do
|
for i in $string; do
|
||||||
@@ -204,9 +204,8 @@ extract() {
|
|||||||
IFS=$SAVEIFS
|
IFS=$SAVEIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
extract $CPPFLAGS
|
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
|
||||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||||
QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS $CXXFLAGS"
|
|
||||||
|
|
||||||
# Substitute the values of these vars in conf.pri.in
|
# Substitute the values of these vars in conf.pri.in
|
||||||
AC_SUBST(QBT_CONF_INCLUDES)
|
AC_SUBST(QBT_CONF_INCLUDES)
|
||||||
|
|||||||
4
dist/mac/Info.plist
vendored
4
dist/mac/Info.plist
vendored
@@ -45,7 +45,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.0.0</string>
|
<string>4.0.4</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>qBit</string>
|
<string>qBit</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<key>NSAppleScriptEnabled</key>
|
<key>NSAppleScriptEnabled</key>
|
||||||
<string>YES</string>
|
<string>YES</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2006-2017 The qBittorrent project</string>
|
<string>Copyright © 2006-2018 The qBittorrent project</string>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
2
dist/unix/qbittorrent.appdata.xml
vendored
2
dist/unix/qbittorrent.appdata.xml
vendored
@@ -56,7 +56,7 @@
|
|||||||
</image>
|
</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<url type="homepage">http://www.qbittorrent.org/</url>
|
<url type="homepage">https://www.qbittorrent.org/</url>
|
||||||
<update_contact>sledgehammer999@qbittorrent.org</update_contact>
|
<update_contact>sledgehammer999@qbittorrent.org</update_contact>
|
||||||
<developer_name>The qBittorrent Project</developer_name>
|
<developer_name>The qBittorrent Project</developer_name>
|
||||||
<url type="bugtracker">http://bugs.qbittorrent.org/</url>
|
<url type="bugtracker">http://bugs.qbittorrent.org/</url>
|
||||||
|
|||||||
2
dist/windows/installer.nsi
vendored
2
dist/windows/installer.nsi
vendored
@@ -86,7 +86,7 @@ Section $(inst_qbt_req) ;"qBittorrent (required)"
|
|||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "UninstallString" '"$INSTDIR\uninst.exe"'
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "UninstallString" '"$INSTDIR\uninst.exe"'
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayIcon" '"$INSTDIR\qbittorrent.exe",0'
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayIcon" '"$INSTDIR\qbittorrent.exe",0'
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "Publisher" "The qBittorrent project"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "Publisher" "The qBittorrent project"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "URLInfoAbout" "http://www.qbittorrent.org"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "URLInfoAbout" "https://www.qbittorrent.org"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayVersion" "${PROG_VERSION}"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayVersion" "${PROG_VERSION}"
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "NoModify" 1
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "NoModify" 1
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "NoRepair" 1
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "NoRepair" 1
|
||||||
|
|||||||
4
dist/windows/options.nsi
vendored
4
dist/windows/options.nsi
vendored
@@ -27,7 +27,7 @@ XPStyle on
|
|||||||
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
||||||
|
|
||||||
; Program specific
|
; Program specific
|
||||||
!define PROG_VERSION "4.0.0"
|
!define PROG_VERSION "4.0.4"
|
||||||
|
|
||||||
!define MUI_FINISHPAGE_RUN
|
!define MUI_FINISHPAGE_RUN
|
||||||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
||||||
@@ -50,7 +50,7 @@ XPStyle on
|
|||||||
;Installer Version Information
|
;Installer Version Information
|
||||||
VIAddVersionKey "ProductName" "qBittorrent"
|
VIAddVersionKey "ProductName" "qBittorrent"
|
||||||
VIAddVersionKey "CompanyName" "The qBittorrent project"
|
VIAddVersionKey "CompanyName" "The qBittorrent project"
|
||||||
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2017 The qBittorrent project"
|
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2018 The qBittorrent project"
|
||||||
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
||||||
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
||||||
|
|
||||||
|
|||||||
2
dist/windows/qt.conf
vendored
2
dist/windows/qt.conf
vendored
@@ -2,4 +2,4 @@
|
|||||||
Translations = translations
|
Translations = translations
|
||||||
|
|
||||||
[Platforms]
|
[Platforms]
|
||||||
WindowsArguments = dpiawareness=1
|
;WindowsArguments = dpiawareness=1
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
|
|||||||
AS_CASE([${host_cpu}],
|
AS_CASE([${host_cpu}],
|
||||||
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
|
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
|
||||||
[ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
|
[ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
|
||||||
[libsubdirs="lib"],
|
[libsubdirs="lib"]
|
||||||
)
|
)
|
||||||
|
|
||||||
dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
|
dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace
|
|||||||
const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path");
|
const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path");
|
||||||
const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup");
|
const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup");
|
||||||
const QString KEY_FILELOGGER_DELETEOLD = FILELOGGER_SETTINGS_KEY("DeleteOld");
|
const QString KEY_FILELOGGER_DELETEOLD = FILELOGGER_SETTINGS_KEY("DeleteOld");
|
||||||
const QString KEY_FILELOGGER_MAXSIZE = FILELOGGER_SETTINGS_KEY("MaxSize");
|
const QString KEY_FILELOGGER_MAXSIZEBYTES = FILELOGGER_SETTINGS_KEY("MaxSizeBytes");
|
||||||
const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age");
|
const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age");
|
||||||
const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType");
|
const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType");
|
||||||
|
|
||||||
@@ -98,6 +98,10 @@ namespace
|
|||||||
const char PARAMS_SEPARATOR[] = "|";
|
const char PARAMS_SEPARATOR[] = "|";
|
||||||
|
|
||||||
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QLatin1String("profile");
|
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QLatin1String("profile");
|
||||||
|
|
||||||
|
const int MIN_FILELOG_SIZE = 1024; // 1KiB
|
||||||
|
const int MAX_FILELOG_SIZE = 1000 * 1024 * 1024; // 1000MiB
|
||||||
|
const int DEFAULT_FILELOG_SIZE = 65 * 1024; // 65KiB
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(const QString &id, int &argc, char **argv)
|
Application::Application(const QString &id, int &argc, char **argv)
|
||||||
@@ -105,6 +109,9 @@ Application::Application(const QString &id, int &argc, char **argv)
|
|||||||
, m_running(false)
|
, m_running(false)
|
||||||
, m_shutdownAct(ShutdownDialogAction::Exit)
|
, m_shutdownAct(ShutdownDialogAction::Exit)
|
||||||
, m_commandLineArgs(parseCommandLine(this->arguments()))
|
, m_commandLineArgs(parseCommandLine(this->arguments()))
|
||||||
|
#ifndef DISABLE_WEBUI
|
||||||
|
, m_webui(nullptr)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
qRegisterMetaType<Log::Msg>("Log::Msg");
|
qRegisterMetaType<Log::Msg>("Log::Msg");
|
||||||
|
|
||||||
@@ -125,7 +132,6 @@ Application::Application(const QString &id, int &argc, char **argv)
|
|||||||
if (m_commandLineArgs.webUiPort > 0) // it will be -1 when user did not set any value
|
if (m_commandLineArgs.webUiPort > 0) // it will be -1 when user did not set any value
|
||||||
Preferences::instance()->setWebUiPort(m_commandLineArgs.webUiPort);
|
Preferences::instance()->setWebUiPort(m_commandLineArgs.webUiPort);
|
||||||
|
|
||||||
setApplicationName("qBittorrent");
|
|
||||||
initializeTranslation();
|
initializeTranslation();
|
||||||
|
|
||||||
#if !defined(DISABLE_GUI)
|
#if !defined(DISABLE_GUI)
|
||||||
@@ -218,29 +224,22 @@ void Application::setFileLoggerDeleteOld(bool value)
|
|||||||
|
|
||||||
int Application::fileLoggerMaxSize() const
|
int Application::fileLoggerMaxSize() const
|
||||||
{
|
{
|
||||||
int val = settings()->loadValue(KEY_FILELOGGER_MAXSIZE, 10).toInt();
|
int val = settings()->loadValue(KEY_FILELOGGER_MAXSIZEBYTES, DEFAULT_FILELOG_SIZE).toInt();
|
||||||
if (val < 1)
|
return std::min(std::max(val, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
|
||||||
return 1;
|
|
||||||
if (val > 1000)
|
|
||||||
return 1000;
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerMaxSize(const int value)
|
void Application::setFileLoggerMaxSize(const int bytes)
|
||||||
{
|
{
|
||||||
|
int clampedValue = std::min(std::max(bytes, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
|
||||||
if (m_fileLogger)
|
if (m_fileLogger)
|
||||||
m_fileLogger->setMaxSize(value);
|
m_fileLogger->setMaxSize(clampedValue);
|
||||||
settings()->storeValue(KEY_FILELOGGER_MAXSIZE, std::min(std::max(value, 1), 1000));
|
settings()->storeValue(KEY_FILELOGGER_MAXSIZEBYTES, clampedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::fileLoggerAge() const
|
int Application::fileLoggerAge() const
|
||||||
{
|
{
|
||||||
int val = settings()->loadValue(KEY_FILELOGGER_AGE, 6).toInt();
|
int val = settings()->loadValue(KEY_FILELOGGER_AGE, 1).toInt();
|
||||||
if (val < 1)
|
return std::min(std::max(val, 1), 365);
|
||||||
return 1;
|
|
||||||
if (val > 365)
|
|
||||||
return 365;
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerAge(const int value)
|
void Application::setFileLoggerAge(const int value)
|
||||||
@@ -288,27 +287,6 @@ void Application::runExternalProgram(BitTorrent::TorrentHandle *const torrent) c
|
|||||||
|
|
||||||
#if defined(Q_OS_UNIX)
|
#if defined(Q_OS_UNIX)
|
||||||
QProcess::startDetached(QLatin1String("/bin/sh"), {QLatin1String("-c"), program});
|
QProcess::startDetached(QLatin1String("/bin/sh"), {QLatin1String("-c"), program});
|
||||||
#elif defined(Q_OS_WIN) // test cmd: `echo "%F" > "c:\ab ba.txt"`
|
|
||||||
program.prepend(QLatin1String("\"")).append(QLatin1String("\""));
|
|
||||||
program.prepend(Utils::Misc::windowsSystemPath() + QLatin1String("\\cmd.exe /C "));
|
|
||||||
const int cmdMaxLength = 32768; // max length (incl. terminate char) for `lpCommandLine` in `CreateProcessW()`
|
|
||||||
if ((program.size() + 1) > cmdMaxLength) {
|
|
||||||
logger->addMessage(tr("Torrent: %1, run external program command too long (length > %2), execution failed.").arg(torrent->name()).arg(cmdMaxLength), Log::CRITICAL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
STARTUPINFOW si = {0};
|
|
||||||
si.cb = sizeof(si);
|
|
||||||
PROCESS_INFORMATION pi = {0};
|
|
||||||
|
|
||||||
WCHAR *arg = new WCHAR[program.size() + 1];
|
|
||||||
program.toWCharArray(arg);
|
|
||||||
arg[program.size()] = L'\0';
|
|
||||||
if (CreateProcessW(NULL, arg, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
}
|
|
||||||
delete[] arg;
|
|
||||||
#else
|
#else
|
||||||
QProcess::startDetached(program);
|
QProcess::startDetached(program);
|
||||||
#endif
|
#endif
|
||||||
@@ -518,15 +496,15 @@ int Application::exec(const QStringList ¶ms)
|
|||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
m_running = true;
|
m_running = true;
|
||||||
|
|
||||||
|
// Now UI is ready to process signals from Session
|
||||||
|
BitTorrent::Session::instance()->startUpTorrents();
|
||||||
|
|
||||||
m_paramsQueue = params + m_paramsQueue;
|
m_paramsQueue = params + m_paramsQueue;
|
||||||
if (!m_paramsQueue.isEmpty()) {
|
if (!m_paramsQueue.isEmpty()) {
|
||||||
processParams(m_paramsQueue);
|
processParams(m_paramsQueue);
|
||||||
m_paramsQueue.clear();
|
m_paramsQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now UI is ready to process signals from Session
|
|
||||||
BitTorrent::Session::instance()->startUpTorrents();
|
|
||||||
|
|
||||||
return BaseApplication::exec();
|
return BaseApplication::exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,15 +577,15 @@ void Application::initializeTranslation()
|
|||||||
// Load translation
|
// Load translation
|
||||||
QString localeStr = pref->getLocale();
|
QString localeStr = pref->getLocale();
|
||||||
|
|
||||||
if (m_qtTranslator.load(QString::fromUtf8("qtbase_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) ||
|
if (m_qtTranslator.load(QLatin1String("qtbase_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) ||
|
||||||
m_qtTranslator.load(QString::fromUtf8("qt_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
m_qtTranslator.load(QLatin1String("qt_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||||
qDebug("Qt %s locale recognized, using translation.", qUtf8Printable(localeStr));
|
qDebug("Qt %s locale recognized, using translation.", qUtf8Printable(localeStr));
|
||||||
else
|
else
|
||||||
qDebug("Qt %s locale unrecognized, using default (en).", qUtf8Printable(localeStr));
|
qDebug("Qt %s locale unrecognized, using default (en).", qUtf8Printable(localeStr));
|
||||||
|
|
||||||
installTranslator(&m_qtTranslator);
|
installTranslator(&m_qtTranslator);
|
||||||
|
|
||||||
if (m_translator.load(QString::fromUtf8(":/lang/qbittorrent_") + localeStr))
|
if (m_translator.load(QLatin1String(":/lang/qbittorrent_") + localeStr))
|
||||||
qDebug("%s locale recognized, using translation.", qUtf8Printable(localeStr));
|
qDebug("%s locale recognized, using translation.", qUtf8Printable(localeStr));
|
||||||
else
|
else
|
||||||
qDebug("%s locale unrecognized, using default (en).", qUtf8Printable(localeStr));
|
qDebug("%s locale unrecognized, using default (en).", qUtf8Printable(localeStr));
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public:
|
|||||||
bool isFileLoggerDeleteOld() const;
|
bool isFileLoggerDeleteOld() const;
|
||||||
void setFileLoggerDeleteOld(bool value);
|
void setFileLoggerDeleteOld(bool value);
|
||||||
int fileLoggerMaxSize() const;
|
int fileLoggerMaxSize() const;
|
||||||
void setFileLoggerMaxSize(const int value);
|
void setFileLoggerMaxSize(const int bytes);
|
||||||
int fileLoggerAge() const;
|
int fileLoggerAge() const;
|
||||||
void setFileLoggerAge(const int value);
|
void setFileLoggerAge(const int value);
|
||||||
int fileLoggerAgeType() const;
|
int fileLoggerAgeType() const;
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ void FileLogger::addLogMessage(const Log::Msg &msg)
|
|||||||
|
|
||||||
str << QDateTime::fromMSecsSinceEpoch(msg.timestamp).toString(Qt::ISODate) << " - " << msg.message << endl;
|
str << QDateTime::fromMSecsSinceEpoch(msg.timestamp).toString(Qt::ISODate) << " - " << msg.message << endl;
|
||||||
|
|
||||||
if (m_backup && (m_logFile->size() >= (m_maxSize * 1024 * 1024))) {
|
if (m_backup && (m_logFile->size() >= m_maxSize)) {
|
||||||
closeLogFile();
|
closeLogFile();
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
QString backupLogFilename = m_path + ".bak";
|
QString backupLogFilename = m_path + ".bak";
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ int main(int argc, char *argv[])
|
|||||||
// 3. https://bugreports.qt.io/browse/QTBUG-46015
|
// 3. https://bugreports.qt.io/browse/QTBUG-46015
|
||||||
|
|
||||||
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
|
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||||
|
// this is the default in Qt6
|
||||||
|
app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ else (GUI)
|
|||||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp)
|
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp)
|
||||||
endif (GUI)
|
endif (GUI)
|
||||||
|
|
||||||
add_library(qtsingleapplication ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES})
|
add_library(qtsingleapplication STATIC ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES})
|
||||||
target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}")
|
target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}")
|
||||||
target_link_qt_components(qtsingleapplication Network)
|
target_link_qt_components(qtsingleapplication Network)
|
||||||
|
|
||||||
|
|||||||
@@ -1,124 +1,124 @@
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/asyncfilestorage.h \
|
$$PWD/asyncfilestorage.h \
|
||||||
$$PWD/types.h \
|
$$PWD/bittorrent/addtorrentparams.h \
|
||||||
$$PWD/tristatebool.h \
|
$$PWD/bittorrent/cachestatus.h \
|
||||||
|
$$PWD/bittorrent/infohash.h \
|
||||||
|
$$PWD/bittorrent/magneturi.h \
|
||||||
|
$$PWD/bittorrent/peerinfo.h \
|
||||||
|
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
||||||
|
$$PWD/bittorrent/private/filterparserthread.h \
|
||||||
|
$$PWD/bittorrent/private/resumedatasavingmanager.h \
|
||||||
|
$$PWD/bittorrent/private/speedmonitor.h \
|
||||||
|
$$PWD/bittorrent/private/statistics.h \
|
||||||
|
$$PWD/bittorrent/session.h \
|
||||||
|
$$PWD/bittorrent/sessionstatus.h \
|
||||||
|
$$PWD/bittorrent/torrentcreatorthread.h \
|
||||||
|
$$PWD/bittorrent/torrenthandle.h \
|
||||||
|
$$PWD/bittorrent/torrentinfo.h \
|
||||||
|
$$PWD/bittorrent/tracker.h \
|
||||||
|
$$PWD/bittorrent/trackerentry.h \
|
||||||
$$PWD/filesystemwatcher.h \
|
$$PWD/filesystemwatcher.h \
|
||||||
$$PWD/logger.h \
|
$$PWD/global.h \
|
||||||
$$PWD/settingsstorage.h \
|
|
||||||
$$PWD/settingvalue.h \
|
|
||||||
$$PWD/preferences.h \
|
|
||||||
$$PWD/indexrange.h \
|
|
||||||
$$PWD/iconprovider.h \
|
|
||||||
$$PWD/http/irequesthandler.h \
|
|
||||||
$$PWD/http/connection.h \
|
$$PWD/http/connection.h \
|
||||||
|
$$PWD/http/irequesthandler.h \
|
||||||
$$PWD/http/requestparser.h \
|
$$PWD/http/requestparser.h \
|
||||||
|
$$PWD/http/responsebuilder.h \
|
||||||
$$PWD/http/responsegenerator.h \
|
$$PWD/http/responsegenerator.h \
|
||||||
$$PWD/http/server.h \
|
$$PWD/http/server.h \
|
||||||
$$PWD/http/types.h \
|
$$PWD/http/types.h \
|
||||||
$$PWD/http/responsebuilder.h \
|
$$PWD/iconprovider.h \
|
||||||
|
$$PWD/indexrange.h \
|
||||||
|
$$PWD/logger.h \
|
||||||
$$PWD/net/dnsupdater.h \
|
$$PWD/net/dnsupdater.h \
|
||||||
$$PWD/net/downloadmanager.h \
|
|
||||||
$$PWD/net/downloadhandler.h \
|
$$PWD/net/downloadhandler.h \
|
||||||
|
$$PWD/net/downloadmanager.h \
|
||||||
$$PWD/net/geoipmanager.h \
|
$$PWD/net/geoipmanager.h \
|
||||||
$$PWD/net/portforwarder.h \
|
$$PWD/net/portforwarder.h \
|
||||||
|
$$PWD/net/private/geoipdatabase.h \
|
||||||
$$PWD/net/proxyconfigurationmanager.h \
|
$$PWD/net/proxyconfigurationmanager.h \
|
||||||
$$PWD/net/reverseresolution.h \
|
$$PWD/net/reverseresolution.h \
|
||||||
$$PWD/net/smtp.h \
|
$$PWD/net/smtp.h \
|
||||||
$$PWD/net/private/geoipdatabase.h \
|
$$PWD/preferences.h \
|
||||||
$$PWD/bittorrent/addtorrentparams.h \
|
$$PWD/private/profile_p.h \
|
||||||
$$PWD/bittorrent/infohash.h \
|
$$PWD/profile.h \
|
||||||
$$PWD/bittorrent/session.h \
|
$$PWD/rss/private/rss_parser.h \
|
||||||
$$PWD/bittorrent/sessionstatus.h \
|
|
||||||
$$PWD/bittorrent/cachestatus.h \
|
|
||||||
$$PWD/bittorrent/magneturi.h \
|
|
||||||
$$PWD/bittorrent/torrentinfo.h \
|
|
||||||
$$PWD/bittorrent/torrenthandle.h \
|
|
||||||
$$PWD/bittorrent/peerinfo.h \
|
|
||||||
$$PWD/bittorrent/trackerentry.h \
|
|
||||||
$$PWD/bittorrent/tracker.h \
|
|
||||||
$$PWD/bittorrent/torrentcreatorthread.h \
|
|
||||||
$$PWD/bittorrent/private/speedmonitor.h \
|
|
||||||
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
|
||||||
$$PWD/bittorrent/private/filterparserthread.h \
|
|
||||||
$$PWD/bittorrent/private/statistics.h \
|
|
||||||
$$PWD/bittorrent/private/resumedatasavingmanager.h \
|
|
||||||
$$PWD/rss/rss_article.h \
|
$$PWD/rss/rss_article.h \
|
||||||
$$PWD/rss/rss_item.h \
|
|
||||||
$$PWD/rss/rss_feed.h \
|
|
||||||
$$PWD/rss/rss_folder.h \
|
|
||||||
$$PWD/rss/rss_session.h \
|
|
||||||
$$PWD/rss/rss_autodownloader.h \
|
$$PWD/rss/rss_autodownloader.h \
|
||||||
$$PWD/rss/rss_autodownloadrule.h \
|
$$PWD/rss/rss_autodownloadrule.h \
|
||||||
$$PWD/rss/private/rss_parser.h \
|
$$PWD/rss/rss_feed.h \
|
||||||
|
$$PWD/rss/rss_folder.h \
|
||||||
|
$$PWD/rss/rss_item.h \
|
||||||
|
$$PWD/rss/rss_session.h \
|
||||||
|
$$PWD/scanfoldersmodel.h \
|
||||||
|
$$PWD/searchengine.h \
|
||||||
|
$$PWD/settingsstorage.h \
|
||||||
|
$$PWD/settingvalue.h \
|
||||||
|
$$PWD/torrentfileguard.h \
|
||||||
|
$$PWD/torrentfilter.h \
|
||||||
|
$$PWD/tristatebool.h \
|
||||||
|
$$PWD/types.h \
|
||||||
|
$$PWD/unicodestrings.h \
|
||||||
$$PWD/utils/fs.h \
|
$$PWD/utils/fs.h \
|
||||||
$$PWD/utils/gzip.h \
|
$$PWD/utils/gzip.h \
|
||||||
$$PWD/utils/misc.h \
|
$$PWD/utils/misc.h \
|
||||||
$$PWD/utils/net.h \
|
$$PWD/utils/net.h \
|
||||||
$$PWD/utils/random.h \
|
$$PWD/utils/random.h \
|
||||||
$$PWD/utils/string.h \
|
$$PWD/utils/string.h \
|
||||||
$$PWD/utils/version.h \
|
$$PWD/utils/version.h
|
||||||
$$PWD/profile.h \
|
|
||||||
$$PWD/private/profile_p.h \
|
|
||||||
$$PWD/unicodestrings.h \
|
|
||||||
$$PWD/torrentfileguard.h \
|
|
||||||
$$PWD/torrentfilter.h \
|
|
||||||
$$PWD/scanfoldersmodel.h \
|
|
||||||
$$PWD/searchengine.h \
|
|
||||||
$$PWD/global.h
|
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/asyncfilestorage.cpp \
|
$$PWD/asyncfilestorage.cpp \
|
||||||
$$PWD/tristatebool.cpp \
|
$$PWD/bittorrent/infohash.cpp \
|
||||||
|
$$PWD/bittorrent/magneturi.cpp \
|
||||||
|
$$PWD/bittorrent/peerinfo.cpp \
|
||||||
|
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
||||||
|
$$PWD/bittorrent/private/filterparserthread.cpp \
|
||||||
|
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
|
||||||
|
$$PWD/bittorrent/private/speedmonitor.cpp \
|
||||||
|
$$PWD/bittorrent/private/statistics.cpp \
|
||||||
|
$$PWD/bittorrent/session.cpp \
|
||||||
|
$$PWD/bittorrent/torrentcreatorthread.cpp \
|
||||||
|
$$PWD/bittorrent/torrenthandle.cpp \
|
||||||
|
$$PWD/bittorrent/torrentinfo.cpp \
|
||||||
|
$$PWD/bittorrent/tracker.cpp \
|
||||||
|
$$PWD/bittorrent/trackerentry.cpp \
|
||||||
$$PWD/filesystemwatcher.cpp \
|
$$PWD/filesystemwatcher.cpp \
|
||||||
$$PWD/logger.cpp \
|
|
||||||
$$PWD/settingsstorage.cpp \
|
|
||||||
$$PWD/preferences.cpp \
|
|
||||||
$$PWD/iconprovider.cpp \
|
|
||||||
$$PWD/http/connection.cpp \
|
$$PWD/http/connection.cpp \
|
||||||
$$PWD/http/requestparser.cpp \
|
$$PWD/http/requestparser.cpp \
|
||||||
|
$$PWD/http/responsebuilder.cpp \
|
||||||
$$PWD/http/responsegenerator.cpp \
|
$$PWD/http/responsegenerator.cpp \
|
||||||
$$PWD/http/server.cpp \
|
$$PWD/http/server.cpp \
|
||||||
$$PWD/http/responsebuilder.cpp \
|
$$PWD/iconprovider.cpp \
|
||||||
|
$$PWD/logger.cpp \
|
||||||
$$PWD/net/dnsupdater.cpp \
|
$$PWD/net/dnsupdater.cpp \
|
||||||
$$PWD/net/downloadmanager.cpp \
|
|
||||||
$$PWD/net/downloadhandler.cpp \
|
$$PWD/net/downloadhandler.cpp \
|
||||||
|
$$PWD/net/downloadmanager.cpp \
|
||||||
$$PWD/net/geoipmanager.cpp \
|
$$PWD/net/geoipmanager.cpp \
|
||||||
$$PWD/net/portforwarder.cpp \
|
$$PWD/net/portforwarder.cpp \
|
||||||
|
$$PWD/net/private/geoipdatabase.cpp \
|
||||||
$$PWD/net/proxyconfigurationmanager.cpp \
|
$$PWD/net/proxyconfigurationmanager.cpp \
|
||||||
$$PWD/net/reverseresolution.cpp \
|
$$PWD/net/reverseresolution.cpp \
|
||||||
$$PWD/net/smtp.cpp \
|
$$PWD/net/smtp.cpp \
|
||||||
$$PWD/net/private/geoipdatabase.cpp \
|
$$PWD/preferences.cpp \
|
||||||
$$PWD/bittorrent/infohash.cpp \
|
$$PWD/private/profile_p.cpp \
|
||||||
$$PWD/bittorrent/session.cpp \
|
$$PWD/profile.cpp \
|
||||||
$$PWD/bittorrent/magneturi.cpp \
|
$$PWD/rss/private/rss_parser.cpp \
|
||||||
$$PWD/bittorrent/torrentinfo.cpp \
|
|
||||||
$$PWD/bittorrent/torrenthandle.cpp \
|
|
||||||
$$PWD/bittorrent/peerinfo.cpp \
|
|
||||||
$$PWD/bittorrent/trackerentry.cpp \
|
|
||||||
$$PWD/bittorrent/tracker.cpp \
|
|
||||||
$$PWD/bittorrent/torrentcreatorthread.cpp \
|
|
||||||
$$PWD/bittorrent/private/speedmonitor.cpp \
|
|
||||||
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
|
||||||
$$PWD/bittorrent/private/filterparserthread.cpp \
|
|
||||||
$$PWD/bittorrent/private/statistics.cpp \
|
|
||||||
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
|
|
||||||
$$PWD/rss/rss_article.cpp \
|
$$PWD/rss/rss_article.cpp \
|
||||||
$$PWD/rss/rss_item.cpp \
|
|
||||||
$$PWD/rss/rss_feed.cpp \
|
|
||||||
$$PWD/rss/rss_folder.cpp \
|
|
||||||
$$PWD/rss/rss_session.cpp \
|
|
||||||
$$PWD/rss/rss_autodownloader.cpp \
|
$$PWD/rss/rss_autodownloader.cpp \
|
||||||
$$PWD/rss/rss_autodownloadrule.cpp \
|
$$PWD/rss/rss_autodownloadrule.cpp \
|
||||||
$$PWD/rss/private/rss_parser.cpp \
|
$$PWD/rss/rss_feed.cpp \
|
||||||
|
$$PWD/rss/rss_folder.cpp \
|
||||||
|
$$PWD/rss/rss_item.cpp \
|
||||||
|
$$PWD/rss/rss_session.cpp \
|
||||||
|
$$PWD/scanfoldersmodel.cpp \
|
||||||
|
$$PWD/searchengine.cpp \
|
||||||
|
$$PWD/settingsstorage.cpp \
|
||||||
|
$$PWD/torrentfileguard.cpp \
|
||||||
|
$$PWD/torrentfilter.cpp \
|
||||||
|
$$PWD/tristatebool.cpp \
|
||||||
$$PWD/utils/fs.cpp \
|
$$PWD/utils/fs.cpp \
|
||||||
$$PWD/utils/gzip.cpp \
|
$$PWD/utils/gzip.cpp \
|
||||||
$$PWD/utils/misc.cpp \
|
$$PWD/utils/misc.cpp \
|
||||||
$$PWD/utils/net.cpp \
|
$$PWD/utils/net.cpp \
|
||||||
$$PWD/utils/random.cpp \
|
$$PWD/utils/random.cpp \
|
||||||
$$PWD/utils/string.cpp \
|
$$PWD/utils/string.cpp
|
||||||
$$PWD/profile.cpp \
|
|
||||||
$$PWD/private/profile_p.cpp \
|
|
||||||
$$PWD/torrentfileguard.cpp \
|
|
||||||
$$PWD/torrentfilter.cpp \
|
|
||||||
$$PWD/scanfoldersmodel.cpp \
|
|
||||||
$$PWD/searchengine.cpp
|
|
||||||
|
|||||||
@@ -273,18 +273,20 @@ qreal PeerInfo::relevance() const
|
|||||||
|
|
||||||
void PeerInfo::determineFlags()
|
void PeerInfo::determineFlags()
|
||||||
{
|
{
|
||||||
|
QStringList flagsDescriptionList;
|
||||||
|
|
||||||
if (isInteresting()) {
|
if (isInteresting()) {
|
||||||
// d = Your client wants to download, but peer doesn't want to send (interested and choked)
|
// d = Your client wants to download, but peer doesn't want to send (interested and choked)
|
||||||
if (isRemoteChocked()) {
|
if (isRemoteChocked()) {
|
||||||
m_flags += "d ";
|
m_flags += "d ";
|
||||||
m_flagsDescription += tr("interested(local) and choked(peer)");
|
flagsDescriptionList += "d = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("Interested(local) and Choked(peer)");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// D = Currently downloading (interested and not choked)
|
// D = Currently downloading (interested and not choked)
|
||||||
m_flags += "D ";
|
m_flags += "D ";
|
||||||
m_flagsDescription += tr("interested(local) and unchoked(peer)");
|
flagsDescriptionList += "D = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("interested(local) and unchoked(peer)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,97 +294,95 @@ void PeerInfo::determineFlags()
|
|||||||
// u = Peer wants your client to upload, but your client doesn't want to (interested and choked)
|
// u = Peer wants your client to upload, but your client doesn't want to (interested and choked)
|
||||||
if (isChocked()) {
|
if (isChocked()) {
|
||||||
m_flags += "u ";
|
m_flags += "u ";
|
||||||
m_flagsDescription += tr("interested(peer) and choked(local)");
|
flagsDescriptionList += "u = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("interested(peer) and choked(local)");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// U = Currently uploading (interested and not choked)
|
// U = Currently uploading (interested and not choked)
|
||||||
m_flags += "U ";
|
m_flags += "U ";
|
||||||
m_flagsDescription += tr("interested(peer) and unchoked(local)");
|
flagsDescriptionList += "U = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("interested(peer) and unchoked(local)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// O = Optimistic unchoke
|
// O = Optimistic unchoke
|
||||||
if (optimisticUnchoke()) {
|
if (optimisticUnchoke()) {
|
||||||
m_flags += "O ";
|
m_flags += "O ";
|
||||||
m_flagsDescription += tr("optimistic unchoke");
|
flagsDescriptionList += "O = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("optimistic unchoke");
|
||||||
}
|
}
|
||||||
|
|
||||||
// S = Peer is snubbed
|
// S = Peer is snubbed
|
||||||
if (isSnubbed()) {
|
if (isSnubbed()) {
|
||||||
m_flags += "S ";
|
m_flags += "S ";
|
||||||
m_flagsDescription += tr("peer snubbed");
|
flagsDescriptionList += "S = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("peer snubbed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// I = Peer is an incoming connection
|
// I = Peer is an incoming connection
|
||||||
if (!isLocalConnection()) {
|
if (!isLocalConnection()) {
|
||||||
m_flags += "I ";
|
m_flags += "I ";
|
||||||
m_flagsDescription += tr("incoming connection");
|
flagsDescriptionList += "I = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("incoming connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
// K = Peer is unchoking your client, but your client is not interested
|
// K = Peer is unchoking your client, but your client is not interested
|
||||||
if (!isRemoteChocked() && !isInteresting()) {
|
if (!isRemoteChocked() && !isInteresting()) {
|
||||||
m_flags += "K ";
|
m_flags += "K ";
|
||||||
m_flagsDescription += tr("not interested(local) and unchoked(peer)");
|
flagsDescriptionList += "K = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("not interested(local) and unchoked(peer)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ? = Your client unchoked the peer but the peer is not interested
|
// ? = Your client unchoked the peer but the peer is not interested
|
||||||
if (!isChocked() && !isRemoteInterested()) {
|
if (!isChocked() && !isRemoteInterested()) {
|
||||||
m_flags += "? ";
|
m_flags += "? ";
|
||||||
m_flagsDescription += tr("not interested(peer) and unchoked(local)");
|
flagsDescriptionList += "? = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("not interested(peer) and unchoked(local)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// X = Peer was included in peerlists obtained through Peer Exchange (PEX)
|
// X = Peer was included in peerlists obtained through Peer Exchange (PEX)
|
||||||
if (fromPeX()) {
|
if (fromPeX()) {
|
||||||
m_flags += "X ";
|
m_flags += "X ";
|
||||||
m_flagsDescription += tr("peer from PEX");
|
flagsDescriptionList += "X = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("peer from PEX");
|
||||||
}
|
}
|
||||||
|
|
||||||
// H = Peer was obtained through DHT
|
// H = Peer was obtained through DHT
|
||||||
if (fromDHT()) {
|
if (fromDHT()) {
|
||||||
m_flags += "H ";
|
m_flags += "H ";
|
||||||
m_flagsDescription += tr("peer from DHT");
|
flagsDescriptionList += "H = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("peer from DHT");
|
||||||
}
|
}
|
||||||
|
|
||||||
// E = Peer is using Protocol Encryption (all traffic)
|
// E = Peer is using Protocol Encryption (all traffic)
|
||||||
if (isRC4Encrypted()) {
|
if (isRC4Encrypted()) {
|
||||||
m_flags += "E ";
|
m_flags += "E ";
|
||||||
m_flagsDescription += tr("encrypted traffic");
|
flagsDescriptionList += "E = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("encrypted traffic");
|
||||||
}
|
}
|
||||||
|
|
||||||
// e = Peer is using Protocol Encryption (handshake)
|
// e = Peer is using Protocol Encryption (handshake)
|
||||||
if (isPlaintextEncrypted()) {
|
if (isPlaintextEncrypted()) {
|
||||||
m_flags += "e ";
|
m_flags += "e ";
|
||||||
m_flagsDescription += tr("encrypted handshake");
|
flagsDescriptionList += "e = "
|
||||||
m_flagsDescription += ", ";
|
+ tr("encrypted handshake");
|
||||||
}
|
}
|
||||||
|
|
||||||
// P = Peer is using uTorrent uTP
|
// P = Peer is using uTorrent uTP
|
||||||
if (useUTPSocket()) {
|
if (useUTPSocket()) {
|
||||||
m_flags += "P ";
|
m_flags += "P ";
|
||||||
m_flagsDescription += QString::fromUtf8(C_UTP);
|
flagsDescriptionList += "P = "
|
||||||
m_flagsDescription += ", ";
|
+ QString::fromUtf8(C_UTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// L = Peer is local
|
// L = Peer is local
|
||||||
if (fromLSD()) {
|
if (fromLSD()) {
|
||||||
m_flags += "L";
|
m_flags += "L";
|
||||||
m_flagsDescription += tr("peer from LSD");
|
flagsDescriptionList += "L = "
|
||||||
|
+ tr("peer from LSD");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_flags = m_flags.trimmed();
|
m_flags = m_flags.trimmed();
|
||||||
m_flagsDescription = m_flagsDescription.trimmed();
|
m_flagsDescription = flagsDescriptionList.join('\n');
|
||||||
if (m_flagsDescription.endsWith(',', Qt::CaseInsensitive))
|
|
||||||
m_flagsDescription.chop(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PeerInfo::flags() const
|
QString PeerInfo::flags() const
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int BUFFER_SIZE = 2 * 1024 * 1024; // 2 MiB
|
const int BUFFER_SIZE = 2 * 1024 * 1024; // 2 MiB
|
||||||
|
const int MAX_LOGGED_ERRORS = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterParserThread::FilterParserThread(QObject *parent)
|
FilterParserThread::FilterParserThread(QObject *parent)
|
||||||
@@ -134,6 +135,12 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
int start = 0;
|
int start = 0;
|
||||||
int endOfLine = -1;
|
int endOfLine = -1;
|
||||||
int nbLine = 0;
|
int nbLine = 0;
|
||||||
|
int parseErrorCount = 0;
|
||||||
|
const auto addLog = [&parseErrorCount](const QString &msg)
|
||||||
|
{
|
||||||
|
if (parseErrorCount <= MAX_LOGGED_ERRORS)
|
||||||
|
LogMsg(msg, Log::CRITICAL);
|
||||||
|
};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
bytesRead = file.read(buffer.data() + offset, BUFFER_SIZE - offset - 1);
|
bytesRead = file.read(buffer.data() + offset, BUFFER_SIZE - offset - 1);
|
||||||
@@ -202,7 +209,8 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
int endOfIPRange = ((firstComma == -1) ? (endOfLine - 1) : (firstComma - 1));
|
int endOfIPRange = ((firstComma == -1) ? (endOfLine - 1) : (firstComma - 1));
|
||||||
int delimIP = findAndNullDelimiter(buffer.data(), '-', start, endOfIPRange);
|
int delimIP = findAndNullDelimiter(buffer.data(), '-', start, endOfIPRange);
|
||||||
if (delimIP == -1) {
|
if (delimIP == -1) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -210,7 +218,8 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
libt::address startAddr;
|
libt::address startAddr;
|
||||||
int newStart = trim(buffer.data(), start, delimIP - 1);
|
int newStart = trim(buffer.data(), start, delimIP - 1);
|
||||||
if (!parseIPAddress(buffer.data() + newStart, startAddr)) {
|
if (!parseIPAddress(buffer.data() + newStart, startAddr)) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed. Start IP of the range is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed. Start IP of the range is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -218,14 +227,16 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
libt::address endAddr;
|
libt::address endAddr;
|
||||||
newStart = trim(buffer.data(), delimIP + 1, endOfIPRange);
|
newStart = trim(buffer.data(), delimIP + 1, endOfIPRange);
|
||||||
if (!parseIPAddress(buffer.data() + newStart, endAddr)) {
|
if (!parseIPAddress(buffer.data() + newStart, endAddr)) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed. End IP of the range is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed. End IP of the range is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((startAddr.is_v4() != endAddr.is_v4())
|
if ((startAddr.is_v4() != endAddr.is_v4())
|
||||||
|| (startAddr.is_v6() != endAddr.is_v6())) {
|
|| (startAddr.is_v6() != endAddr.is_v6())) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed. One IP is IPv4 and the other is IPv6!").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed. One IP is IPv4 and the other is IPv6!").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -238,8 +249,9 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
++ruleCount;
|
++ruleCount;
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (std::exception &e) {
|
||||||
LogMsg(tr("IP filter exception thrown for line %1. Exception is: %2").arg(nbLine)
|
++parseErrorCount;
|
||||||
.arg(QString::fromLocal8Bit(e.what())), Log::CRITICAL);
|
addLog(tr("IP filter exception thrown for line %1. Exception is: %2")
|
||||||
|
.arg(nbLine).arg(QString::fromLocal8Bit(e.what())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +259,9 @@ int FilterParserThread::parseDATFilterFile()
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parseErrorCount > MAX_LOGGED_ERRORS)
|
||||||
|
LogMsg(tr("%1 extra IP filter parsing errors occurred.", "513 extra IP filter parsing errors occurred.")
|
||||||
|
.arg(parseErrorCount - MAX_LOGGED_ERRORS), Log::CRITICAL);
|
||||||
return ruleCount;
|
return ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +283,12 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
int start = 0;
|
int start = 0;
|
||||||
int endOfLine = -1;
|
int endOfLine = -1;
|
||||||
int nbLine = 0;
|
int nbLine = 0;
|
||||||
|
int parseErrorCount = 0;
|
||||||
|
const auto addLog = [&parseErrorCount](const QString &msg)
|
||||||
|
{
|
||||||
|
if (parseErrorCount <= MAX_LOGGED_ERRORS)
|
||||||
|
LogMsg(msg, Log::CRITICAL);
|
||||||
|
};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
bytesRead = file.read(buffer.data() + offset, BUFFER_SIZE - offset - 1);
|
bytesRead = file.read(buffer.data() + offset, BUFFER_SIZE - offset - 1);
|
||||||
@@ -319,7 +340,8 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
// The "Some organization" part might contain a ':' char itself so we find the last occurrence
|
// The "Some organization" part might contain a ':' char itself so we find the last occurrence
|
||||||
int partsDelimiter = findAndNullDelimiter(buffer.data(), ':', start, endOfLine, true);
|
int partsDelimiter = findAndNullDelimiter(buffer.data(), ':', start, endOfLine, true);
|
||||||
if (partsDelimiter == -1) {
|
if (partsDelimiter == -1) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -327,7 +349,8 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
// IP Range should be split by a dash
|
// IP Range should be split by a dash
|
||||||
int delimIP = findAndNullDelimiter(buffer.data(), '-', partsDelimiter + 1, endOfLine);
|
int delimIP = findAndNullDelimiter(buffer.data(), '-', partsDelimiter + 1, endOfLine);
|
||||||
if (delimIP == -1) {
|
if (delimIP == -1) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -335,7 +358,8 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
libt::address startAddr;
|
libt::address startAddr;
|
||||||
int newStart = trim(buffer.data(), partsDelimiter + 1, delimIP - 1);
|
int newStart = trim(buffer.data(), partsDelimiter + 1, delimIP - 1);
|
||||||
if (!parseIPAddress(buffer.data() + newStart, startAddr)) {
|
if (!parseIPAddress(buffer.data() + newStart, startAddr)) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed. Start IP of the range is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed. Start IP of the range is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -343,14 +367,16 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
libt::address endAddr;
|
libt::address endAddr;
|
||||||
newStart = trim(buffer.data(), delimIP + 1, endOfLine);
|
newStart = trim(buffer.data(), delimIP + 1, endOfLine);
|
||||||
if (!parseIPAddress(buffer.data() + newStart, endAddr)) {
|
if (!parseIPAddress(buffer.data() + newStart, endAddr)) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed. End IP of the range is malformed.").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed. End IP of the range is malformed.").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((startAddr.is_v4() != endAddr.is_v4())
|
if ((startAddr.is_v4() != endAddr.is_v4())
|
||||||
|| (startAddr.is_v6() != endAddr.is_v6())) {
|
|| (startAddr.is_v6() != endAddr.is_v6())) {
|
||||||
LogMsg(tr("IP filter line %1 is malformed. One IP is IPv4 and the other is IPv6!").arg(nbLine), Log::CRITICAL);
|
++parseErrorCount;
|
||||||
|
addLog(tr("IP filter line %1 is malformed. One IP is IPv4 and the other is IPv6!").arg(nbLine));
|
||||||
start = endOfLine;
|
start = endOfLine;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -362,8 +388,9 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
++ruleCount;
|
++ruleCount;
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (std::exception &e) {
|
||||||
LogMsg(tr("IP filter exception thrown for line %1. Exception is: %2").arg(nbLine)
|
++parseErrorCount;
|
||||||
.arg(QString::fromLocal8Bit(e.what())), Log::CRITICAL);
|
addLog(tr("IP filter exception thrown for line %1. Exception is: %2")
|
||||||
|
.arg(nbLine).arg(QString::fromLocal8Bit(e.what())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,6 +398,9 @@ int FilterParserThread::parseP2PFilterFile()
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parseErrorCount > MAX_LOGGED_ERRORS)
|
||||||
|
LogMsg(tr("%1 extra IP filter parsing errors occurred.", "513 extra IP filter parsing errors occurred.")
|
||||||
|
.arg(parseErrorCount - MAX_LOGGED_ERRORS), Log::CRITICAL);
|
||||||
return ruleCount;
|
return ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ Session::Session(QObject *parent)
|
|||||||
, m_btProtocol(BITTORRENT_SESSION_KEY("BTProtocol"), BTProtocol::Both
|
, m_btProtocol(BITTORRENT_SESSION_KEY("BTProtocol"), BTProtocol::Both
|
||||||
, clampValue(BTProtocol::Both, BTProtocol::UTP))
|
, clampValue(BTProtocol::Both, BTProtocol::UTP))
|
||||||
, m_isUTPRateLimited(BITTORRENT_SESSION_KEY("uTPRateLimited"), true)
|
, m_isUTPRateLimited(BITTORRENT_SESSION_KEY("uTPRateLimited"), true)
|
||||||
, m_utpMixedMode(BITTORRENT_SESSION_KEY("uTPMixedMode"), MixedModeAlgorithm::Proportional
|
, m_utpMixedMode(BITTORRENT_SESSION_KEY("uTPMixedMode"), MixedModeAlgorithm::TCP
|
||||||
, clampValue(MixedModeAlgorithm::TCP, MixedModeAlgorithm::Proportional))
|
, clampValue(MixedModeAlgorithm::TCP, MixedModeAlgorithm::Proportional))
|
||||||
, m_multiConnectionsPerIpEnabled(BITTORRENT_SESSION_KEY("MultiConnectionsPerIp"), false)
|
, m_multiConnectionsPerIpEnabled(BITTORRENT_SESSION_KEY("MultiConnectionsPerIp"), false)
|
||||||
, m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false)
|
, m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false)
|
||||||
@@ -1418,8 +1418,11 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
|
|||||||
void Session::configurePeerClasses()
|
void Session::configurePeerClasses()
|
||||||
{
|
{
|
||||||
libt::ip_filter f;
|
libt::ip_filter f;
|
||||||
f.add_rule(libt::address_v4::from_string("0.0.0.0")
|
// address_v4::from_string("255.255.255.255") crashes on some people's systems
|
||||||
, libt::address_v4::from_string("255.255.255.255")
|
// so instead we use address_v4::broadcast()
|
||||||
|
// Proactively do the same for 0.0.0.0 and address_v4::any()
|
||||||
|
f.add_rule(libt::address_v4::any()
|
||||||
|
, libt::address_v4::broadcast()
|
||||||
, 1 << libt::session::global_peer_class_id);
|
, 1 << libt::session::global_peer_class_id);
|
||||||
#if TORRENT_USE_IPV6
|
#if TORRENT_USE_IPV6
|
||||||
// IPv6 may not be available on OS and the parsing
|
// IPv6 may not be available on OS and the parsing
|
||||||
@@ -1478,14 +1481,10 @@ void Session::configurePeerClasses()
|
|||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::tcp_socket, libt::session::tcp_peer_class_id);
|
peerClassTypeFilter.add(libt::peer_class_type_filter::tcp_socket, libt::session::tcp_peer_class_id);
|
||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_tcp_socket, libt::session::tcp_peer_class_id);
|
peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_tcp_socket, libt::session::tcp_peer_class_id);
|
||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::i2p_socket, libt::session::tcp_peer_class_id);
|
peerClassTypeFilter.add(libt::peer_class_type_filter::i2p_socket, libt::session::tcp_peer_class_id);
|
||||||
if (isUTPRateLimited()) {
|
if (!isUTPRateLimited()) {
|
||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::utp_socket
|
peerClassTypeFilter.disallow(libt::peer_class_type_filter::utp_socket
|
||||||
, libt::session::local_peer_class_id);
|
|
||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::utp_socket
|
|
||||||
, libt::session::global_peer_class_id);
|
, libt::session::global_peer_class_id);
|
||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_utp_socket
|
peerClassTypeFilter.disallow(libt::peer_class_type_filter::ssl_utp_socket
|
||||||
, libt::session::local_peer_class_id);
|
|
||||||
peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_utp_socket
|
|
||||||
, libt::session::global_peer_class_id);
|
, libt::session::global_peer_class_id);
|
||||||
}
|
}
|
||||||
m_nativeSession->set_peer_class_type_filter(peerClassTypeFilter);
|
m_nativeSession->set_peer_class_type_filter(peerClassTypeFilter);
|
||||||
|
|||||||
@@ -35,8 +35,8 @@
|
|||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
#include <libtorrent/create_torrent.hpp>
|
#include <libtorrent/create_torrent.hpp>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
|
||||||
#include <libtorrent/storage.hpp>
|
#include <libtorrent/storage.hpp>
|
||||||
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
@@ -44,120 +44,115 @@
|
|||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// do not include files and folders whose
|
||||||
|
// name starts with a .
|
||||||
|
bool fileFilter(const std::string &f)
|
||||||
|
{
|
||||||
|
return !Utils::Fs::fileName(QString::fromStdString(f)).startsWith('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace libt = libtorrent;
|
namespace libt = libtorrent;
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
|
|
||||||
// do not include files and folders whose
|
|
||||||
// name starts with a .
|
|
||||||
bool fileFilter(const std::string &f)
|
|
||||||
{
|
|
||||||
return !Utils::Fs::fileName(QString::fromStdString(f)).startsWith('.');
|
|
||||||
}
|
|
||||||
|
|
||||||
TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
|
TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
|
||||||
: QThread(parent)
|
: QThread(parent)
|
||||||
, m_private(false)
|
|
||||||
, m_pieceSize(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentCreatorThread::~TorrentCreatorThread()
|
TorrentCreatorThread::~TorrentCreatorThread()
|
||||||
{
|
{
|
||||||
requestInterruption();
|
requestInterruption();
|
||||||
wait(1000);
|
wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorThread::create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
|
void TorrentCreatorThread::create(const TorrentCreatorParams ¶ms)
|
||||||
const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize)
|
|
||||||
{
|
{
|
||||||
m_inputPath = Utils::Fs::fromNativePath(inputPath);
|
m_params = params;
|
||||||
m_savePath = Utils::Fs::fromNativePath(savePath);
|
|
||||||
if (QFile(m_savePath).exists())
|
|
||||||
Utils::Fs::forceRemove(m_savePath);
|
|
||||||
m_trackers = trackers;
|
|
||||||
m_urlSeeds = urlSeeds;
|
|
||||||
m_comment = comment;
|
|
||||||
m_private = isPrivate;
|
|
||||||
m_pieceSize = pieceSize;
|
|
||||||
|
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces)
|
void TorrentCreatorThread::sendProgressSignal(int currentPieceIdx, int totalPieces)
|
||||||
{
|
{
|
||||||
emit updateProgress(static_cast<int>((numHashes * 100.) / numPieces));
|
emit updateProgress(static_cast<int>((currentPieceIdx * 100.) / totalPieces));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorThread::run()
|
void TorrentCreatorThread::run()
|
||||||
{
|
{
|
||||||
|
const QString creatorStr("qBittorrent " QBT_VERSION);
|
||||||
|
|
||||||
emit updateProgress(0);
|
emit updateProgress(0);
|
||||||
|
|
||||||
QString creator_str("qBittorrent " QBT_VERSION);
|
|
||||||
try {
|
try {
|
||||||
libt::file_storage fs;
|
libt::file_storage fs;
|
||||||
// Adding files to the torrent
|
// Adding files to the torrent
|
||||||
libt::add_files(fs, Utils::Fs::toNativePath(m_inputPath).toStdString(), fileFilter);
|
libt::add_files(fs, Utils::Fs::toNativePath(m_params.inputPath).toStdString(), fileFilter);
|
||||||
|
|
||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
libt::create_torrent t(fs, m_pieceSize);
|
libt::create_torrent newTorrent(fs, m_params.pieceSize);
|
||||||
|
|
||||||
// Add url seeds
|
// Add url seeds
|
||||||
foreach (const QString &seed, m_urlSeeds)
|
foreach (QString seed, m_params.urlSeeds) {
|
||||||
t.add_url_seed(seed.trimmed().toStdString());
|
seed = seed.trimmed();
|
||||||
|
if (!seed.isEmpty())
|
||||||
|
newTorrent.add_url_seed(seed.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
int tier = 0;
|
int tier = 0;
|
||||||
bool newline = false;
|
foreach (const QString &tracker, m_params.trackers) {
|
||||||
foreach (const QString &tracker, m_trackers) {
|
if (tracker.isEmpty())
|
||||||
if (tracker.isEmpty()) {
|
|
||||||
if (newline)
|
|
||||||
continue;
|
|
||||||
++tier;
|
++tier;
|
||||||
newline = true;
|
else
|
||||||
continue;
|
newTorrent.add_tracker(tracker.trimmed().toStdString(), tier);
|
||||||
}
|
|
||||||
t.add_tracker(tracker.trimmed().toStdString(), tier);
|
|
||||||
newline = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
// calculate the hash for all pieces
|
// calculate the hash for all pieces
|
||||||
const QString parentPath = Utils::Fs::branchPath(m_inputPath) + "/";
|
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + "/";
|
||||||
libt::set_piece_hashes(t, Utils::Fs::toNativePath(parentPath).toStdString(), boost::bind(&TorrentCreatorThread::sendProgressSignal, this, _1, t.num_pieces()));
|
libt::set_piece_hashes(newTorrent, Utils::Fs::toNativePath(parentPath).toStdString()
|
||||||
|
, [this, &newTorrent](const int n) { sendProgressSignal(n, newTorrent.num_pieces()); });
|
||||||
// Set qBittorrent as creator and add user comment to
|
// Set qBittorrent as creator and add user comment to
|
||||||
// torrent_info structure
|
// torrent_info structure
|
||||||
t.set_creator(creator_str.toUtf8().constData());
|
newTorrent.set_creator(creatorStr.toUtf8().constData());
|
||||||
t.set_comment(m_comment.toUtf8().constData());
|
newTorrent.set_comment(m_params.comment.toUtf8().constData());
|
||||||
// Is private ?
|
// Is private ?
|
||||||
t.set_priv(m_private);
|
newTorrent.set_priv(m_params.isPrivate);
|
||||||
|
|
||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
// create the torrent and print it to out
|
libt::entry entry = newTorrent.generate();
|
||||||
qDebug("Saving to %s", qUtf8Printable(m_savePath));
|
|
||||||
|
// add source field
|
||||||
|
if (!m_params.source.isEmpty())
|
||||||
|
entry["info"]["source"] = m_params.source.toStdString();
|
||||||
|
|
||||||
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
|
// create the torrent
|
||||||
|
std::ofstream outfile(
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
wchar_t *savePathW = new wchar_t[m_savePath.length() + 1];
|
Utils::Fs::toNativePath(m_params.savePath).toStdWString().c_str()
|
||||||
int len = Utils::Fs::toNativePath(m_savePath).toWCharArray(savePathW);
|
|
||||||
savePathW[len] = L'\0';
|
|
||||||
std::ofstream outfile(savePathW, std::ios_base::out | std::ios_base::binary);
|
|
||||||
delete[] savePathW;
|
|
||||||
#else
|
#else
|
||||||
std::ofstream outfile(Utils::Fs::toNativePath(m_savePath).toLocal8Bit().constData(), std::ios_base::out | std::ios_base::binary);
|
Utils::Fs::toNativePath(m_params.savePath).toUtf8().constData()
|
||||||
#endif
|
#endif
|
||||||
|
, (std::ios_base::out | std::ios_base::binary | std::ios_base::trunc));
|
||||||
if (outfile.fail())
|
if (outfile.fail())
|
||||||
throw std::exception();
|
throw std::runtime_error(tr("create new torrent file failed").toStdString());
|
||||||
|
|
||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
libt::bencode(std::ostream_iterator<char>(outfile), t.generate());
|
libt::bencode(std::ostream_iterator<char>(outfile), entry);
|
||||||
outfile.close();
|
outfile.close();
|
||||||
|
|
||||||
emit updateProgress(100);
|
emit updateProgress(100);
|
||||||
emit creationSuccess(m_savePath, parentPath);
|
emit creationSuccess(m_params.savePath, parentPath);
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (const std::exception &e) {
|
||||||
emit creationFailure(QString::fromStdString(e.what()));
|
emit creationFailure(e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,16 +36,27 @@
|
|||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
|
struct TorrentCreatorParams
|
||||||
|
{
|
||||||
|
bool isPrivate;
|
||||||
|
int pieceSize;
|
||||||
|
QString inputPath;
|
||||||
|
QString savePath;
|
||||||
|
QString comment;
|
||||||
|
QString source;
|
||||||
|
QStringList trackers;
|
||||||
|
QStringList urlSeeds;
|
||||||
|
};
|
||||||
|
|
||||||
class TorrentCreatorThread : public QThread
|
class TorrentCreatorThread : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TorrentCreatorThread(QObject *parent = 0);
|
TorrentCreatorThread(QObject *parent = nullptr);
|
||||||
~TorrentCreatorThread();
|
~TorrentCreatorThread();
|
||||||
|
|
||||||
void create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
|
void create(const TorrentCreatorParams ¶ms);
|
||||||
const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize);
|
|
||||||
|
|
||||||
static int calculateTotalPieces(const QString &inputPath, const int pieceSize);
|
static int calculateTotalPieces(const QString &inputPath, const int pieceSize);
|
||||||
|
|
||||||
@@ -58,15 +69,9 @@ namespace BitTorrent
|
|||||||
void updateProgress(int progress);
|
void updateProgress(int progress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendProgressSignal(int numHashes, int numPieces);
|
void sendProgressSignal(int currentPieceIdx, int totalPieces);
|
||||||
|
|
||||||
QString m_inputPath;
|
TorrentCreatorParams m_params;
|
||||||
QString m_savePath;
|
|
||||||
QStringList m_trackers;
|
|
||||||
QStringList m_urlSeeds;
|
|
||||||
QString m_comment;
|
|
||||||
bool m_private;
|
|
||||||
int m_pieceSize;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,8 @@ const int TorrentHandle::MAX_SEEDING_TIME = 525600;
|
|||||||
// The following can be removed after one or two libtorrent releases on each branch.
|
// The following can be removed after one or two libtorrent releases on each branch.
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const char i18nContext[] = "TorrentHandle";
|
||||||
|
|
||||||
// new constructor is available
|
// new constructor is available
|
||||||
template<typename T, typename std::enable_if<std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<std::is_constructible<T, libt::torrent_info, bool>::value, int>::type = 0>
|
||||||
T makeTorrentCreator(const libtorrent::torrent_info & ti)
|
T makeTorrentCreator(const libtorrent::torrent_info & ti)
|
||||||
@@ -1469,7 +1471,7 @@ void TorrentHandle::handleStorageMovedFailedAlert(libtorrent::storage_moved_fail
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::instance()->addMessage(tr("Could not move torrent: '%1'. Reason: %2")
|
LogMsg(QCoreApplication::translate(i18nContext, "Could not move torrent: '%1'. Reason: %2")
|
||||||
.arg(name()).arg(QString::fromStdString(p->message())), Log::CRITICAL);
|
.arg(name()).arg(QString::fromStdString(p->message())), Log::CRITICAL);
|
||||||
|
|
||||||
m_moveStorageInfo.newPath.clear();
|
m_moveStorageInfo.newPath.clear();
|
||||||
@@ -1647,13 +1649,13 @@ void TorrentHandle::handleFastResumeRejectedAlert(libtorrent::fastresume_rejecte
|
|||||||
updateStatus();
|
updateStatus();
|
||||||
if (p->error.value() == libt::errors::mismatching_file_size) {
|
if (p->error.value() == libt::errors::mismatching_file_size) {
|
||||||
// Mismatching file size (files were probably moved)
|
// Mismatching file size (files were probably moved)
|
||||||
logger->addMessage(tr("File sizes mismatch for torrent '%1', pausing it.").arg(name()), Log::CRITICAL);
|
logger->addMessage(QCoreApplication::translate(i18nContext, "File sizes mismatch for torrent '%1', pausing it.").arg(name()), Log::CRITICAL);
|
||||||
m_hasMissingFiles = true;
|
m_hasMissingFiles = true;
|
||||||
if (!isPaused())
|
if (!isPaused())
|
||||||
pause();
|
pause();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logger->addMessage(tr("Fast resume data was rejected for torrent '%1'. Reason: %2. Checking again...")
|
logger->addMessage(QCoreApplication::translate(i18nContext, "Fast resume data was rejected for torrent '%1'. Reason: %2. Checking again...")
|
||||||
.arg(name()).arg(QString::fromStdString(p->message())), Log::CRITICAL);
|
.arg(name()).arg(QString::fromStdString(p->message())), Log::CRITICAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ namespace Http
|
|||||||
const char CONTENT_TYPE_JSON[] = "application/json";
|
const char CONTENT_TYPE_JSON[] = "application/json";
|
||||||
const char CONTENT_TYPE_PNG[] = "image/png";
|
const char CONTENT_TYPE_PNG[] = "image/png";
|
||||||
const char CONTENT_TYPE_TXT[] = "text/plain; charset=UTF-8";
|
const char CONTENT_TYPE_TXT[] = "text/plain; charset=UTF-8";
|
||||||
|
const char CONTENT_TYPE_SVG[] = "image/svg+xml";
|
||||||
|
|
||||||
// portability: "\r\n" doesn't guarantee mapping to the correct value
|
// portability: "\r\n" doesn't guarantee mapping to the correct value
|
||||||
const char CRLF[] = {0x0D, 0x0A, '\0'};
|
const char CRLF[] = {0x0D, 0x0A, '\0'};
|
||||||
|
|||||||
@@ -30,9 +30,12 @@
|
|||||||
* Contact : hammered999@gmail.com
|
* Contact : hammered999@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "preferences.h"
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
#include <QMutableListIterator>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
@@ -51,11 +54,10 @@
|
|||||||
#include <CoreServices/CoreServices.h>
|
#include <CoreServices/CoreServices.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "settingsstorage.h"
|
||||||
#include "utils/fs.h"
|
#include "utils/fs.h"
|
||||||
#include "utils/misc.h"
|
#include "utils/misc.h"
|
||||||
#include "settingsstorage.h"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "preferences.h"
|
|
||||||
|
|
||||||
Preferences *Preferences::m_instance = 0;
|
Preferences *Preferences::m_instance = 0;
|
||||||
|
|
||||||
@@ -463,6 +465,42 @@ void Preferences::setWebUiLocalAuthEnabled(bool enabled)
|
|||||||
setValue("Preferences/WebUI/LocalHostAuth", enabled);
|
setValue("Preferences/WebUI/LocalHostAuth", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::isWebUiAuthSubnetWhitelistEnabled() const
|
||||||
|
{
|
||||||
|
return value("Preferences/WebUI/AuthSubnetWhitelistEnabled", false).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setWebUiAuthSubnetWhitelistEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
setValue("Preferences/WebUI/AuthSubnetWhitelistEnabled", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Utils::Net::Subnet> Preferences::getWebUiAuthSubnetWhitelist() const
|
||||||
|
{
|
||||||
|
QList<Utils::Net::Subnet> subnets;
|
||||||
|
foreach (const QString &rawSubnet, value("Preferences/WebUI/AuthSubnetWhitelist").toStringList()) {
|
||||||
|
bool ok = false;
|
||||||
|
const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(rawSubnet.trimmed(), &ok);
|
||||||
|
if (ok)
|
||||||
|
subnets.append(subnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subnets;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setWebUiAuthSubnetWhitelist(QStringList subnets)
|
||||||
|
{
|
||||||
|
QMutableListIterator<QString> i(subnets);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
bool ok = false;
|
||||||
|
const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(i.next().trimmed(), &ok);
|
||||||
|
if (!ok)
|
||||||
|
i.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue("Preferences/WebUI/AuthSubnetWhitelist", subnets);
|
||||||
|
}
|
||||||
|
|
||||||
QString Preferences::getServerDomains() const
|
QString Preferences::getServerDomains() const
|
||||||
{
|
{
|
||||||
return value("Preferences/WebUI/ServerDomains", "*").toString();
|
return value("Preferences/WebUI/ServerDomains", "*").toString();
|
||||||
@@ -1183,9 +1221,9 @@ void Preferences::setMainLastDir(const QString &path)
|
|||||||
setValue("MainWindowLastDir", path);
|
setValue("MainWindowLastDir", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Preferences::getPrefSize(const QSize &defaultSize) const
|
QSize Preferences::getPrefSize() const
|
||||||
{
|
{
|
||||||
return value("Preferences/State/size", defaultSize).toSize();
|
return value("Preferences/State/size").toSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setPrefSize(const QSize &size)
|
void Preferences::setPrefSize(const QSize &size)
|
||||||
@@ -1263,9 +1301,9 @@ void Preferences::setPropTrackerListState(const QByteArray &state)
|
|||||||
setValue("TorrentProperties/Trackers/qt5/TrackerListState", state);
|
setValue("TorrentProperties/Trackers/qt5/TrackerListState", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Preferences::getRssGeometrySize(const QSize &defaultSize) const
|
QSize Preferences::getRssGeometrySize() const
|
||||||
{
|
{
|
||||||
return value("RssFeedDownloader/geometrySize", defaultSize).toSize();
|
return value("RssFeedDownloader/geometrySize").toSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setRssGeometrySize(const QSize &geometry)
|
void Preferences::setRssGeometrySize(const QSize &geometry)
|
||||||
|
|||||||
@@ -33,15 +33,18 @@
|
|||||||
#ifndef PREFERENCES_H
|
#ifndef PREFERENCES_H
|
||||||
#define PREFERENCES_H
|
#define PREFERENCES_H
|
||||||
|
|
||||||
#include <QTime>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QHostAddress>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSize>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QReadWriteLock>
|
|
||||||
#include <QNetworkCookie>
|
#include <QNetworkCookie>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QTimer>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include "base/utils/net.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
enum scheduler_days
|
enum scheduler_days
|
||||||
@@ -170,10 +173,9 @@ public:
|
|||||||
bool isSearchEnabled() const;
|
bool isSearchEnabled() const;
|
||||||
void setSearchEnabled(bool enabled);
|
void setSearchEnabled(bool enabled);
|
||||||
|
|
||||||
|
// HTTP Server
|
||||||
bool isWebUiEnabled() const;
|
bool isWebUiEnabled() const;
|
||||||
void setWebUiEnabled(bool enabled);
|
void setWebUiEnabled(bool enabled);
|
||||||
bool isWebUiLocalAuthEnabled() const;
|
|
||||||
void setWebUiLocalAuthEnabled(bool enabled);
|
|
||||||
QString getServerDomains() const;
|
QString getServerDomains() const;
|
||||||
void setServerDomains(const QString &str);
|
void setServerDomains(const QString &str);
|
||||||
QString getWebUiAddress() const;
|
QString getWebUiAddress() const;
|
||||||
@@ -182,16 +184,28 @@ public:
|
|||||||
void setWebUiPort(quint16 port);
|
void setWebUiPort(quint16 port);
|
||||||
bool useUPnPForWebUIPort() const;
|
bool useUPnPForWebUIPort() const;
|
||||||
void setUPnPForWebUIPort(bool enabled);
|
void setUPnPForWebUIPort(bool enabled);
|
||||||
|
|
||||||
|
// Authentication
|
||||||
|
bool isWebUiLocalAuthEnabled() const;
|
||||||
|
void setWebUiLocalAuthEnabled(bool enabled);
|
||||||
|
bool isWebUiAuthSubnetWhitelistEnabled() const;
|
||||||
|
void setWebUiAuthSubnetWhitelistEnabled(bool enabled);
|
||||||
|
QList<Utils::Net::Subnet> getWebUiAuthSubnetWhitelist() const;
|
||||||
|
void setWebUiAuthSubnetWhitelist(QStringList subnets);
|
||||||
QString getWebUiUsername() const;
|
QString getWebUiUsername() const;
|
||||||
void setWebUiUsername(const QString &username);
|
void setWebUiUsername(const QString &username);
|
||||||
QString getWebUiPassword() const;
|
QString getWebUiPassword() const;
|
||||||
void setWebUiPassword(const QString &new_password);
|
void setWebUiPassword(const QString &new_password);
|
||||||
|
|
||||||
|
// HTTPS
|
||||||
bool isWebUiHttpsEnabled() const;
|
bool isWebUiHttpsEnabled() const;
|
||||||
void setWebUiHttpsEnabled(bool enabled);
|
void setWebUiHttpsEnabled(bool enabled);
|
||||||
QByteArray getWebUiHttpsCertificate() const;
|
QByteArray getWebUiHttpsCertificate() const;
|
||||||
void setWebUiHttpsCertificate(const QByteArray &data);
|
void setWebUiHttpsCertificate(const QByteArray &data);
|
||||||
QByteArray getWebUiHttpsKey() const;
|
QByteArray getWebUiHttpsKey() const;
|
||||||
void setWebUiHttpsKey(const QByteArray &data);
|
void setWebUiHttpsKey(const QByteArray &data);
|
||||||
|
|
||||||
|
// Dynamic DNS
|
||||||
bool isDynDNSEnabled() const;
|
bool isDynDNSEnabled() const;
|
||||||
void setDynDNSEnabled(bool enabled);
|
void setDynDNSEnabled(bool enabled);
|
||||||
DNS::Service getDynDNSService() const;
|
DNS::Service getDynDNSService() const;
|
||||||
@@ -287,7 +301,7 @@ public:
|
|||||||
void setMainVSplitterState(const QByteArray &state);
|
void setMainVSplitterState(const QByteArray &state);
|
||||||
QString getMainLastDir() const;
|
QString getMainLastDir() const;
|
||||||
void setMainLastDir(const QString &path);
|
void setMainLastDir(const QString &path);
|
||||||
QSize getPrefSize(const QSize &defaultSize) const;
|
QSize getPrefSize() const;
|
||||||
void setPrefSize(const QSize &size);
|
void setPrefSize(const QSize &size);
|
||||||
QStringList getPrefHSplitterSizes() const;
|
QStringList getPrefHSplitterSizes() const;
|
||||||
void setPrefHSplitterSizes(const QStringList &sizes);
|
void setPrefHSplitterSizes(const QStringList &sizes);
|
||||||
@@ -303,7 +317,7 @@ public:
|
|||||||
void setPropVisible(const bool visible);
|
void setPropVisible(const bool visible);
|
||||||
QByteArray getPropTrackerListState() const;
|
QByteArray getPropTrackerListState() const;
|
||||||
void setPropTrackerListState(const QByteArray &state);
|
void setPropTrackerListState(const QByteArray &state);
|
||||||
QSize getRssGeometrySize(const QSize &defaultSize) const;
|
QSize getRssGeometrySize() const;
|
||||||
void setRssGeometrySize(const QSize &geometry);
|
void setRssGeometrySize(const QSize &geometry);
|
||||||
QByteArray getRssHSplitterSizes() const;
|
QByteArray getRssHSplitterSizes() const;
|
||||||
void setRssHSplitterSizes(const QByteArray &sizes);
|
void setRssHSplitterSizes(const QByteArray &sizes);
|
||||||
|
|||||||
@@ -227,10 +227,9 @@ void Parser::parse(const QByteArray &feedData)
|
|||||||
// read and create items from a rss document
|
// read and create items from a rss document
|
||||||
void Parser::parse_impl(const QByteArray &feedData)
|
void Parser::parse_impl(const QByteArray &feedData)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
|
|
||||||
QXmlStreamReader xml(feedData);
|
QXmlStreamReader xml(feedData);
|
||||||
bool foundChannel = false;
|
bool foundChannel = false;
|
||||||
|
|
||||||
while (xml.readNextStartElement()) {
|
while (xml.readNextStartElement()) {
|
||||||
if (xml.name() == "rss") {
|
if (xml.name() == "rss") {
|
||||||
// Find channels
|
// Find channels
|
||||||
@@ -258,11 +257,15 @@ void Parser::parse_impl(const QByteArray &feedData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.hasError())
|
if (!foundChannel) {
|
||||||
m_result.error = xml.errorString();
|
|
||||||
else if (!foundChannel)
|
|
||||||
m_result.error = tr("Invalid RSS feed.");
|
m_result.error = tr("Invalid RSS feed.");
|
||||||
else
|
}
|
||||||
|
else if (xml.hasError()) {
|
||||||
|
m_result.error = tr("%1 (line: %2, column: %3, offset: %4).")
|
||||||
|
.arg(xml.errorString()).arg(xml.lineNumber())
|
||||||
|
.arg(xml.columnNumber()).arg(xml.characterOffset());
|
||||||
|
}
|
||||||
|
else {
|
||||||
// Sort article list chronologically
|
// Sort article list chronologically
|
||||||
// NOTE: We don't need to sort it here if articles are always
|
// NOTE: We don't need to sort it here if articles are always
|
||||||
// sorted in fetched XML in reverse chronological order
|
// sorted in fetched XML in reverse chronological order
|
||||||
@@ -271,6 +274,7 @@ void Parser::parse_impl(const QByteArray &feedData)
|
|||||||
{
|
{
|
||||||
return a1["date"].toDateTime() < a2["date"].toDateTime();
|
return a1["date"].toDateTime() < a2["date"].toDateTime();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
emit finished(m_result);
|
emit finished(m_result);
|
||||||
m_result.articles.clear(); // clear articles only
|
m_result.articles.clear(); // clear articles only
|
||||||
@@ -288,35 +292,34 @@ void Parser::parseRssArticle(QXmlStreamReader &xml)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (xml.isStartElement()) {
|
if (xml.isStartElement()) {
|
||||||
const QString text(xml.readElementText().trimmed());
|
|
||||||
|
|
||||||
if (name == QLatin1String("title")) {
|
if (name == QLatin1String("title")) {
|
||||||
article[Article::KeyTitle] = text;
|
article[Article::KeyTitle] = xml.readElementText().trimmed();
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("enclosure")) {
|
else if (name == QLatin1String("enclosure")) {
|
||||||
if (xml.attributes().value("type") == QLatin1String("application/x-bittorrent"))
|
if (xml.attributes().value("type") == QLatin1String("application/x-bittorrent"))
|
||||||
article[Article::KeyTorrentURL] = xml.attributes().value(QLatin1String("url")).toString();
|
article[Article::KeyTorrentURL] = xml.attributes().value(QLatin1String("url")).toString();
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("link")) {
|
else if (name == QLatin1String("link")) {
|
||||||
|
const QString text {xml.readElementText().trimmed()};
|
||||||
if (text.startsWith(QLatin1String("magnet:"), Qt::CaseInsensitive))
|
if (text.startsWith(QLatin1String("magnet:"), Qt::CaseInsensitive))
|
||||||
article[Article::KeyTorrentURL] = text; // magnet link instead of a news URL
|
article[Article::KeyTorrentURL] = text; // magnet link instead of a news URL
|
||||||
else
|
else
|
||||||
article[Article::KeyLink] = text;
|
article[Article::KeyLink] = text;
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("description")) {
|
else if (name == QLatin1String("description")) {
|
||||||
article[Article::KeyDescription] = text;
|
article[Article::KeyDescription] = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("pubDate")) {
|
else if (name == QLatin1String("pubDate")) {
|
||||||
article[Article::KeyDate] = parseDate(text);
|
article[Article::KeyDate] = parseDate(xml.readElementText().trimmed());
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("author")) {
|
else if (name == QLatin1String("author")) {
|
||||||
article[Article::KeyAuthor] = text;
|
article[Article::KeyAuthor] = xml.readElementText().trimmed();
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("guid")) {
|
else if (name == QLatin1String("guid")) {
|
||||||
article[Article::KeyId] = text;
|
article[Article::KeyId] = xml.readElementText().trimmed();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
article[name] = text;
|
article[name] = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,17 +329,14 @@ void Parser::parseRssArticle(QXmlStreamReader &xml)
|
|||||||
|
|
||||||
void Parser::parseRSSChannel(QXmlStreamReader &xml)
|
void Parser::parseRSSChannel(QXmlStreamReader &xml)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
Q_ASSERT(xml.isStartElement() && xml.name() == "channel");
|
|
||||||
|
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
|
|
||||||
if (xml.isStartElement()) {
|
if (xml.isStartElement()) {
|
||||||
if (xml.name() == "title") {
|
if (xml.name() == QLatin1String("title")) {
|
||||||
m_result.title = xml.readElementText();
|
m_result.title = xml.readElementText();
|
||||||
}
|
}
|
||||||
else if (xml.name() == "lastBuildDate") {
|
else if (xml.name() == QLatin1String("lastBuildDate")) {
|
||||||
QString lastBuildDate = xml.readElementText();
|
QString lastBuildDate = xml.readElementText();
|
||||||
if (!lastBuildDate.isEmpty()) {
|
if (!lastBuildDate.isEmpty()) {
|
||||||
if (m_result.lastBuildDate == lastBuildDate) {
|
if (m_result.lastBuildDate == lastBuildDate) {
|
||||||
@@ -346,7 +346,7 @@ void Parser::parseRSSChannel(QXmlStreamReader &xml)
|
|||||||
m_result.lastBuildDate = lastBuildDate;
|
m_result.lastBuildDate = lastBuildDate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xml.name() == "item") {
|
else if (xml.name() == QLatin1String("item")) {
|
||||||
parseRssArticle(xml);
|
parseRssArticle(xml);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,14 +366,12 @@ void Parser::parseAtomArticle(QXmlStreamReader &xml)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (xml.isStartElement()) {
|
if (xml.isStartElement()) {
|
||||||
const QString text(xml.readElementText().trimmed());
|
|
||||||
|
|
||||||
if (name == QLatin1String("title")) {
|
if (name == QLatin1String("title")) {
|
||||||
article[Article::KeyTitle] = text;
|
article[Article::KeyTitle] = xml.readElementText().trimmed();
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("link")) {
|
else if (name == QLatin1String("link")) {
|
||||||
QString link = (xml.attributes().isEmpty()
|
QString link = (xml.attributes().isEmpty()
|
||||||
? text
|
? xml.readElementText().trimmed()
|
||||||
: xml.attributes().value(QLatin1String("href")).toString());
|
: xml.attributes().value(QLatin1String("href")).toString());
|
||||||
|
|
||||||
if (link.startsWith(QLatin1String("magnet:"), Qt::CaseInsensitive))
|
if (link.startsWith(QLatin1String("magnet:"), Qt::CaseInsensitive))
|
||||||
@@ -385,42 +383,38 @@ void Parser::parseAtomArticle(QXmlStreamReader &xml)
|
|||||||
article[Article::KeyLink] = (m_baseUrl.isEmpty() ? link : m_baseUrl + link);
|
article[Article::KeyLink] = (m_baseUrl.isEmpty() ? link : m_baseUrl + link);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ((name == QLatin1String("summary")) || (name == QLatin1String("content"))){
|
else if ((name == QLatin1String("summary")) || (name == QLatin1String("content"))) {
|
||||||
if (doubleContent) { // Duplicate content -> ignore
|
if (doubleContent) { // Duplicate content -> ignore
|
||||||
xml.readNext();
|
xml.skipCurrentElement();
|
||||||
|
|
||||||
while ((xml.name() != QLatin1String("summary")) && (xml.name() != QLatin1String("content")))
|
|
||||||
xml.readNext();
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to also parse broken articles, which don't use html '&' escapes
|
// Try to also parse broken articles, which don't use html '&' escapes
|
||||||
// Actually works great for non-broken content too
|
// Actually works great for non-broken content too
|
||||||
QString feedText = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString feedText = xml.readElementText(QXmlStreamReader::IncludeChildElements).trimmed();
|
||||||
if (!feedText.isEmpty())
|
if (!feedText.isEmpty()) {
|
||||||
article[Article::KeyDescription] = feedText.trimmed();
|
article[Article::KeyDescription] = feedText;
|
||||||
|
doubleContent = true;
|
||||||
doubleContent = true;
|
}
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("updated")) {
|
else if (name == QLatin1String("updated")) {
|
||||||
// ATOM uses standard compliant date, don't do fancy stuff
|
// ATOM uses standard compliant date, don't do fancy stuff
|
||||||
QDateTime articleDate = QDateTime::fromString(text, Qt::ISODate);
|
QDateTime articleDate = QDateTime::fromString(xml.readElementText().trimmed(), Qt::ISODate);
|
||||||
article[Article::KeyDate] = (articleDate.isValid() ? articleDate : QDateTime::currentDateTime());
|
article[Article::KeyDate] = (articleDate.isValid() ? articleDate : QDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("author")) {
|
else if (name == QLatin1String("author")) {
|
||||||
xml.readNext();
|
while (xml.readNextStartElement()) {
|
||||||
while (xml.name() != QLatin1String("author")) {
|
|
||||||
if (xml.name() == QLatin1String("name"))
|
if (xml.name() == QLatin1String("name"))
|
||||||
article[Article::KeyAuthor] = xml.readElementText().trimmed();
|
article[Article::KeyAuthor] = xml.readElementText().trimmed();
|
||||||
xml.readNext();
|
else
|
||||||
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (name == QLatin1String("id")) {
|
else if (name == QLatin1String("id")) {
|
||||||
article[Article::KeyId] = text;
|
article[Article::KeyId] = xml.readElementText().trimmed();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
article[name] = text;
|
article[name] = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,19 +424,16 @@ void Parser::parseAtomArticle(QXmlStreamReader &xml)
|
|||||||
|
|
||||||
void Parser::parseAtomChannel(QXmlStreamReader &xml)
|
void Parser::parseAtomChannel(QXmlStreamReader &xml)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
Q_ASSERT(xml.isStartElement() && xml.name() == "feed");
|
|
||||||
|
|
||||||
m_baseUrl = xml.attributes().value("xml:base").toString();
|
m_baseUrl = xml.attributes().value("xml:base").toString();
|
||||||
|
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
|
|
||||||
if (xml.isStartElement()) {
|
if (xml.isStartElement()) {
|
||||||
if (xml.name() == "title") {
|
if (xml.name() == QLatin1String("title")) {
|
||||||
m_result.title = xml.readElementText();
|
m_result.title = xml.readElementText();
|
||||||
}
|
}
|
||||||
else if (xml.name() == "updated") {
|
else if (xml.name() == QLatin1String("updated")) {
|
||||||
QString lastBuildDate = xml.readElementText();
|
QString lastBuildDate = xml.readElementText();
|
||||||
if (!lastBuildDate.isEmpty()) {
|
if (!lastBuildDate.isEmpty()) {
|
||||||
if (m_result.lastBuildDate == lastBuildDate) {
|
if (m_result.lastBuildDate == lastBuildDate) {
|
||||||
@@ -452,7 +443,7 @@ void Parser::parseAtomChannel(QXmlStreamReader &xml)
|
|||||||
m_result.lastBuildDate = lastBuildDate;
|
m_result.lastBuildDate = lastBuildDate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xml.name() == "entry") {
|
else if (xml.name() == QLatin1String("entry")) {
|
||||||
parseAtomArticle(xml);
|
parseAtomArticle(xml);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "rss_autodownloader.h"
|
#include "rss_autodownloader.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include "../bittorrent/magneturi.h"
|
#include "../bittorrent/magneturi.h"
|
||||||
#include "../bittorrent/session.h"
|
#include "../bittorrent/session.h"
|
||||||
@@ -63,6 +65,32 @@ const QString RulesFileName(QStringLiteral("download_rules.json"));
|
|||||||
|
|
||||||
const QString SettingsKey_ProcessingEnabled(QStringLiteral("RSS/AutoDownloader/EnableProcessing"));
|
const QString SettingsKey_ProcessingEnabled(QStringLiteral("RSS/AutoDownloader/EnableProcessing"));
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QVector<RSS::AutoDownloadRule> rulesFromJSON(const QByteArray &jsonData)
|
||||||
|
{
|
||||||
|
QJsonParseError jsonError;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &jsonError);
|
||||||
|
if (jsonError.error != QJsonParseError::NoError)
|
||||||
|
throw RSS::ParsingError(jsonError.errorString());
|
||||||
|
|
||||||
|
if (!jsonDoc.isObject())
|
||||||
|
throw RSS::ParsingError(RSS::AutoDownloader::tr("Invalid data format."));
|
||||||
|
|
||||||
|
const QJsonObject jsonObj {jsonDoc.object()};
|
||||||
|
QVector<RSS::AutoDownloadRule> rules;
|
||||||
|
for (auto it = jsonObj.begin(); it != jsonObj.end(); ++it) {
|
||||||
|
const QJsonValue jsonVal {it.value()};
|
||||||
|
if (!jsonVal.isObject())
|
||||||
|
throw RSS::ParsingError(RSS::AutoDownloader::tr("Invalid data format."));
|
||||||
|
|
||||||
|
rules.append(RSS::AutoDownloadRule::fromJsonObject(jsonVal.toObject(), it.key()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using namespace RSS;
|
using namespace RSS;
|
||||||
|
|
||||||
QPointer<AutoDownloader> AutoDownloader::m_instance = nullptr;
|
QPointer<AutoDownloader> AutoDownloader::m_instance = nullptr;
|
||||||
@@ -84,8 +112,8 @@ AutoDownloader::AutoDownloader()
|
|||||||
connect(m_ioThread, &QThread::finished, m_fileStorage, &AsyncFileStorage::deleteLater);
|
connect(m_ioThread, &QThread::finished, m_fileStorage, &AsyncFileStorage::deleteLater);
|
||||||
connect(m_fileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
|
connect(m_fileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
|
||||||
{
|
{
|
||||||
Logger::instance()->addMessage(QString("Couldn't save RSS AutoDownloader data in %1. Error: %2")
|
LogMsg(tr("Couldn't save RSS AutoDownloader data in %1. Error: %2")
|
||||||
.arg(fileName).arg(errorString), Log::WARNING);
|
.arg(fileName).arg(errorString), Log::CRITICAL);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_ioThread->start();
|
m_ioThread->start();
|
||||||
@@ -174,6 +202,70 @@ void AutoDownloader::removeRule(const QString &ruleName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray AutoDownloader::exportRules(AutoDownloader::RulesFileFormat format) const
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case RulesFileFormat::Legacy:
|
||||||
|
return exportRulesToLegacyFormat();
|
||||||
|
default:
|
||||||
|
return exportRulesToJSONFormat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloader::importRules(const QByteArray &data, AutoDownloader::RulesFileFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case RulesFileFormat::Legacy:
|
||||||
|
importRulesFromLegacyFormat(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
importRulesFromJSONFormat(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray AutoDownloader::exportRulesToJSONFormat() const
|
||||||
|
{
|
||||||
|
QJsonObject jsonObj;
|
||||||
|
for (const auto &rule : rules())
|
||||||
|
jsonObj.insert(rule.name(), rule.toJsonObject());
|
||||||
|
|
||||||
|
return QJsonDocument(jsonObj).toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloader::importRulesFromJSONFormat(const QByteArray &data)
|
||||||
|
{
|
||||||
|
const auto rules = rulesFromJSON(data);
|
||||||
|
for (const auto &rule : rules)
|
||||||
|
insertRule(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray AutoDownloader::exportRulesToLegacyFormat() const
|
||||||
|
{
|
||||||
|
QVariantHash dict;
|
||||||
|
for (const auto &rule : rules())
|
||||||
|
dict[rule.name()] = rule.toLegacyDict();
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
QDataStream out(&data, QIODevice::WriteOnly);
|
||||||
|
out.setVersion(QDataStream::Qt_4_5);
|
||||||
|
out << dict;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloader::importRulesFromLegacyFormat(const QByteArray &data)
|
||||||
|
{
|
||||||
|
QDataStream in(data);
|
||||||
|
in.setVersion(QDataStream::Qt_4_5);
|
||||||
|
QVariantHash dict;
|
||||||
|
in >> dict;
|
||||||
|
if (in.status() != QDataStream::Ok)
|
||||||
|
throw ParsingError(tr("Invalid data format"));
|
||||||
|
|
||||||
|
for (const QVariant &val : dict)
|
||||||
|
insertRule(AutoDownloadRule::fromLegacyDict(val.toHash()));
|
||||||
|
}
|
||||||
|
|
||||||
void AutoDownloader::process()
|
void AutoDownloader::process()
|
||||||
{
|
{
|
||||||
if (m_processingQueue.isEmpty()) return; // processing was disabled
|
if (m_processingQueue.isEmpty()) return; // processing was disabled
|
||||||
@@ -276,39 +368,20 @@ void AutoDownloader::load()
|
|||||||
else if (rulesFile.open(QFile::ReadOnly))
|
else if (rulesFile.open(QFile::ReadOnly))
|
||||||
loadRules(rulesFile.readAll());
|
loadRules(rulesFile.readAll());
|
||||||
else
|
else
|
||||||
Logger::instance()->addMessage(
|
LogMsg(tr("Couldn't read RSS AutoDownloader rules from %1. Error: %2")
|
||||||
QString("Couldn't read RSS AutoDownloader rules from %1. Error: %2")
|
.arg(rulesFile.fileName()).arg(rulesFile.errorString()), Log::CRITICAL);
|
||||||
.arg(rulesFile.fileName()).arg(rulesFile.errorString()), Log::WARNING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoDownloader::loadRules(const QByteArray &data)
|
void AutoDownloader::loadRules(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QJsonParseError jsonError;
|
try {
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
const auto rules = rulesFromJSON(data);
|
||||||
if (jsonError.error != QJsonParseError::NoError) {
|
for (const auto &rule : rules)
|
||||||
Logger::instance()->addMessage(
|
setRule_impl(rule);
|
||||||
QString("Couldn't parse RSS AutoDownloader rules. Error: %1")
|
|
||||||
.arg(jsonError.errorString()), Log::WARNING);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
catch (const ParsingError &error) {
|
||||||
if (!jsonDoc.isObject()) {
|
LogMsg(tr("Couldn't load RSS AutoDownloader rules. Reason: %1")
|
||||||
Logger::instance()->addMessage(
|
.arg(error.message()), Log::CRITICAL);
|
||||||
QString("Couldn't load RSS AutoDownloader rules. Invalid data format."), Log::WARNING);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject jsonObj = jsonDoc.object();
|
|
||||||
foreach (const QString &key, jsonObj.keys()) {
|
|
||||||
const QJsonValue jsonVal = jsonObj.value(key);
|
|
||||||
if (!jsonVal.isObject()) {
|
|
||||||
Logger::instance()->addMessage(
|
|
||||||
QString("Couldn't load RSS AutoDownloader rule '%1'. Invalid data format.")
|
|
||||||
.arg(key), Log::WARNING);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
setRule_impl(AutoDownloadRule::fromJsonObject(jsonVal.toObject(), key));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +390,7 @@ void AutoDownloader::loadRulesLegacy()
|
|||||||
SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss"));
|
SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss"));
|
||||||
QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash();
|
QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash();
|
||||||
foreach (const QVariant &ruleVar, rules) {
|
foreach (const QVariant &ruleVar, rules) {
|
||||||
auto rule = AutoDownloadRule::fromVariantHash(ruleVar.toHash());
|
auto rule = AutoDownloadRule::fromLegacyDict(ruleVar.toHash());
|
||||||
if (!rule.name().isEmpty())
|
if (!rule.name().isEmpty())
|
||||||
insertRule(rule);
|
insertRule(rule);
|
||||||
}
|
}
|
||||||
@@ -351,6 +424,8 @@ bool AutoDownloader::isProcessingEnabled() const
|
|||||||
void AutoDownloader::resetProcessingQueue()
|
void AutoDownloader::resetProcessingQueue()
|
||||||
{
|
{
|
||||||
m_processingQueue.clear();
|
m_processingQueue.clear();
|
||||||
|
if (!m_processingEnabled) return;
|
||||||
|
|
||||||
foreach (Article *article, Session::instance()->rootFolder()->articles()) {
|
foreach (Article *article, Session::instance()->rootFolder()->articles()) {
|
||||||
if (!article->isRead() && !article->torrentUrl().isEmpty())
|
if (!article->isRead() && !article->torrentUrl().isEmpty())
|
||||||
addJobForArticle(article);
|
addJobForArticle(article);
|
||||||
@@ -385,3 +460,13 @@ void AutoDownloader::timerEvent(QTimerEvent *event)
|
|||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
store();
|
store();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParsingError::ParsingError(const QString &message)
|
||||||
|
: std::runtime_error(message.toUtf8().data())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ParsingError::message() const
|
||||||
|
{
|
||||||
|
return what();
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <QBasicTimer>
|
#include <QBasicTimer>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
@@ -49,6 +51,13 @@ namespace RSS
|
|||||||
|
|
||||||
class AutoDownloadRule;
|
class AutoDownloadRule;
|
||||||
|
|
||||||
|
class ParsingError : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ParsingError(const QString &message);
|
||||||
|
QString message() const;
|
||||||
|
};
|
||||||
|
|
||||||
class AutoDownloader final: public QObject
|
class AutoDownloader final: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -60,6 +69,12 @@ namespace RSS
|
|||||||
~AutoDownloader() override;
|
~AutoDownloader() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum class RulesFileFormat
|
||||||
|
{
|
||||||
|
Legacy,
|
||||||
|
JSON
|
||||||
|
};
|
||||||
|
|
||||||
static AutoDownloader *instance();
|
static AutoDownloader *instance();
|
||||||
|
|
||||||
bool isProcessingEnabled() const;
|
bool isProcessingEnabled() const;
|
||||||
@@ -73,6 +88,9 @@ namespace RSS
|
|||||||
bool renameRule(const QString &ruleName, const QString &newRuleName);
|
bool renameRule(const QString &ruleName, const QString &newRuleName);
|
||||||
void removeRule(const QString &ruleName);
|
void removeRule(const QString &ruleName);
|
||||||
|
|
||||||
|
QByteArray exportRules(RulesFileFormat format = RulesFileFormat::JSON) const;
|
||||||
|
void importRules(const QByteArray &data, RulesFileFormat format = RulesFileFormat::JSON);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void processingStateChanged(bool enabled);
|
void processingStateChanged(bool enabled);
|
||||||
void ruleAdded(const QString &ruleName);
|
void ruleAdded(const QString &ruleName);
|
||||||
@@ -98,6 +116,10 @@ namespace RSS
|
|||||||
void loadRulesLegacy();
|
void loadRulesLegacy();
|
||||||
void store();
|
void store();
|
||||||
void storeDeferred();
|
void storeDeferred();
|
||||||
|
QByteArray exportRulesToJSONFormat() const;
|
||||||
|
void importRulesFromJSONFormat(const QByteArray &data);
|
||||||
|
QByteArray exportRulesToLegacyFormat() const;
|
||||||
|
void importRulesFromLegacyFormat(const QByteArray &data);
|
||||||
|
|
||||||
static QPointer<AutoDownloader> m_instance;
|
static QPointer<AutoDownloader> m_instance;
|
||||||
|
|
||||||
|
|||||||
@@ -63,11 +63,29 @@ namespace
|
|||||||
QJsonValue triStateBoolToJsonValue(const TriStateBool &triStateBool)
|
QJsonValue triStateBoolToJsonValue(const TriStateBool &triStateBool)
|
||||||
{
|
{
|
||||||
switch (static_cast<int>(triStateBool)) {
|
switch (static_cast<int>(triStateBool)) {
|
||||||
case 0: return false; break;
|
case 0: return false;
|
||||||
case 1: return true; break;
|
case 1: return true;
|
||||||
default: return QJsonValue();
|
default: return QJsonValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TriStateBool addPausedLegacyToTriStateBool(int val)
|
||||||
|
{
|
||||||
|
switch (val) {
|
||||||
|
case 1: return TriStateBool::True; // always
|
||||||
|
case 2: return TriStateBool::False; // never
|
||||||
|
default: return TriStateBool::Undefined; // default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int triStateBoolToAddPausedLegacy(const TriStateBool &triStateBool)
|
||||||
|
{
|
||||||
|
switch (static_cast<int>(triStateBool)) {
|
||||||
|
case 0: return 2; // never
|
||||||
|
case 1: return 1; // always
|
||||||
|
default: return 0; // default
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString Str_Name(QStringLiteral("name"));
|
const QString Str_Name(QStringLiteral("name"));
|
||||||
@@ -378,21 +396,37 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
|
|||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoDownloadRule AutoDownloadRule::fromVariantHash(const QVariantHash &varHash)
|
QVariantHash AutoDownloadRule::toLegacyDict() const
|
||||||
{
|
{
|
||||||
AutoDownloadRule rule(varHash.value("name").toString());
|
return {{"name", name()},
|
||||||
|
{"must_contain", mustContain()},
|
||||||
|
{"must_not_contain", mustNotContain()},
|
||||||
|
{"save_path", savePath()},
|
||||||
|
{"affected_feeds", feedURLs()},
|
||||||
|
{"enabled", isEnabled()},
|
||||||
|
{"category_assigned", assignedCategory()},
|
||||||
|
{"use_regex", useRegex()},
|
||||||
|
{"add_paused", triStateBoolToAddPausedLegacy(addPaused())},
|
||||||
|
{"episode_filter", episodeFilter()},
|
||||||
|
{"last_match", lastMatch()},
|
||||||
|
{"ignore_days", ignoreDays()}};
|
||||||
|
}
|
||||||
|
|
||||||
rule.setUseRegex(varHash.value("use_regex", false).toBool());
|
AutoDownloadRule AutoDownloadRule::fromLegacyDict(const QVariantHash &dict)
|
||||||
rule.setMustContain(varHash.value("must_contain").toString());
|
{
|
||||||
rule.setMustNotContain(varHash.value("must_not_contain").toString());
|
AutoDownloadRule rule(dict.value("name").toString());
|
||||||
rule.setEpisodeFilter(varHash.value("episode_filter").toString());
|
|
||||||
rule.setFeedURLs(varHash.value("affected_feeds").toStringList());
|
rule.setUseRegex(dict.value("use_regex", false).toBool());
|
||||||
rule.setEnabled(varHash.value("enabled", false).toBool());
|
rule.setMustContain(dict.value("must_contain").toString());
|
||||||
rule.setSavePath(varHash.value("save_path").toString());
|
rule.setMustNotContain(dict.value("must_not_contain").toString());
|
||||||
rule.setCategory(varHash.value("category_assigned").toString());
|
rule.setEpisodeFilter(dict.value("episode_filter").toString());
|
||||||
rule.setAddPaused(TriStateBool(varHash.value("add_paused").toInt() - 1));
|
rule.setFeedURLs(dict.value("affected_feeds").toStringList());
|
||||||
rule.setLastMatch(varHash.value("last_match").toDateTime());
|
rule.setEnabled(dict.value("enabled", false).toBool());
|
||||||
rule.setIgnoreDays(varHash.value("ignore_days").toInt());
|
rule.setSavePath(dict.value("save_path").toString());
|
||||||
|
rule.setCategory(dict.value("category_assigned").toString());
|
||||||
|
rule.setAddPaused(addPausedLegacyToTriStateBool(dict.value("add_paused").toInt()));
|
||||||
|
rule.setLastMatch(dict.value("last_match").toDateTime());
|
||||||
|
rule.setIgnoreDays(dict.value("ignore_days").toInt());
|
||||||
|
|
||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ namespace RSS
|
|||||||
|
|
||||||
QJsonObject toJsonObject() const;
|
QJsonObject toJsonObject() const;
|
||||||
static AutoDownloadRule fromJsonObject(const QJsonObject &jsonObj, const QString &name = "");
|
static AutoDownloadRule fromJsonObject(const QJsonObject &jsonObj, const QString &name = "");
|
||||||
static AutoDownloadRule fromVariantHash(const QVariantHash &varHash);
|
|
||||||
|
QVariantHash toLegacyDict() const;
|
||||||
|
static AutoDownloadRule fromLegacyDict(const QVariantHash &dict);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool matches(const QString &articleTitle, const QString &expression) const;
|
bool matches(const QString &articleTitle, const QString &expression) const;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "rss_feed.h"
|
#include "rss_feed.h"
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|||||||
@@ -102,6 +102,27 @@ Session::Session()
|
|||||||
m_refreshTimer.start(m_refreshInterval * MsecsPerMin);
|
m_refreshTimer.start(m_refreshInterval * MsecsPerMin);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove legacy/corrupted settings
|
||||||
|
// (at least on Windows, QSettings is case-insensitive and it can get
|
||||||
|
// confused when asked about settings that differ only in their case)
|
||||||
|
auto settingsStorage = SettingsStorage::instance();
|
||||||
|
settingsStorage->removeValue("Rss/streamList");
|
||||||
|
settingsStorage->removeValue("Rss/streamAlias");
|
||||||
|
settingsStorage->removeValue("Rss/open_folders");
|
||||||
|
settingsStorage->removeValue("Rss/qt5/splitter_h");
|
||||||
|
settingsStorage->removeValue("Rss/qt5/splitterMain");
|
||||||
|
settingsStorage->removeValue("Rss/hosts_cookies");
|
||||||
|
settingsStorage->removeValue("RSS/streamList");
|
||||||
|
settingsStorage->removeValue("RSS/streamAlias");
|
||||||
|
settingsStorage->removeValue("RSS/open_folders");
|
||||||
|
settingsStorage->removeValue("RSS/qt5/splitter_h");
|
||||||
|
settingsStorage->removeValue("RSS/qt5/splitterMain");
|
||||||
|
settingsStorage->removeValue("RSS/hosts_cookies");
|
||||||
|
settingsStorage->removeValue("Rss/Session/EnableProcessing");
|
||||||
|
settingsStorage->removeValue("Rss/Session/RefreshInterval");
|
||||||
|
settingsStorage->removeValue("Rss/Session/MaxArticlesPerFeed");
|
||||||
|
settingsStorage->removeValue("Rss/AutoDownloader/EnableProcessing");
|
||||||
}
|
}
|
||||||
|
|
||||||
Session::~Session()
|
Session::~Session()
|
||||||
@@ -163,7 +184,7 @@ bool Session::moveItem(const QString &itemPath, const QString &destPath, QString
|
|||||||
auto item = m_itemsByPath.value(itemPath);
|
auto item = m_itemsByPath.value(itemPath);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
if (error)
|
if (error)
|
||||||
*error = tr("Item doesn't exists: %1.").arg(itemPath);
|
*error = tr("Item doesn't exist: %1.").arg(itemPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +222,7 @@ bool Session::removeItem(const QString &itemPath, QString *error)
|
|||||||
auto item = m_itemsByPath.value(itemPath);
|
auto item = m_itemsByPath.value(itemPath);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
if (error)
|
if (error)
|
||||||
*error = tr("Item doesn't exists: %1.").arg(itemPath);
|
*error = tr("Item doesn't exist: %1.").arg(itemPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,20 +316,6 @@ void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
|
|||||||
|
|
||||||
void Session::loadLegacy()
|
void Session::loadLegacy()
|
||||||
{
|
{
|
||||||
struct LegacySettingsDeleter
|
|
||||||
{
|
|
||||||
~LegacySettingsDeleter()
|
|
||||||
{
|
|
||||||
auto settingsStorage = SettingsStorage::instance();
|
|
||||||
settingsStorage->removeValue("Rss/streamList");
|
|
||||||
settingsStorage->removeValue("Rss/streamAlias");
|
|
||||||
settingsStorage->removeValue("Rss/open_folders");
|
|
||||||
settingsStorage->removeValue("Rss/qt5/splitter_h");
|
|
||||||
settingsStorage->removeValue("Rss/qt5/splitterMain");
|
|
||||||
settingsStorage->removeValue("Rss/hosts_cookies");
|
|
||||||
}
|
|
||||||
} legacySettingsDeleter;
|
|
||||||
|
|
||||||
const QStringList legacyFeedPaths = SettingsStorage::instance()->loadValue("Rss/streamList").toStringList();
|
const QStringList legacyFeedPaths = SettingsStorage::instance()->loadValue("Rss/streamList").toStringList();
|
||||||
const QStringList feedAliases = SettingsStorage::instance()->loadValue("Rss/streamAlias").toStringList();
|
const QStringList feedAliases = SettingsStorage::instance()->loadValue("Rss/streamAlias").toStringList();
|
||||||
if (legacyFeedPaths.size() != feedAliases.size()) {
|
if (legacyFeedPaths.size() != feedAliases.size()) {
|
||||||
|
|||||||
@@ -632,19 +632,6 @@ void Utils::Misc::openFolderSelect(const QString &absolutePath)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Utils::Misc::smallIconSize()
|
|
||||||
{
|
|
||||||
// Get DPI scaled icon size (device-dependent), see QT source
|
|
||||||
int s = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
|
|
||||||
return QSize(s, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize Utils::Misc::largeIconSize()
|
|
||||||
{
|
|
||||||
// Get DPI scaled icon size (device-dependent), see QT source
|
|
||||||
int s = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
|
|
||||||
return QSize(s, s);
|
|
||||||
}
|
|
||||||
#endif // DISABLE_GUI
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
QString Utils::Misc::osName()
|
QString Utils::Misc::osName()
|
||||||
|
|||||||
@@ -103,8 +103,6 @@ namespace Utils
|
|||||||
void openFolderSelect(const QString& absolutePath);
|
void openFolderSelect(const QString& absolutePath);
|
||||||
|
|
||||||
QPoint screenCenter(const QWidget *w);
|
QPoint screenCenter(const QWidget *w);
|
||||||
QSize smallIconSize();
|
|
||||||
QSize largeIconSize();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
@@ -38,5 +39,55 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
return !QHostAddress(ip).isNull();
|
return !QHostAddress(ip).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Subnet parseSubnet(const QString &subnetStr, bool *ok)
|
||||||
|
{
|
||||||
|
const Subnet invalid = qMakePair(QHostAddress(), -1);
|
||||||
|
const Subnet subnet = QHostAddress::parseSubnet(subnetStr);
|
||||||
|
if (ok)
|
||||||
|
*ok = (subnet != invalid);
|
||||||
|
return subnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canParseSubnet(const QString &subnetStr)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
parseSubnet(subnetStr, &ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLoopbackAddress(const QHostAddress &addr)
|
||||||
|
{
|
||||||
|
return (addr == QHostAddress::LocalHost)
|
||||||
|
|| (addr == QHostAddress::LocalHostIPv6)
|
||||||
|
|| (addr == QHostAddress(QLatin1String("::ffff:127.0.0.1")));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIPInRange(const QHostAddress &addr, const QList<Subnet> &subnets)
|
||||||
|
{
|
||||||
|
QHostAddress protocolEquivalentAddress;
|
||||||
|
bool addrConversionOk = false;
|
||||||
|
|
||||||
|
if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||||
|
// always succeeds
|
||||||
|
protocolEquivalentAddress = QHostAddress(addr.toIPv6Address());
|
||||||
|
addrConversionOk = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// only succeeds when addr is an ipv4-mapped ipv6 address
|
||||||
|
protocolEquivalentAddress = QHostAddress(addr.toIPv4Address(&addrConversionOk));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Subnet &subnet : subnets)
|
||||||
|
if (addr.isInSubnet(subnet) || (addrConversionOk && protocolEquivalentAddress.isInSubnet(subnet)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString subnetToString(const Subnet &subnet)
|
||||||
|
{
|
||||||
|
return subnet.first.toString() + '/' + QString::number(subnet.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,26 @@
|
|||||||
|
|
||||||
#ifndef BASE_UTILS_NET_H
|
#ifndef BASE_UTILS_NET_H
|
||||||
#define BASE_UTILS_NET_H
|
#define BASE_UTILS_NET_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QPair>
|
||||||
|
|
||||||
|
class QHostAddress;
|
||||||
class QString;
|
class QString;
|
||||||
|
class QStringList;
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
namespace Net
|
namespace Net
|
||||||
{
|
{
|
||||||
|
using Subnet = QPair<QHostAddress, int>;
|
||||||
|
|
||||||
bool isValidIP(const QString &ip);
|
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 QList<Subnet> &subnets);
|
||||||
|
QString subnetToString(const Subnet &subnet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,9 @@
|
|||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QCollator>
|
#include <QCollator>
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
#include <QtGlobal>
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
#include <QThreadStorage>
|
#include <QThreadStorage>
|
||||||
#endif
|
#endif
|
||||||
@@ -45,110 +45,106 @@ namespace
|
|||||||
class NaturalCompare
|
class NaturalCompare
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit NaturalCompare(const bool caseSensitive = true)
|
explicit NaturalCompare(const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
|
||||||
: m_caseSensitive(caseSensitive)
|
: m_caseSensitivity(caseSensitivity)
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_WIN)
|
#ifdef Q_OS_WIN
|
||||||
// Without ICU library, QCollator uses the native API on Windows 7+. But that API
|
// Without ICU library, QCollator uses the native API on Windows 7+. But that API
|
||||||
// sorts older versions of μTorrent differently than the newer ones because the
|
// sorts older versions of μTorrent differently than the newer ones because the
|
||||||
// 'μ' character is encoded differently and the native API can't cope with that.
|
// 'μ' character is encoded differently and the native API can't cope with that.
|
||||||
// So default to using our custom natural sorting algorithm instead.
|
// So default to using our custom natural sorting algorithm instead.
|
||||||
// See #5238 and #5240
|
// See #5238 and #5240
|
||||||
// Without ICU library, QCollator doesn't support `setNumericMode(true)` on OS older than Win7
|
// Without ICU library, QCollator doesn't support `setNumericMode(true)` on an OS older than Win7
|
||||||
// if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7)
|
#else
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
m_collator.setNumericMode(true);
|
m_collator.setNumericMode(true);
|
||||||
m_collator.setCaseSensitivity(caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
m_collator.setCaseSensitivity(caseSensitivity);
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const QString &left, const QString &right) const
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
// Without ICU library, QCollator uses the native API on Windows 7+. But that API
|
|
||||||
// sorts older versions of μTorrent differently than the newer ones because the
|
|
||||||
// 'μ' character is encoded differently and the native API can't cope with that.
|
|
||||||
// So default to using our custom natural sorting algorithm instead.
|
|
||||||
// See #5238 and #5240
|
|
||||||
// Without ICU library, QCollator doesn't support `setNumericMode(true)` on OS older than Win7
|
|
||||||
// if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7)
|
|
||||||
return lessThan(left, right);
|
|
||||||
#endif
|
#endif
|
||||||
return (m_collator.compare(left, right) < 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lessThan(const QString &left, const QString &right) const
|
int operator()(const QString &left, const QString &right) const
|
||||||
{
|
{
|
||||||
// Return value `false` indicates `right` should go before `left`, otherwise, after
|
#ifdef Q_OS_WIN
|
||||||
int posL = 0;
|
return compare(left, right);
|
||||||
int posR = 0;
|
#else
|
||||||
while (true) {
|
return m_collator.compare(left, right);
|
||||||
while (true) {
|
#endif
|
||||||
if ((posL == left.size()) || (posR == right.size()))
|
|
||||||
return (left.size() < right.size()); // when a shorter string is another string's prefix, shorter string place before longer string
|
|
||||||
|
|
||||||
QChar leftChar = m_caseSensitive ? left[posL] : left[posL].toLower();
|
|
||||||
QChar rightChar = m_caseSensitive ? right[posR] : right[posR].toLower();
|
|
||||||
if (leftChar == rightChar)
|
|
||||||
; // compare next character
|
|
||||||
else if (leftChar.isDigit() && rightChar.isDigit())
|
|
||||||
break; // Both are digits, break this loop and compare numbers
|
|
||||||
else
|
|
||||||
return leftChar < rightChar;
|
|
||||||
|
|
||||||
++posL;
|
|
||||||
++posR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int startL = posL;
|
|
||||||
while ((posL < left.size()) && left[posL].isDigit())
|
|
||||||
++posL;
|
|
||||||
int numL = left.midRef(startL, posL - startL).toInt();
|
|
||||||
|
|
||||||
int startR = posR;
|
|
||||||
while ((posR < right.size()) && right[posR].isDigit())
|
|
||||||
++posR;
|
|
||||||
int numR = right.midRef(startR, posR - startR).toInt();
|
|
||||||
|
|
||||||
if (numL != numR)
|
|
||||||
return (numL < numR);
|
|
||||||
|
|
||||||
// Strings + digits do match and we haven't hit string end
|
|
||||||
// Do another round
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int compare(const QString &left, const QString &right) const
|
||||||
|
{
|
||||||
|
// Return value <0: `left` is smaller than `right`
|
||||||
|
// Return value >0: `left` is greater than `right`
|
||||||
|
// Return value =0: both strings are equal
|
||||||
|
|
||||||
|
int posL = 0;
|
||||||
|
int posR = 0;
|
||||||
|
while (true) {
|
||||||
|
if ((posL == left.size()) || (posR == right.size()))
|
||||||
|
return (left.size() - right.size()); // when a shorter string is another string's prefix, shorter string place before longer string
|
||||||
|
|
||||||
|
const QChar leftChar = (m_caseSensitivity == Qt::CaseSensitive) ? left[posL] : left[posL].toLower();
|
||||||
|
const QChar rightChar = (m_caseSensitivity == Qt::CaseSensitive) ? right[posR] : right[posR].toLower();
|
||||||
|
// Compare only non-digits.
|
||||||
|
// Numbers should be compared as a whole
|
||||||
|
// otherwise the string->int conversion can yield a wrong value
|
||||||
|
if ((leftChar == rightChar) && !leftChar.isDigit()) {
|
||||||
|
// compare next character
|
||||||
|
++posL;
|
||||||
|
++posR;
|
||||||
|
}
|
||||||
|
else if (leftChar.isDigit() && rightChar.isDigit()) {
|
||||||
|
// Both are digits, compare the numbers
|
||||||
|
const auto consumeNumber = [](const QString &str, int &pos) -> int
|
||||||
|
{
|
||||||
|
const int start = pos;
|
||||||
|
while ((pos < str.size()) && str[pos].isDigit())
|
||||||
|
++pos;
|
||||||
|
return str.midRef(start, (pos - start)).toInt();
|
||||||
|
};
|
||||||
|
|
||||||
|
const int numL = consumeNumber(left, posL);
|
||||||
|
const int numR = consumeNumber(right, posR);
|
||||||
|
if (numL != numR)
|
||||||
|
return (numL - numR);
|
||||||
|
|
||||||
|
// String + digits do match and we haven't hit the end of both strings
|
||||||
|
// then continue to consume the remainings
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (leftChar.unicode() - rightChar.unicode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QCollator m_collator;
|
QCollator m_collator;
|
||||||
const bool m_caseSensitive;
|
const Qt::CaseSensitivity m_caseSensitivity;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::String::naturalCompareCaseSensitive(const QString &left, const QString &right)
|
int Utils::String::naturalCompare(const QString &left, const QString &right, const Qt::CaseSensitivity caseSensitivity)
|
||||||
{
|
{
|
||||||
// provide a single `NaturalCompare` instance for easy use
|
// provide a single `NaturalCompare` instance for easy use
|
||||||
// https://doc.qt.io/qt-5/threads-reentrancy.html
|
// https://doc.qt.io/qt-5/threads-reentrancy.html
|
||||||
|
if (caseSensitivity == Qt::CaseSensitive) {
|
||||||
#ifdef Q_OS_MAC // workaround for Apple xcode: https://stackoverflow.com/a/29929949
|
#ifdef Q_OS_MAC // workaround for Apple xcode: https://stackoverflow.com/a/29929949
|
||||||
static QThreadStorage<NaturalCompare> nCmp;
|
static QThreadStorage<NaturalCompare> nCmp;
|
||||||
if (!nCmp.hasLocalData()) nCmp.setLocalData(NaturalCompare(true));
|
if (!nCmp.hasLocalData())
|
||||||
return (nCmp.localData())(left, right);
|
nCmp.setLocalData(NaturalCompare(Qt::CaseSensitive));
|
||||||
|
return (nCmp.localData())(left, right);
|
||||||
#else
|
#else
|
||||||
thread_local NaturalCompare nCmp(true);
|
thread_local NaturalCompare nCmp(Qt::CaseSensitive);
|
||||||
return nCmp(left, right);
|
return nCmp(left, right);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::String::naturalCompareCaseInsensitive(const QString &left, const QString &right)
|
#ifdef Q_OS_MAC
|
||||||
{
|
|
||||||
// provide a single `NaturalCompare` instance for easy use
|
|
||||||
// https://doc.qt.io/qt-5/threads-reentrancy.html
|
|
||||||
#ifdef Q_OS_MAC // workaround for Apple xcode: https://stackoverflow.com/a/29929949
|
|
||||||
static QThreadStorage<NaturalCompare> nCmp;
|
static QThreadStorage<NaturalCompare> nCmp;
|
||||||
if (!nCmp.hasLocalData()) nCmp.setLocalData(NaturalCompare(false));
|
if (!nCmp.hasLocalData())
|
||||||
|
nCmp.setLocalData(NaturalCompare(Qt::CaseInsensitive));
|
||||||
return (nCmp.localData())(left, right);
|
return (nCmp.localData())(left, right);
|
||||||
#else
|
#else
|
||||||
thread_local NaturalCompare nCmp(false);
|
thread_local NaturalCompare nCmp(Qt::CaseInsensitive);
|
||||||
return nCmp(left, right);
|
return nCmp(left, right);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -188,4 +184,3 @@ QString Utils::String::wildcardToRegex(const QString &pattern)
|
|||||||
{
|
{
|
||||||
return qt_regexp_toCanonical(pattern, QRegExp::Wildcard);
|
return qt_regexp_toCanonical(pattern, QRegExp::Wildcard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,12 @@ namespace Utils
|
|||||||
// Taken from https://crackstation.net/hashing-security.htm
|
// Taken from https://crackstation.net/hashing-security.htm
|
||||||
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
||||||
|
|
||||||
bool naturalCompareCaseSensitive(const QString &left, const QString &right);
|
int naturalCompare(const QString &left, const QString &right, const Qt::CaseSensitivity caseSensitivity);
|
||||||
bool naturalCompareCaseInsensitive(const QString &left, const QString &right);
|
template <Qt::CaseSensitivity caseSensitivity>
|
||||||
|
bool naturalLessThan(const QString &left, const QString &right)
|
||||||
|
{
|
||||||
|
return (naturalCompare(left, right, caseSensitivity) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
QString wildcardToRegex(const QString &pattern);
|
QString wildcardToRegex(const QString &pattern);
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ set(QBT_GUI_HEADERS
|
|||||||
about_imp.h
|
about_imp.h
|
||||||
addnewtorrentdialog.h
|
addnewtorrentdialog.h
|
||||||
advancedsettings.h
|
advancedsettings.h
|
||||||
advancedsettings.h
|
|
||||||
autoexpandabledialog.h
|
autoexpandabledialog.h
|
||||||
banlistoptions.h
|
banlistoptions.h
|
||||||
categoryfiltermodel.h
|
categoryfiltermodel.h
|
||||||
@@ -45,6 +44,7 @@ fspathedit.h
|
|||||||
fspathedit_p.h
|
fspathedit_p.h
|
||||||
guiiconprovider.h
|
guiiconprovider.h
|
||||||
hidabletabwidget.h
|
hidabletabwidget.h
|
||||||
|
ipsubnetwhitelistoptionsdialog.h
|
||||||
loglistwidget.h
|
loglistwidget.h
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
messageboxraised.h
|
messageboxraised.h
|
||||||
@@ -74,6 +74,7 @@ transferlistfilterswidget.h
|
|||||||
transferlistsortmodel.h
|
transferlistsortmodel.h
|
||||||
transferlistwidget.h
|
transferlistwidget.h
|
||||||
updownratiodlg.h
|
updownratiodlg.h
|
||||||
|
utils.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QBT_GUI_SOURCES
|
set(QBT_GUI_SOURCES
|
||||||
@@ -90,6 +91,7 @@ executionlog.cpp
|
|||||||
fspathedit.cpp
|
fspathedit.cpp
|
||||||
fspathedit_p.cpp
|
fspathedit_p.cpp
|
||||||
guiiconprovider.cpp
|
guiiconprovider.cpp
|
||||||
|
ipsubnetwhitelistoptionsdialog.cpp
|
||||||
loglistwidget.cpp
|
loglistwidget.cpp
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
messageboxraised.cpp
|
messageboxraised.cpp
|
||||||
@@ -118,6 +120,7 @@ transferlistfilterswidget.cpp
|
|||||||
transferlistsortmodel.cpp
|
transferlistsortmodel.cpp
|
||||||
transferlistwidget.cpp
|
transferlistwidget.cpp
|
||||||
updownratiodlg.cpp
|
updownratiodlg.cpp
|
||||||
|
utils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
@@ -135,6 +138,7 @@ mainwindow.ui
|
|||||||
about.ui
|
about.ui
|
||||||
banlistoptions.ui
|
banlistoptions.ui
|
||||||
cookiesdialog.ui
|
cookiesdialog.ui
|
||||||
|
ipsubnetwhitelistoptionsdialog.ui
|
||||||
previewselectdialog.ui
|
previewselectdialog.ui
|
||||||
login.ui
|
login.ui
|
||||||
downloadfromurldlg.ui
|
downloadfromurldlg.ui
|
||||||
|
|||||||
@@ -18,11 +18,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="titleHBoxLayout">
|
<layout class="QHBoxLayout" name="titleHBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="logo">
|
<widget class="QLabel" name="logo"/>
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap resource="../icons.qrc">:/icons/skin/qbittorrent32.png</pixmap>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="lb_name">
|
<widget class="QLabel" name="lb_name">
|
||||||
@@ -57,11 +53,7 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="aboutTabLayout">
|
<layout class="QGridLayout" name="aboutTabLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="mascot_lbl">
|
<widget class="QLabel" name="labelMascot"/>
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap resource="../icons.qrc">:/icons/skin/mascot.png</pixmap>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="lb_about">
|
<widget class="QLabel" name="lb_about">
|
||||||
|
|||||||
@@ -31,10 +31,12 @@
|
|||||||
#ifndef ABOUT_H
|
#ifndef ABOUT_H
|
||||||
#define ABOUT_H
|
#define ABOUT_H
|
||||||
|
|
||||||
#include "ui_about.h"
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/unicodestrings.h"
|
#include "base/unicodestrings.h"
|
||||||
|
#include "ui_about.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
class about: public QDialog, private Ui::AboutDlg
|
class about: public QDialog, private Ui::AboutDlg
|
||||||
{
|
{
|
||||||
@@ -53,24 +55,28 @@ public:
|
|||||||
lb_name->setText("<b><h2>qBittorrent " QBT_VERSION " (32-bit)</h2></b>");
|
lb_name->setText("<b><h2>qBittorrent " QBT_VERSION " (32-bit)</h2></b>");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
logo->setPixmap(Utils::Gui::scaledPixmap(":/icons/skin/qbittorrent32.png", this));
|
||||||
|
|
||||||
// About
|
// About
|
||||||
QString aboutText = QString(
|
QString aboutText = QString(
|
||||||
"<p style=\"white-space: pre-wrap;\">"
|
"<p style=\"white-space: pre-wrap;\">"
|
||||||
"%1\n\n"
|
"%1\n\n"
|
||||||
"%2\n\n"
|
"%2\n\n"
|
||||||
"<table>"
|
"<table>"
|
||||||
"<tr><td>%3</td><td><a href=\"http://www.qbittorrent.org\">http://www.qbittorrent.org</a></td></tr>"
|
"<tr><td>%3</td><td><a href=\"https://www.qbittorrent.org\">https://www.qbittorrent.org</a></td></tr>"
|
||||||
"<tr><td>%4</td><td><a href=\"http://forum.qbittorrent.org\">http://forum.qbittorrent.org</a></td></tr>"
|
"<tr><td>%4</td><td><a href=\"http://forum.qbittorrent.org\">http://forum.qbittorrent.org</a></td></tr>"
|
||||||
"<tr><td>%5</td><td><a href=\"http://bugs.qbittorrent.org\">http://bugs.qbittorrent.org</a></td></tr>"
|
"<tr><td>%5</td><td><a href=\"http://bugs.qbittorrent.org\">http://bugs.qbittorrent.org</a></td></tr>"
|
||||||
"</table>"
|
"</table>"
|
||||||
"</p>")
|
"</p>")
|
||||||
.arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar."))
|
.arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar."))
|
||||||
.arg(tr("Copyright %1 2006-2017 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT)))
|
.arg(tr("Copyright %1 2006-2018 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT)))
|
||||||
.arg(tr("Home Page:"))
|
.arg(tr("Home Page:"))
|
||||||
.arg(tr("Forum:"))
|
.arg(tr("Forum:"))
|
||||||
.arg(tr("Bug Tracker:"));
|
.arg(tr("Bug Tracker:"));
|
||||||
lb_about->setText(aboutText);
|
lb_about->setText(aboutText);
|
||||||
|
|
||||||
|
labelMascot->setPixmap(Utils::Gui::scaledPixmap(":/icons/skin/mascot.png", this));
|
||||||
|
|
||||||
// Thanks
|
// Thanks
|
||||||
QFile thanksfile(":/thanks.html");
|
QFile thanksfile(":/thanks.html");
|
||||||
if (thanksfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (thanksfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
@@ -97,6 +103,7 @@ public:
|
|||||||
label_12->setText(Utils::Misc::libtorrentVersionString());
|
label_12->setText(Utils::Misc::libtorrentVersionString());
|
||||||
label_13->setText(Utils::Misc::boostVersionString());
|
label_13->setText(Utils::Misc::boostVersionString());
|
||||||
|
|
||||||
|
Utils::Gui::resize(this);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,36 +28,38 @@
|
|||||||
* Contact : chris@qbittorrent.org
|
* Contact : chris@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QDebug>
|
#include "addnewtorrentdialog.h"
|
||||||
#include <QString>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "autoexpandabledialog.h"
|
||||||
|
#include "base/bittorrent/magneturi.h"
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
|
#include "base/bittorrent/torrentinfo.h"
|
||||||
|
#include "base/net/downloadhandler.h"
|
||||||
|
#include "base/net/downloadmanager.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/settingsstorage.h"
|
#include "base/settingsstorage.h"
|
||||||
#include "base/settingvalue.h"
|
#include "base/settingvalue.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/torrentfileguard.h"
|
||||||
#include "base/net/downloadhandler.h"
|
#include "base/unicodestrings.h"
|
||||||
#include "base/bittorrent/session.h"
|
|
||||||
#include "base/bittorrent/magneturi.h"
|
|
||||||
#include "base/bittorrent/torrentinfo.h"
|
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "base/torrentfileguard.h"
|
|
||||||
#include "base/unicodestrings.h"
|
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
#include "autoexpandabledialog.h"
|
|
||||||
#include "messageboxraised.h"
|
#include "messageboxraised.h"
|
||||||
#include "proplistdelegate.h"
|
#include "proplistdelegate.h"
|
||||||
#include "torrentcontentmodel.h"
|
|
||||||
#include "torrentcontentfiltermodel.h"
|
#include "torrentcontentfiltermodel.h"
|
||||||
|
#include "torrentcontentmodel.h"
|
||||||
#include "ui_addnewtorrentdialog.h"
|
#include "ui_addnewtorrentdialog.h"
|
||||||
#include "addnewtorrentdialog.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -128,7 +130,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
|
|||||||
|
|
||||||
// Load categories
|
// Load categories
|
||||||
QStringList categories = session->categories().keys();
|
QStringList categories = session->categories().keys();
|
||||||
std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive);
|
std::sort(categories.begin(), categories.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
||||||
QString defaultCategory = settings()->loadValue(KEY_DEFAULTCATEGORY).toString();
|
QString defaultCategory = settings()->loadValue(KEY_DEFAULTCATEGORY).toString();
|
||||||
|
|
||||||
if (!m_torrentParams.category.isEmpty())
|
if (!m_torrentParams.category.isEmpty())
|
||||||
@@ -212,10 +214,11 @@ CachedSettingValue<int> &AddNewTorrentDialog::savePathHistoryLengthSetting()
|
|||||||
void AddNewTorrentDialog::loadState()
|
void AddNewTorrentDialog::loadState()
|
||||||
{
|
{
|
||||||
m_headerState = settings()->loadValue(KEY_TREEHEADERSTATE).toByteArray();
|
m_headerState = settings()->loadValue(KEY_TREEHEADERSTATE).toByteArray();
|
||||||
int width = settings()->loadValue(KEY_WIDTH, -1).toInt();
|
|
||||||
QSize geo = size();
|
const QSize newSize = Utils::Gui::scaledSize(this, size());
|
||||||
geo.setWidth(width);
|
const int width = settings()->loadValue(KEY_WIDTH, newSize.width()).toInt();
|
||||||
resize(geo);
|
const int height = newSize.height();
|
||||||
|
resize(width, height);
|
||||||
|
|
||||||
ui->adv_button->setChecked(settings()->loadValue(KEY_EXPANDED).toBool());
|
ui->adv_button->setChecked(settings()->loadValue(KEY_EXPANDED).toBool());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "ui_autoexpandabledialog.h"
|
#include "ui_autoexpandabledialog.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
AutoExpandableDialog::AutoExpandableDialog(QWidget *parent)
|
AutoExpandableDialog::AutoExpandableDialog(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
@@ -68,30 +69,29 @@ QString AutoExpandableDialog::getText(QWidget *parent, const QString &title, con
|
|||||||
void AutoExpandableDialog::showEvent(QShowEvent *e)
|
void AutoExpandableDialog::showEvent(QShowEvent *e)
|
||||||
{
|
{
|
||||||
// Overriding showEvent is required for consistent UI with fixed size under custom DPI
|
// Overriding showEvent is required for consistent UI with fixed size under custom DPI
|
||||||
// Show dialog
|
|
||||||
QDialog::showEvent(e);
|
QDialog::showEvent(e);
|
||||||
// and resize textbox to fit the text
|
|
||||||
|
|
||||||
// NOTE: For some strange reason QFontMetrics gets more accurate
|
// Show dialog and resize textbox to fit the text
|
||||||
// when called from showEvent. Only 6 symbols off instead of 11 symbols off.
|
// NOTE: For unknown reason QFontMetrics gets more accurate when called from showEvent.
|
||||||
int textW = m_ui->textEdit->fontMetrics().width(m_ui->textEdit->text()) + 4;
|
int wd = m_ui->textEdit->fontMetrics().width(m_ui->textEdit->text()) + 4;
|
||||||
int wd = textW;
|
|
||||||
|
|
||||||
if (!windowTitle().isEmpty()) {
|
if (!windowTitle().isEmpty()) {
|
||||||
int w = fontMetrics().width(windowTitle());
|
// not really the font metrics in window title, so we enlarge it a bit,
|
||||||
if (w > wd)
|
// including the small icon and close button width
|
||||||
wd = w;
|
int w = fontMetrics().width(windowTitle()) * 1.8;
|
||||||
|
wd = std::max(wd, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_ui->textLabel->text().isEmpty()) {
|
if (!m_ui->textLabel->text().isEmpty()) {
|
||||||
int w = m_ui->textLabel->fontMetrics().width(m_ui->textLabel->text());
|
int w = m_ui->textLabel->fontMetrics().width(m_ui->textLabel->text());
|
||||||
if (w > wd)
|
wd = std::max(wd, w);
|
||||||
wd = w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now resize the dialog to fit the contents
|
// Now resize the dialog to fit the contents
|
||||||
// max width of text from either of: label, title, textedit
|
// max width of text from either of: label, title, textedit
|
||||||
// If the value is less than dialog default size, default size is used
|
// If the value is less than dialog default size, default size is used
|
||||||
if (wd > width())
|
if (wd > width()) {
|
||||||
resize(width() - m_ui->verticalLayout->sizeHint().width() + wd, height());
|
QSize size = {width() - m_ui->verticalLayout->sizeHint().width() + wd, height()};
|
||||||
|
Utils::Gui::resize(this, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/utils/net.h"
|
#include "base/utils/net.h"
|
||||||
#include "ui_banlistoptions.h"
|
#include "ui_banlistoptions.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
BanListOptions::BanListOptions(QWidget *parent)
|
BanListOptions::BanListOptions(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
@@ -52,6 +53,8 @@ BanListOptions::BanListOptions(QWidget *parent)
|
|||||||
m_ui->bannedIPList->setModel(m_sortFilter);
|
m_ui->bannedIPList->setModel(m_sortFilter);
|
||||||
m_ui->bannedIPList->sortByColumn(0, Qt::AscendingOrder);
|
m_ui->bannedIPList->sortByColumn(0, Qt::AscendingOrder);
|
||||||
m_ui->buttonBanIP->setEnabled(false);
|
m_ui->buttonBanIP->setEnabled(false);
|
||||||
|
|
||||||
|
Utils::Gui::resize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BanListOptions::~BanListOptions()
|
BanListOptions::~BanListOptions()
|
||||||
@@ -70,8 +73,11 @@ void BanListOptions::on_buttonBox_accepted()
|
|||||||
IPList << index.data().toString();
|
IPList << index.data().toString();
|
||||||
}
|
}
|
||||||
BitTorrent::Session::instance()->setBannedIPs(IPList);
|
BitTorrent::Session::instance()->setBannedIPs(IPList);
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QDialog::reject();
|
||||||
}
|
}
|
||||||
QDialog::accept();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BanListOptions::on_buttonBanIP_clicked()
|
void BanListOptions::on_buttonBanIP_clicked()
|
||||||
|
|||||||
@@ -50,8 +50,10 @@ bool CategoryFilterProxyModel::lessThan(const QModelIndex &left, const QModelInd
|
|||||||
{
|
{
|
||||||
// "All" and "Uncategorized" must be left in place
|
// "All" and "Uncategorized" must be left in place
|
||||||
if (CategoryFilterModel::isSpecialItem(left) || CategoryFilterModel::isSpecialItem(right))
|
if (CategoryFilterModel::isSpecialItem(left) || CategoryFilterModel::isSpecialItem(right))
|
||||||
return left.row() < right.row();
|
return (left < right);
|
||||||
else
|
|
||||||
return Utils::String::naturalCompareCaseInsensitive(
|
int result = Utils::String::naturalCompare(left.data().toString(), right.data().toString()
|
||||||
left.data().toString(), right.data().toString());
|
, Qt::CaseInsensitive);
|
||||||
|
|
||||||
|
return (result < 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,11 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/utils/misc.h"
|
|
||||||
#include "categoryfiltermodel.h"
|
#include "categoryfiltermodel.h"
|
||||||
#include "categoryfilterproxymodel.h"
|
#include "categoryfilterproxymodel.h"
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
#include "torrentcategorydialog.h"
|
#include "torrentcategorydialog.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -70,7 +70,7 @@ CategoryFilterWidget::CategoryFilterWidget(QWidget *parent)
|
|||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
setUniformRowHeights(true);
|
setUniformRowHeights(true);
|
||||||
setHeaderHidden(true);
|
setHeaderHidden(true);
|
||||||
setIconSize(Utils::Misc::smallIconSize());
|
setIconSize(Utils::Gui::smallIconSize());
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "cookiesmodel.h"
|
#include "cookiesmodel.h"
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
#include "ui_cookiesdialog.h"
|
#include "ui_cookiesdialog.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#define SETTINGS_KEY(name) "CookiesDialog/" name
|
#define SETTINGS_KEY(name) "CookiesDialog/" name
|
||||||
const QString KEY_SIZE = SETTINGS_KEY("Size");
|
const QString KEY_SIZE = SETTINGS_KEY("Size");
|
||||||
@@ -50,6 +51,8 @@ CookiesDialog::CookiesDialog(QWidget *parent)
|
|||||||
setWindowIcon(GuiIconProvider::instance()->getIcon("preferences-web-browser-cookies"));
|
setWindowIcon(GuiIconProvider::instance()->getIcon("preferences-web-browser-cookies"));
|
||||||
m_ui->buttonAdd->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
m_ui->buttonAdd->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
|
||||||
m_ui->buttonDelete->setIcon(GuiIconProvider::instance()->getIcon("list-remove"));
|
m_ui->buttonDelete->setIcon(GuiIconProvider::instance()->getIcon("list-remove"));
|
||||||
|
m_ui->buttonAdd->setIconSize(Utils::Gui::mediumIconSize());
|
||||||
|
m_ui->buttonDelete->setIconSize(Utils::Gui::mediumIconSize());
|
||||||
|
|
||||||
m_ui->treeView->setModel(m_cookiesModel);
|
m_ui->treeView->setModel(m_cookiesModel);
|
||||||
if (m_cookiesModel->rowCount() > 0)
|
if (m_cookiesModel->rowCount() > 0)
|
||||||
@@ -57,7 +60,7 @@ CookiesDialog::CookiesDialog(QWidget *parent)
|
|||||||
m_cookiesModel->index(0, 0),
|
m_cookiesModel->index(0, 0),
|
||||||
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||||
|
|
||||||
resize(SettingsStorage::instance()->loadValue(KEY_SIZE, size()).toSize());
|
Utils::Gui::resize(this, SettingsStorage::instance()->loadValue(KEY_SIZE).toSize());
|
||||||
m_ui->treeView->header()->restoreState(
|
m_ui->treeView->header()->restoreState(
|
||||||
SettingsStorage::instance()->loadValue(KEY_COOKIESVIEWSTATE).toByteArray());
|
SettingsStorage::instance()->loadValue(KEY_COOKIESVIEWSTATE).toByteArray());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,12 +49,6 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -78,12 +72,6 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -33,11 +33,13 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include "ui_confirmdeletiondlg.h"
|
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
|
#include "ui_confirmdeletiondlg.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -50,13 +52,17 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
|||||||
else
|
else
|
||||||
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
||||||
// Icons
|
// Icons
|
||||||
lbl_warn->setPixmap(GuiIconProvider::instance()->getIcon("dialog-warning").pixmap(lbl_warn->height()));
|
const QSize iconSize = Utils::Gui::largeIconSize();
|
||||||
lbl_warn->setFixedWidth(lbl_warn->height());
|
lbl_warn->setPixmap(GuiIconProvider::instance()->getIcon("dialog-warning").pixmap(iconSize));
|
||||||
|
lbl_warn->setFixedWidth(iconSize.width());
|
||||||
rememberBtn->setIcon(GuiIconProvider::instance()->getIcon("object-locked"));
|
rememberBtn->setIcon(GuiIconProvider::instance()->getIcon("object-locked"));
|
||||||
|
rememberBtn->setIconSize(Utils::Gui::mediumIconSize());
|
||||||
|
|
||||||
checkPermDelete->setChecked(defaultDeleteFiles || Preferences::instance()->deleteTorrentFilesAsDefault());
|
checkPermDelete->setChecked(defaultDeleteFiles || Preferences::instance()->deleteTorrentFilesAsDefault());
|
||||||
connect(checkPermDelete, SIGNAL(clicked()), this, SLOT(updateRememberButtonState()));
|
connect(checkPermDelete, SIGNAL(clicked()), this, SLOT(updateRememberButtonState()));
|
||||||
buttonBox->button(QDialogButtonBox::Cancel)->setFocus();
|
buttonBox->button(QDialogButtonBox::Cancel)->setFocus();
|
||||||
|
|
||||||
|
Utils::Gui::resize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldDeleteLocalFiles() const {
|
bool shouldDeleteLocalFiles() const {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include "ui_downloadfromurldlg.h"
|
#include "ui_downloadfromurldlg.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
class downloadFromURL : public QDialog, private Ui::downloadFromURL
|
class downloadFromURL : public QDialog, private Ui::downloadFromURL
|
||||||
{
|
{
|
||||||
@@ -60,7 +61,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL
|
|||||||
|
|
||||||
// Paste clipboard if there is an URL in it
|
// Paste clipboard if there is an URL in it
|
||||||
QString clip_txt = qApp->clipboard()->text();
|
QString clip_txt = qApp->clipboard()->text();
|
||||||
QStringList clip_txt_list = clip_txt.split(QString::fromUtf8("\n"));
|
QStringList clip_txt_list = clip_txt.split(QLatin1Char('\n'));
|
||||||
clip_txt.clear();
|
clip_txt.clear();
|
||||||
QStringList clip_txt_list_cleaned;
|
QStringList clip_txt_list_cleaned;
|
||||||
foreach (clip_txt, clip_txt_list) {
|
foreach (clip_txt, clip_txt_list) {
|
||||||
@@ -82,6 +83,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL
|
|||||||
if (clip_txt_list_cleaned.size() > 0)
|
if (clip_txt_list_cleaned.size() > 0)
|
||||||
textUrls->setText(clip_txt_list_cleaned.join("\n"));
|
textUrls->setText(clip_txt_list_cleaned.join("\n"));
|
||||||
|
|
||||||
|
Utils::Gui::resize(this);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL
|
|||||||
void downloadButtonClicked()
|
void downloadButtonClicked()
|
||||||
{
|
{
|
||||||
QString urls = textUrls->toPlainText();
|
QString urls = textUrls->toPlainText();
|
||||||
QStringList url_list = urls.split(QString::fromUtf8("\n"));
|
QStringList url_list = urls.split(QLatin1Char('\n'));
|
||||||
QString url;
|
QString url;
|
||||||
QStringList url_list_cleaned;
|
QStringList url_list_cleaned;
|
||||||
foreach (url, url_list) {
|
foreach (url, url_list) {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const char i18nContext[] = "FileSystemPathEdit";
|
||||||
struct TrStringWithComment
|
struct TrStringWithComment
|
||||||
{
|
{
|
||||||
const char *source;
|
const char *source;
|
||||||
@@ -47,18 +49,18 @@ namespace
|
|||||||
|
|
||||||
QString tr() const
|
QString tr() const
|
||||||
{
|
{
|
||||||
return QObject::tr(source, comment);
|
return QCoreApplication::translate(i18nContext, source, comment);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr TrStringWithComment browseButtonBriefText =
|
constexpr TrStringWithComment browseButtonBriefText =
|
||||||
QT_TRANSLATE_NOOP3("FileSystemPathEdit", "...", "Launch file dialog button text (brief)");
|
QT_TRANSLATE_NOOP3(i18nContext, "...", "Launch file dialog button text (brief)");
|
||||||
constexpr TrStringWithComment browseButtonFullText =
|
constexpr TrStringWithComment browseButtonFullText =
|
||||||
QT_TRANSLATE_NOOP3("FileSystemPathEdit", "&Browse...", "Launch file dialog button text (full)");
|
QT_TRANSLATE_NOOP3(i18nContext, "&Browse...", "Launch file dialog button text (full)");
|
||||||
constexpr TrStringWithComment defaultDialogCaptionForFile =
|
constexpr TrStringWithComment defaultDialogCaptionForFile =
|
||||||
QT_TRANSLATE_NOOP3("FileSystemPathEdit", "Choose a file", "Caption for file open/save dialog");
|
QT_TRANSLATE_NOOP3(i18nContext, "Choose a file", "Caption for file open/save dialog");
|
||||||
constexpr TrStringWithComment defaultDialogCaptionForDirectory =
|
constexpr TrStringWithComment defaultDialogCaptionForDirectory =
|
||||||
QT_TRANSLATE_NOOP3("FileSystemPathEdit", "Choose a folder", "Caption for directory open dialog");
|
QT_TRANSLATE_NOOP3(i18nContext, "Choose a folder", "Caption for directory open dialog");
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileSystemPathEdit::FileSystemPathEditPrivate
|
class FileSystemPathEdit::FileSystemPathEditPrivate
|
||||||
@@ -154,7 +156,9 @@ void FileSystemPathEdit::FileSystemPathEditPrivate::modeChanged()
|
|||||||
switch (m_mode) {
|
switch (m_mode) {
|
||||||
case FileSystemPathEdit::Mode::FileOpen:
|
case FileSystemPathEdit::Mode::FileOpen:
|
||||||
case FileSystemPathEdit::Mode::FileSave:
|
case FileSystemPathEdit::Mode::FileSave:
|
||||||
pixmap = QStyle::SP_DialogOpenButton;
|
#ifdef Q_OS_WIN
|
||||||
|
pixmap = QStyle::SP_DirOpenIcon;
|
||||||
|
#endif
|
||||||
showDirsOnly = false;
|
showDirsOnly = false;
|
||||||
break;
|
break;
|
||||||
case FileSystemPathEdit::Mode::DirectoryOpen:
|
case FileSystemPathEdit::Mode::DirectoryOpen:
|
||||||
|
|||||||
211
src/gui/gui.pri
211
src/gui/gui.pri
@@ -1,122 +1,126 @@
|
|||||||
INCLUDEPATH += $$PWD
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
include(lineedit/lineedit.pri)
|
include(lineedit/lineedit.pri)
|
||||||
include(properties/properties.pri)
|
|
||||||
include(powermanagement/powermanagement.pri)
|
include(powermanagement/powermanagement.pri)
|
||||||
|
include(properties/properties.pri)
|
||||||
unix:!macx:dbus: include(qtnotify/qtnotify.pri)
|
unix:!macx:dbus: include(qtnotify/qtnotify.pri)
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/mainwindow.h \
|
|
||||||
$$PWD/transferlistwidget.h \
|
|
||||||
$$PWD/transferlistdelegate.h \
|
|
||||||
$$PWD/transferlistfilterswidget.h \
|
|
||||||
$$PWD/transferlistsortmodel.h \
|
|
||||||
$$PWD/torrentcategorydialog.h \
|
|
||||||
$$PWD/torrentcontentmodel.h \
|
|
||||||
$$PWD/torrentcontentmodelitem.h \
|
|
||||||
$$PWD/torrentcontentmodelfolder.h \
|
|
||||||
$$PWD/torrentcontentmodelfile.h \
|
|
||||||
$$PWD/torrentcontentfiltermodel.h \
|
|
||||||
$$PWD/torrentcontenttreeview.h \
|
|
||||||
$$PWD/deletionconfirmationdlg.h \
|
|
||||||
$$PWD/statusbar.h \
|
|
||||||
$$PWD/speedlimitdlg.h \
|
|
||||||
$$PWD/about_imp.h \
|
$$PWD/about_imp.h \
|
||||||
$$PWD/previewlistdelegate.h \
|
|
||||||
$$PWD/downloadfromurldlg.h \
|
|
||||||
$$PWD/trackerlogin.h \
|
|
||||||
$$PWD/hidabletabwidget.h \
|
|
||||||
$$PWD/executionlog.h \
|
|
||||||
$$PWD/guiiconprovider.h \
|
|
||||||
$$PWD/updownratiodlg.h \
|
|
||||||
$$PWD/loglistwidget.h \
|
|
||||||
$$PWD/addnewtorrentdialog.h \
|
$$PWD/addnewtorrentdialog.h \
|
||||||
|
$$PWD/advancedsettings.h \
|
||||||
$$PWD/autoexpandabledialog.h \
|
$$PWD/autoexpandabledialog.h \
|
||||||
$$PWD/statsdialog.h \
|
$$PWD/banlistoptions.h \
|
||||||
|
$$PWD/categoryfiltermodel.h \
|
||||||
|
$$PWD/categoryfilterproxymodel.h \
|
||||||
|
$$PWD/categoryfilterwidget.h \
|
||||||
|
$$PWD/cookiesdialog.h \
|
||||||
|
$$PWD/cookiesmodel.h \
|
||||||
|
$$PWD/deletionconfirmationdlg.h \
|
||||||
|
$$PWD/downloadfromurldlg.h \
|
||||||
|
$$PWD/executionlog.h \
|
||||||
|
$$PWD/fspathedit.h \
|
||||||
|
$$PWD/fspathedit_p.h \
|
||||||
|
$$PWD/guiiconprovider.h \
|
||||||
|
$$PWD/hidabletabwidget.h \
|
||||||
|
$$PWD/ipsubnetwhitelistoptionsdialog.h \
|
||||||
|
$$PWD/loglistwidget.h \
|
||||||
|
$$PWD/mainwindow.h \
|
||||||
$$PWD/messageboxraised.h \
|
$$PWD/messageboxraised.h \
|
||||||
$$PWD/optionsdlg.h \
|
$$PWD/optionsdlg.h \
|
||||||
$$PWD/advancedsettings.h \
|
$$PWD/previewlistdelegate.h \
|
||||||
$$PWD/shutdownconfirmdlg.h \
|
$$PWD/previewselectdialog.h \
|
||||||
$$PWD/torrentmodel.h \
|
$$PWD/rss/articlelistwidget.h \
|
||||||
$$PWD/torrentcreatordlg.h \
|
$$PWD/rss/automatedrssdownloader.h \
|
||||||
|
$$PWD/rss/feedlistwidget.h \
|
||||||
|
$$PWD/rss/htmlbrowser.h \
|
||||||
|
$$PWD/rss/rsswidget.h \
|
||||||
$$PWD/scanfoldersdelegate.h \
|
$$PWD/scanfoldersdelegate.h \
|
||||||
$$PWD/search/searchwidget.h \
|
|
||||||
$$PWD/search/searchtab.h \
|
|
||||||
$$PWD/search/pluginselectdlg.h \
|
$$PWD/search/pluginselectdlg.h \
|
||||||
$$PWD/search/pluginsourcedlg.h \
|
$$PWD/search/pluginsourcedlg.h \
|
||||||
$$PWD/search/searchlistdelegate.h \
|
$$PWD/search/searchlistdelegate.h \
|
||||||
$$PWD/search/searchsortmodel.h \
|
$$PWD/search/searchsortmodel.h \
|
||||||
$$PWD/cookiesmodel.h \
|
$$PWD/search/searchtab.h \
|
||||||
$$PWD/cookiesdialog.h \
|
$$PWD/search/searchwidget.h \
|
||||||
$$PWD/categoryfiltermodel.h \
|
$$PWD/shutdownconfirmdlg.h \
|
||||||
$$PWD/categoryfilterproxymodel.h \
|
$$PWD/speedlimitdlg.h \
|
||||||
$$PWD/categoryfilterwidget.h \
|
$$PWD/statsdialog.h \
|
||||||
|
$$PWD/statusbar.h \
|
||||||
$$PWD/tagfiltermodel.h \
|
$$PWD/tagfiltermodel.h \
|
||||||
$$PWD/tagfilterproxymodel.h \
|
$$PWD/tagfilterproxymodel.h \
|
||||||
$$PWD/tagfilterwidget.h \
|
$$PWD/tagfilterwidget.h \
|
||||||
$$PWD/banlistoptions.h \
|
$$PWD/torrentcategorydialog.h \
|
||||||
$$PWD/rss/rsswidget.h \
|
$$PWD/torrentcontentfiltermodel.h \
|
||||||
$$PWD/rss/articlelistwidget.h \
|
$$PWD/torrentcontentmodel.h \
|
||||||
$$PWD/rss/feedlistwidget.h \
|
$$PWD/torrentcontentmodelfile.h \
|
||||||
$$PWD/rss/automatedrssdownloader.h \
|
$$PWD/torrentcontentmodelfolder.h \
|
||||||
$$PWD/rss/htmlbrowser.h \
|
$$PWD/torrentcontentmodelitem.h \
|
||||||
$$PWD/fspathedit.h \
|
$$PWD/torrentcontenttreeview.h \
|
||||||
$$PWD/fspathedit_p.h \
|
$$PWD/torrentcreatordlg.h \
|
||||||
$$PWD/previewselectdialog.h \
|
$$PWD/torrentmodel.h \
|
||||||
|
$$PWD/trackerlogin.h \
|
||||||
|
$$PWD/transferlistdelegate.h \
|
||||||
|
$$PWD/transferlistfilterswidget.h \
|
||||||
|
$$PWD/transferlistsortmodel.h \
|
||||||
|
$$PWD/transferlistwidget.h \
|
||||||
|
$$PWD/updownratiodlg.h \
|
||||||
|
$$PWD/utils.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/mainwindow.cpp \
|
|
||||||
$$PWD/transferlistwidget.cpp \
|
|
||||||
$$PWD/transferlistsortmodel.cpp \
|
|
||||||
$$PWD/transferlistdelegate.cpp \
|
|
||||||
$$PWD/transferlistfilterswidget.cpp \
|
|
||||||
$$PWD/torrentcategorydialog.cpp \
|
|
||||||
$$PWD/torrentcontentmodel.cpp \
|
|
||||||
$$PWD/torrentcontentmodelitem.cpp \
|
|
||||||
$$PWD/torrentcontentmodelfolder.cpp \
|
|
||||||
$$PWD/torrentcontentmodelfile.cpp \
|
|
||||||
$$PWD/torrentcontentfiltermodel.cpp \
|
|
||||||
$$PWD/torrentcontenttreeview.cpp \
|
|
||||||
$$PWD/executionlog.cpp \
|
|
||||||
$$PWD/speedlimitdlg.cpp \
|
|
||||||
$$PWD/guiiconprovider.cpp \
|
|
||||||
$$PWD/updownratiodlg.cpp \
|
|
||||||
$$PWD/loglistwidget.cpp \
|
|
||||||
$$PWD/addnewtorrentdialog.cpp \
|
$$PWD/addnewtorrentdialog.cpp \
|
||||||
$$PWD/autoexpandabledialog.cpp \
|
|
||||||
$$PWD/statsdialog.cpp \
|
|
||||||
$$PWD/messageboxraised.cpp \
|
|
||||||
$$PWD/statusbar.cpp \
|
|
||||||
$$PWD/advancedsettings.cpp \
|
$$PWD/advancedsettings.cpp \
|
||||||
$$PWD/trackerlogin.cpp \
|
$$PWD/autoexpandabledialog.cpp \
|
||||||
|
$$PWD/banlistoptions.cpp \
|
||||||
|
$$PWD/categoryfiltermodel.cpp \
|
||||||
|
$$PWD/categoryfilterproxymodel.cpp \
|
||||||
|
$$PWD/categoryfilterwidget.cpp \
|
||||||
|
$$PWD/cookiesdialog.cpp \
|
||||||
|
$$PWD/cookiesmodel.cpp \
|
||||||
|
$$PWD/executionlog.cpp \
|
||||||
|
$$PWD/fspathedit.cpp \
|
||||||
|
$$PWD/fspathedit_p.cpp \
|
||||||
|
$$PWD/guiiconprovider.cpp \
|
||||||
|
$$PWD/ipsubnetwhitelistoptionsdialog.cpp \
|
||||||
|
$$PWD/loglistwidget.cpp \
|
||||||
|
$$PWD/mainwindow.cpp \
|
||||||
|
$$PWD/messageboxraised.cpp \
|
||||||
$$PWD/optionsdlg.cpp \
|
$$PWD/optionsdlg.cpp \
|
||||||
$$PWD/shutdownconfirmdlg.cpp \
|
$$PWD/previewselectdialog.cpp \
|
||||||
$$PWD/torrentmodel.cpp \
|
$$PWD/rss/articlelistwidget.cpp \
|
||||||
$$PWD/torrentcreatordlg.cpp \
|
$$PWD/rss/automatedrssdownloader.cpp \
|
||||||
|
$$PWD/rss/feedlistwidget.cpp \
|
||||||
|
$$PWD/rss/htmlbrowser.cpp \
|
||||||
|
$$PWD/rss/rsswidget.cpp \
|
||||||
$$PWD/scanfoldersdelegate.cpp \
|
$$PWD/scanfoldersdelegate.cpp \
|
||||||
$$PWD/search/searchwidget.cpp \
|
|
||||||
$$PWD/search/searchtab.cpp \
|
|
||||||
$$PWD/search/pluginselectdlg.cpp \
|
$$PWD/search/pluginselectdlg.cpp \
|
||||||
$$PWD/search/pluginsourcedlg.cpp \
|
$$PWD/search/pluginsourcedlg.cpp \
|
||||||
$$PWD/search/searchlistdelegate.cpp \
|
$$PWD/search/searchlistdelegate.cpp \
|
||||||
$$PWD/search/searchsortmodel.cpp \
|
$$PWD/search/searchsortmodel.cpp \
|
||||||
$$PWD/cookiesmodel.cpp \
|
$$PWD/search/searchtab.cpp \
|
||||||
$$PWD/cookiesdialog.cpp \
|
$$PWD/search/searchwidget.cpp \
|
||||||
$$PWD/categoryfiltermodel.cpp \
|
$$PWD/shutdownconfirmdlg.cpp \
|
||||||
$$PWD/categoryfilterproxymodel.cpp \
|
$$PWD/speedlimitdlg.cpp \
|
||||||
$$PWD/categoryfilterwidget.cpp \
|
$$PWD/statsdialog.cpp \
|
||||||
|
$$PWD/statusbar.cpp \
|
||||||
$$PWD/tagfiltermodel.cpp \
|
$$PWD/tagfiltermodel.cpp \
|
||||||
$$PWD/tagfilterproxymodel.cpp \
|
$$PWD/tagfilterproxymodel.cpp \
|
||||||
$$PWD/tagfilterwidget.cpp \
|
$$PWD/tagfilterwidget.cpp \
|
||||||
$$PWD/banlistoptions.cpp \
|
$$PWD/torrentcategorydialog.cpp \
|
||||||
$$PWD/rss/rsswidget.cpp \
|
$$PWD/torrentcontentfiltermodel.cpp \
|
||||||
$$PWD/rss/articlelistwidget.cpp \
|
$$PWD/torrentcontentmodel.cpp \
|
||||||
$$PWD/rss/feedlistwidget.cpp \
|
$$PWD/torrentcontentmodelfile.cpp \
|
||||||
$$PWD/rss/automatedrssdownloader.cpp \
|
$$PWD/torrentcontentmodelfolder.cpp \
|
||||||
$$PWD/rss/htmlbrowser.cpp \
|
$$PWD/torrentcontentmodelitem.cpp \
|
||||||
$$PWD/fspathedit.cpp \
|
$$PWD/torrentcontenttreeview.cpp \
|
||||||
$$PWD/fspathedit_p.cpp \
|
$$PWD/torrentcreatordlg.cpp \
|
||||||
$$PWD/previewselectdialog.cpp \
|
$$PWD/torrentmodel.cpp \
|
||||||
|
$$PWD/trackerlogin.cpp \
|
||||||
|
$$PWD/transferlistdelegate.cpp \
|
||||||
|
$$PWD/transferlistfilterswidget.cpp \
|
||||||
|
$$PWD/transferlistsortmodel.cpp \
|
||||||
|
$$PWD/transferlistwidget.cpp \
|
||||||
|
$$PWD/updownratiodlg.cpp \
|
||||||
|
$$PWD/utils.cpp
|
||||||
|
|
||||||
win32|macx {
|
win32|macx {
|
||||||
HEADERS += $$PWD/programupdater.h
|
HEADERS += $$PWD/programupdater.h
|
||||||
@@ -129,29 +133,30 @@ macx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
$$PWD/mainwindow.ui \
|
|
||||||
$$PWD/about.ui \
|
$$PWD/about.ui \
|
||||||
$$PWD/previewselectdialog.ui \
|
|
||||||
$$PWD/login.ui \
|
|
||||||
$$PWD/downloadfromurldlg.ui \
|
|
||||||
$$PWD/bandwidth_limit.ui \
|
|
||||||
$$PWD/updownratiodlg.ui \
|
|
||||||
$$PWD/confirmdeletiondlg.ui \
|
|
||||||
$$PWD/shutdownconfirmdlg.ui \
|
|
||||||
$$PWD/executionlog.ui \
|
|
||||||
$$PWD/addnewtorrentdialog.ui \
|
$$PWD/addnewtorrentdialog.ui \
|
||||||
$$PWD/autoexpandabledialog.ui \
|
$$PWD/autoexpandabledialog.ui \
|
||||||
$$PWD/statsdialog.ui \
|
$$PWD/bandwidth_limit.ui \
|
||||||
|
$$PWD/banlistoptions.ui \
|
||||||
|
$$PWD/confirmdeletiondlg.ui \
|
||||||
|
$$PWD/cookiesdialog.ui \
|
||||||
|
$$PWD/downloadfromurldlg.ui \
|
||||||
|
$$PWD/executionlog.ui \
|
||||||
|
$$PWD/ipsubnetwhitelistoptionsdialog.ui \
|
||||||
|
$$PWD/login.ui \
|
||||||
|
$$PWD/mainwindow.ui \
|
||||||
$$PWD/optionsdlg.ui \
|
$$PWD/optionsdlg.ui \
|
||||||
$$PWD/torrentcreatordlg.ui \
|
$$PWD/previewselectdialog.ui \
|
||||||
$$PWD/search/searchwidget.ui \
|
$$PWD/rss/automatedrssdownloader.ui \
|
||||||
|
$$PWD/rss/rsswidget.ui \
|
||||||
$$PWD/search/pluginselectdlg.ui \
|
$$PWD/search/pluginselectdlg.ui \
|
||||||
$$PWD/search/pluginsourcedlg.ui \
|
$$PWD/search/pluginsourcedlg.ui \
|
||||||
$$PWD/search/searchtab.ui \
|
$$PWD/search/searchtab.ui \
|
||||||
$$PWD/cookiesdialog.ui \
|
$$PWD/search/searchwidget.ui \
|
||||||
$$PWD/banlistoptions.ui \
|
$$PWD/shutdownconfirmdlg.ui \
|
||||||
$$PWD/rss/rsswidget.ui \
|
$$PWD/statsdialog.ui \
|
||||||
$$PWD/rss/automatedrssdownloader.ui \
|
$$PWD/torrentcategorydialog.ui \
|
||||||
$$PWD/torrentcategorydialog.ui
|
$$PWD/torrentcreatordlg.ui \
|
||||||
|
$$PWD/updownratiodlg.ui
|
||||||
|
|
||||||
RESOURCES += $$PWD/about.qrc
|
RESOURCES += $$PWD/about.qrc
|
||||||
|
|||||||
112
src/gui/ipsubnetwhitelistoptionsdialog.cpp
Normal file
112
src/gui/ipsubnetwhitelistoptionsdialog.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2017 Thomas Piccirello <thomas@piccirello.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ipsubnetwhitelistoptionsdialog.h"
|
||||||
|
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QStringListModel>
|
||||||
|
|
||||||
|
#include "base/preferences.h"
|
||||||
|
#include "base/utils/net.h"
|
||||||
|
#include "ui_ipsubnetwhitelistoptionsdialog.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
IPSubnetWhitelistOptionsDialog::IPSubnetWhitelistOptionsDialog(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_ui(new Ui::IPSubnetWhitelistOptionsDialog)
|
||||||
|
, m_modified(false)
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
QStringList authSubnetWhitelistStringList;
|
||||||
|
for (const Utils::Net::Subnet &subnet : Preferences::instance()->getWebUiAuthSubnetWhitelist())
|
||||||
|
authSubnetWhitelistStringList << Utils::Net::subnetToString(subnet);
|
||||||
|
m_model = new QStringListModel(authSubnetWhitelistStringList, this);
|
||||||
|
|
||||||
|
m_sortFilter = new QSortFilterProxyModel(this);
|
||||||
|
m_sortFilter->setDynamicSortFilter(true);
|
||||||
|
m_sortFilter->setSourceModel(m_model);
|
||||||
|
|
||||||
|
m_ui->whitelistedIPSubnetList->setModel(m_sortFilter);
|
||||||
|
m_ui->whitelistedIPSubnetList->sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
m_ui->buttonWhitelistIPSubnet->setEnabled(false);
|
||||||
|
|
||||||
|
Utils::Gui::resize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPSubnetWhitelistOptionsDialog::~IPSubnetWhitelistOptionsDialog()
|
||||||
|
{
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPSubnetWhitelistOptionsDialog::on_buttonBox_accepted()
|
||||||
|
{
|
||||||
|
if (m_modified) {
|
||||||
|
// save to session
|
||||||
|
QStringList subnets;
|
||||||
|
// Operate on the m_sortFilter to grab the strings in sorted order
|
||||||
|
for (int i = 0; i < m_sortFilter->rowCount(); ++i)
|
||||||
|
subnets.append(m_sortFilter->index(i, 0).data().toString());
|
||||||
|
Preferences::instance()->setWebUiAuthSubnetWhitelist(subnets);
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QDialog::reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPSubnetWhitelistOptionsDialog::on_buttonWhitelistIPSubnet_clicked()
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(m_ui->txtIPSubnet->text(), &ok);
|
||||||
|
if (!ok) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("The entered subnet is invalid."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_model->insertRow(m_model->rowCount());
|
||||||
|
m_model->setData(m_model->index(m_model->rowCount() - 1, 0), Utils::Net::subnetToString(subnet));
|
||||||
|
m_ui->txtIPSubnet->clear();
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPSubnetWhitelistOptionsDialog::on_buttonDeleteIPSubnet_clicked()
|
||||||
|
{
|
||||||
|
for (const auto &i : m_ui->whitelistedIPSubnetList->selectionModel()->selectedIndexes())
|
||||||
|
m_sortFilter->removeRow(i.row());
|
||||||
|
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPSubnetWhitelistOptionsDialog::on_txtIPSubnet_textChanged(const QString &subnetStr)
|
||||||
|
{
|
||||||
|
m_ui->buttonWhitelistIPSubnet->setEnabled(Utils::Net::canParseSubnet(subnetStr));
|
||||||
|
}
|
||||||
64
src/gui/ipsubnetwhitelistoptionsdialog.h
Normal file
64
src/gui/ipsubnetwhitelistoptionsdialog.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2017 Thomas Piccirello <thomas@piccirello.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPTIONS_IPSUBNETWHITELIST_H
|
||||||
|
#define OPTIONS_IPSUBNETWHITELIST_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
class QStringListModel;
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class IPSubnetWhitelistOptionsDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class IPSubnetWhitelistOptionsDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(IPSubnetWhitelistOptionsDialog)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IPSubnetWhitelistOptionsDialog(QWidget *parent = nullptr);
|
||||||
|
~IPSubnetWhitelistOptionsDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void on_buttonWhitelistIPSubnet_clicked();
|
||||||
|
void on_buttonDeleteIPSubnet_clicked();
|
||||||
|
void on_txtIPSubnet_textChanged(const QString &subnetStr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::IPSubnetWhitelistOptionsDialog *m_ui;
|
||||||
|
QStringListModel *m_model;
|
||||||
|
QSortFilterProxyModel *m_sortFilter;
|
||||||
|
bool m_modified;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OPTIONS_IPSUBNETWHITELIST_H
|
||||||
114
src/gui/ipsubnetwhitelistoptionsdialog.ui
Normal file
114
src/gui/ipsubnetwhitelistoptionsdialog.ui
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>IPSubnetWhitelistOptionsDialog</class>
|
||||||
|
<widget class="QDialog" name="IPSubnetWhitelistOptionsDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>360</width>
|
||||||
|
<height>450</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>List of whitelisted IP subnets</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="whitelistedIPSubnetBox">
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Panel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_31">
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="whitelistedIPSubnetList">
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="uniformRowHeights">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="itemsExpandable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="headerVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="txtIPSubnet">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Example: 172.17.32.0/24, fdff:ffff:c8::/40</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonWhitelistIPSubnet">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add subnet</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonDeleteIPSubnet">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>whitelistedIPSubnetList</tabstop>
|
||||||
|
<tabstop>txtIPSubnet</tabstop>
|
||||||
|
<tabstop>buttonWhitelistIPSubnet</tabstop>
|
||||||
|
<tabstop>buttonDeleteIPSubnet</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>IPSubnetWhitelistOptionsDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>179</x>
|
||||||
|
<y>427</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>179</x>
|
||||||
|
<y>224</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -6,11 +6,5 @@ set(QBT_LINEEDIT_HEADERS
|
|||||||
src/lineedit.h
|
src/lineedit.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QBT_LINEEDIT_RESOURCES
|
|
||||||
resources/lineeditimages.qrc
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(qbt_lineedit STATIC ${QBT_LINEEDIT_SOURCES} ${QBT_LINEEDIT_HEADERS})
|
add_library(qbt_lineedit STATIC ${QBT_LINEEDIT_SOURCES} ${QBT_LINEEDIT_HEADERS})
|
||||||
target_link_libraries(qbt_lineedit Qt5::Widgets)
|
target_link_libraries(qbt_lineedit Qt5::Widgets)
|
||||||
|
|
||||||
qbt_target_sources(${QBT_LINEEDIT_RESOURCES})
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
INCLUDEPATH += $$PWD/src
|
INCLUDEPATH += $$PWD/src
|
||||||
HEADERS += $$PWD/src/lineedit.h
|
HEADERS += $$PWD/src/lineedit.h
|
||||||
SOURCES += $$PWD/src/lineedit.cpp
|
SOURCES += $$PWD/src/lineedit.cpp
|
||||||
RESOURCES += $$PWD/resources/lineeditimages.qrc
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<!DOCTYPE RCC><RCC version="1.0">
|
|
||||||
<qresource>
|
|
||||||
<file>lineeditimages/search.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 292 B |
@@ -8,37 +8,35 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "lineedit.h"
|
#include "lineedit.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <QResizeEvent>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QResizeEvent>
|
|
||||||
|
#include "guiiconprovider.h"
|
||||||
|
|
||||||
LineEdit::LineEdit(QWidget *parent)
|
LineEdit::LineEdit(QWidget *parent)
|
||||||
: QLineEdit(parent)
|
: QLineEdit(parent)
|
||||||
{
|
{
|
||||||
QPixmap pixmap1(":/lineeditimages/search.png");
|
m_searchButton = new QToolButton(this);
|
||||||
searchButton = new QToolButton(this);
|
m_searchButton->setIcon(GuiIconProvider::instance()->getIcon("edit-find"));
|
||||||
searchButton->setIcon(QIcon(pixmap1));
|
m_searchButton->setCursor(Qt::ArrowCursor);
|
||||||
searchButton->setIconSize(pixmap1.size());
|
m_searchButton->setStyleSheet("QToolButton {border: none; padding: 2px;}");
|
||||||
searchButton->setCursor(Qt::ArrowCursor);
|
|
||||||
searchButton->setStyleSheet("QToolButton { border: none; padding: 2px; }");
|
// padding between text and widget borders
|
||||||
QSize searchButtonHint = searchButton->sizeHint();
|
setStyleSheet(QString("QLineEdit {padding-left: %1px;}").arg(m_searchButton->sizeHint().width()));
|
||||||
|
|
||||||
QSize clearButtonHint(0, 0);
|
|
||||||
setClearButtonEnabled(true);
|
setClearButtonEnabled(true);
|
||||||
setStyleSheet(QString("QLineEdit { padding-left: %1px; }").arg(searchButtonHint.width())); // padding between text and widget borders
|
|
||||||
|
|
||||||
QSize widgetHint = sizeHint();
|
const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
setMaximumHeight(std::max(sizeHint().height(), m_searchButton->sizeHint().height()) + frameWidth * 2);
|
||||||
setMaximumHeight(std::max({ widgetHint.height(), searchButtonHint.height(), clearButtonHint.height() }) + frameWidth * 2);
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineEdit::resizeEvent(QResizeEvent *e)
|
void LineEdit::resizeEvent(QResizeEvent *e)
|
||||||
{
|
{
|
||||||
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
|
m_searchButton->move(frameWidth, (e->size().height() - m_searchButton->sizeHint().height()) / 2);
|
||||||
QSize sz = searchButton->sizeHint();
|
|
||||||
searchButton->move(frameWidth, (e->size().height() - sz.height()) / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ public:
|
|||||||
LineEdit(QWidget *parent);
|
LineEdit(QWidget *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QToolButton *searchButton;
|
QToolButton *m_searchButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIENEDIT_H
|
#endif // LIENEDIT_H
|
||||||
|
|||||||
@@ -33,8 +33,12 @@
|
|||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <objc/objc.h>
|
#include <objc/objc.h>
|
||||||
|
|
||||||
QPixmap pixmapForExtension(const QString &ext, const QSize &size);
|
namespace MacUtils
|
||||||
void overrideDockClickHandler(bool (*dockClickHandler)(id, SEL, ...));
|
{
|
||||||
void displayNotification(const QString &title, const QString &message);
|
QPixmap pixmapForExtension(const QString &ext, const QSize &size);
|
||||||
|
void overrideDockClickHandler(bool (*dockClickHandler)(id, SEL, ...));
|
||||||
|
void displayNotification(const QString &title, const QString &message);
|
||||||
|
void openFiles(const QSet<QString> &pathsList);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // MACUTILITIES_H
|
#endif // MACUTILITIES_H
|
||||||
|
|||||||
@@ -28,56 +28,72 @@
|
|||||||
|
|
||||||
#include "macutilities.h"
|
#include "macutilities.h"
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
#include <QtMac>
|
#include <QtMac>
|
||||||
#include <objc/message.h>
|
#include <objc/message.h>
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
QPixmap pixmapForExtension(const QString &ext, const QSize &size)
|
namespace MacUtils
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
QPixmap pixmapForExtension(const QString &ext, const QSize &size)
|
||||||
NSImage *image = [[NSWorkspace sharedWorkspace] iconForFileType:ext.toNSString()];
|
{
|
||||||
if (image) {
|
@autoreleasepool {
|
||||||
NSRect rect = NSMakeRect(0, 0, size.width(), size.height());
|
NSImage *image = [[NSWorkspace sharedWorkspace] iconForFileType:ext.toNSString()];
|
||||||
CGImageRef cgImage = [image CGImageForProposedRect:&rect context:nil hints:nil];
|
if (image) {
|
||||||
return QtMac::fromCGImageRef(cgImage);
|
NSRect rect = NSMakeRect(0, 0, size.width(), size.height());
|
||||||
|
CGImageRef cgImage = [image CGImageForProposedRect:&rect context:nil hints:nil];
|
||||||
|
return QtMac::fromCGImageRef(cgImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPixmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void overrideDockClickHandler(bool (*dockClickHandler)(id, SEL, ...))
|
||||||
|
{
|
||||||
|
NSApplication *appInst = [NSApplication sharedApplication];
|
||||||
|
|
||||||
|
if (!appInst)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Class delClass = [[appInst delegate] class];
|
||||||
|
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
|
||||||
|
|
||||||
|
if (class_getInstanceMethod(delClass, shouldHandle)) {
|
||||||
|
if (class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:"))
|
||||||
|
qDebug("Registered dock click handler (replaced original method)");
|
||||||
|
else
|
||||||
|
qWarning("Failed to replace method for dock click handler");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:"))
|
||||||
|
qDebug("Registered dock click handler");
|
||||||
|
else
|
||||||
|
qWarning("Failed to register dock click handler");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayNotification(const QString &title, const QString &message)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
||||||
|
notification.title = title.toNSString();
|
||||||
|
notification.informativeText = message.toNSString();
|
||||||
|
notification.soundName = NSUserNotificationDefaultSoundName;
|
||||||
|
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void openFiles(const QSet<QString> &pathsList)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
NSMutableArray *pathURLs = [NSMutableArray arrayWithCapacity:pathsList.size()];
|
||||||
|
|
||||||
|
for (const auto &path : pathsList)
|
||||||
|
[pathURLs addObject:[NSURL fileURLWithPath:path.toNSString()]];
|
||||||
|
|
||||||
|
[[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:pathURLs];
|
||||||
}
|
}
|
||||||
|
|
||||||
return QPixmap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void overrideDockClickHandler(bool (*dockClickHandler)(id, SEL, ...))
|
|
||||||
{
|
|
||||||
NSApplication *appInst = [NSApplication sharedApplication];
|
|
||||||
|
|
||||||
if (!appInst)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Class delClass = [[appInst delegate] class];
|
|
||||||
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
|
|
||||||
|
|
||||||
if (class_getInstanceMethod(delClass, shouldHandle)) {
|
|
||||||
if (class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:"))
|
|
||||||
qDebug("Registered dock click handler (replaced original method)");
|
|
||||||
else
|
|
||||||
qWarning("Failed to replace method for dock click handler");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:"))
|
|
||||||
qDebug("Registered dock click handler");
|
|
||||||
else
|
|
||||||
qWarning("Failed to register dock click handler");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayNotification(const QString &title, const QString &message)
|
|
||||||
{
|
|
||||||
@autoreleasepool {
|
|
||||||
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
|
||||||
notification.title = title.toNSString();
|
|
||||||
notification.informativeText = message.toNSString();
|
|
||||||
notification.soundName = NSUserNotificationDefaultSoundName;
|
|
||||||
|
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,84 +30,84 @@
|
|||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#include <QClipboard>
|
||||||
#include <QtMacExtras>
|
#include <QCloseEvent>
|
||||||
#include <QtMac>
|
#include <QCryptographicHash>
|
||||||
#endif
|
#include <QDebug>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QStatusBar>
|
||||||
|
#include <QSysInfo>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <QtMac>
|
||||||
|
#include <QtMacExtras>
|
||||||
|
#endif
|
||||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB)
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB)
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#include "notifications.h"
|
#include "notifications.h"
|
||||||
#endif
|
#endif
|
||||||
#include <QDebug>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QFileSystemWatcher>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QStatusBar>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QCloseEvent>
|
|
||||||
#include <QShortcut>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QSplitter>
|
|
||||||
#include <QSysInfo>
|
|
||||||
#include <QMimeData>
|
|
||||||
#include <QCryptographicHash>
|
|
||||||
#include <QProcess>
|
|
||||||
|
|
||||||
#include "base/preferences.h"
|
#include "about_imp.h"
|
||||||
#include "base/settingsstorage.h"
|
#include "addnewtorrentdialog.h"
|
||||||
#include "base/logger.h"
|
#include "application.h"
|
||||||
#include "base/utils/misc.h"
|
#include "autoexpandabledialog.h"
|
||||||
#include "base/utils/fs.h"
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#include "base/net/downloadmanager.h"
|
|
||||||
#include "base/net/downloadhandler.h"
|
|
||||||
#endif
|
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/sessionstatus.h"
|
#include "base/bittorrent/sessionstatus.h"
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
|
#include "base/logger.h"
|
||||||
|
#include "base/preferences.h"
|
||||||
#include "base/rss/rss_folder.h"
|
#include "base/rss/rss_folder.h"
|
||||||
#include "base/rss/rss_session.h"
|
#include "base/rss/rss_session.h"
|
||||||
|
#include "base/settingsstorage.h"
|
||||||
|
#include "base/utils/fs.h"
|
||||||
|
#include "base/utils/misc.h"
|
||||||
|
#include "cookiesdialog.h"
|
||||||
|
#include "downloadfromurldlg.h"
|
||||||
|
#include "executionlog.h"
|
||||||
|
#include "guiiconprovider.h"
|
||||||
|
#include "hidabletabwidget.h"
|
||||||
|
#include "lineedit.h"
|
||||||
|
#include "optionsdlg.h"
|
||||||
|
#include "peerlistwidget.h"
|
||||||
|
#include "powermanagement.h"
|
||||||
|
#include "propertieswidget.h"
|
||||||
|
#include "rss/rsswidget.h"
|
||||||
|
#include "search/searchwidget.h"
|
||||||
|
#include "speedlimitdlg.h"
|
||||||
|
#include "statsdialog.h"
|
||||||
|
#include "statusbar.h"
|
||||||
|
#include "torrentcreatordlg.h"
|
||||||
|
#include "torrentmodel.h"
|
||||||
|
#include "trackerlist.h"
|
||||||
|
#include "transferlistfilterswidget.h"
|
||||||
|
#include "transferlistwidget.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "application.h"
|
#ifdef Q_OS_WIN
|
||||||
|
#include "base/net/downloadhandler.h"
|
||||||
|
#include "base/net/downloadmanager.h"
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include "macutilities.h"
|
||||||
|
#endif
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
#include "programupdater.h"
|
#include "programupdater.h"
|
||||||
#endif
|
#endif
|
||||||
#include "powermanagement.h"
|
|
||||||
#include "guiiconprovider.h"
|
|
||||||
#include "torrentmodel.h"
|
|
||||||
#include "autoexpandabledialog.h"
|
|
||||||
#include "torrentcreatordlg.h"
|
|
||||||
#include "downloadfromurldlg.h"
|
|
||||||
#include "addnewtorrentdialog.h"
|
|
||||||
#include "statsdialog.h"
|
|
||||||
#include "cookiesdialog.h"
|
|
||||||
#include "speedlimitdlg.h"
|
|
||||||
#include "transferlistwidget.h"
|
|
||||||
#include "search/searchwidget.h"
|
|
||||||
#include "trackerlist.h"
|
|
||||||
#include "peerlistwidget.h"
|
|
||||||
#include "transferlistfilterswidget.h"
|
|
||||||
#include "propertieswidget.h"
|
|
||||||
#include "statusbar.h"
|
|
||||||
#include "rss/rsswidget.h"
|
|
||||||
#include "about_imp.h"
|
|
||||||
#include "optionsdlg.h"
|
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
#include "trackerlogin.h"
|
#include "trackerlogin.h"
|
||||||
#endif
|
#endif
|
||||||
#include "lineedit.h"
|
|
||||||
#include "executionlog.h"
|
|
||||||
#include "hidabletabwidget.h"
|
|
||||||
#include "ui_mainwindow.h"
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
#include "macutilities.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
void qt_mac_set_dock_menu(QMenu *menu);
|
void qt_mac_set_dock_menu(QMenu *menu);
|
||||||
@@ -231,7 +231,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
m_searchFilter = new LineEdit(this);
|
m_searchFilter = new LineEdit(this);
|
||||||
m_searchFilterAction = m_ui->toolBar->insertWidget(m_ui->actionLock, m_searchFilter);
|
m_searchFilterAction = m_ui->toolBar->insertWidget(m_ui->actionLock, m_searchFilter);
|
||||||
m_searchFilter->setPlaceholderText(tr("Filter torrent list..."));
|
m_searchFilter->setPlaceholderText(tr("Filter torrent list..."));
|
||||||
m_searchFilter->setFixedWidth(200);
|
m_searchFilter->setFixedWidth(Utils::Gui::scaledSize(this, 200));
|
||||||
|
|
||||||
QWidget *spacer = new QWidget(this);
|
QWidget *spacer = new QWidget(this);
|
||||||
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
@@ -843,6 +843,11 @@ void MainWindow::createKeyboardShortcuts()
|
|||||||
m_ui->actionDelete->setShortcutContext(Qt::WidgetShortcut); // nullify its effect: delete key event is handled by respective widgets, not here
|
m_ui->actionDelete->setShortcutContext(Qt::WidgetShortcut); // nullify its effect: delete key event is handled by respective widgets, not here
|
||||||
m_ui->actionDownloadFromURL->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_O);
|
m_ui->actionDownloadFromURL->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_O);
|
||||||
m_ui->actionExit->setShortcut(Qt::CTRL + Qt::Key_Q);
|
m_ui->actionExit->setShortcut(Qt::CTRL + Qt::Key_Q);
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
m_ui->actionCloseWindow->setShortcut(QKeySequence::Close);
|
||||||
|
#else
|
||||||
|
m_ui->actionCloseWindow->setVisible(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
QShortcut *switchTransferShortcut = new QShortcut(Qt::ALT + Qt::Key_1, this);
|
QShortcut *switchTransferShortcut = new QShortcut(Qt::ALT + Qt::Key_1, this);
|
||||||
connect(switchTransferShortcut, &QShortcut::activated, this, &MainWindow::displayTransferTab);
|
connect(switchTransferShortcut, &QShortcut::activated, this, &MainWindow::displayTransferTab);
|
||||||
@@ -978,6 +983,16 @@ void MainWindow::on_actionExit_triggered()
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
void MainWindow::on_actionCloseWindow_triggered()
|
||||||
|
{
|
||||||
|
// On macOS window close is basically equivalent to window hide.
|
||||||
|
// If you decide to implement this functionality for other OS,
|
||||||
|
// then you will also need ui lock checks like in actionExit.
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QWidget *MainWindow::currentTabWidget() const
|
QWidget *MainWindow::currentTabWidget() const
|
||||||
{
|
{
|
||||||
if (isMinimized() || !isVisible())
|
if (isMinimized() || !isVisible())
|
||||||
@@ -1225,24 +1240,26 @@ void MainWindow::dropEvent(QDropEvent *event)
|
|||||||
// remove scheme
|
// remove scheme
|
||||||
QStringList files;
|
QStringList files;
|
||||||
if (event->mimeData()->hasUrls()) {
|
if (event->mimeData()->hasUrls()) {
|
||||||
const QList<QUrl> urls = event->mimeData()->urls();
|
foreach (const QUrl &url, event->mimeData()->urls()) {
|
||||||
foreach (const QUrl &url, urls) {
|
if (url.isEmpty())
|
||||||
if (!url.isEmpty()) {
|
continue;
|
||||||
if (url.scheme().compare("file", Qt::CaseInsensitive) == 0)
|
|
||||||
files << url.toLocalFile();
|
files << ((url.scheme().compare("file", Qt::CaseInsensitive) == 0)
|
||||||
else
|
? url.toLocalFile()
|
||||||
files << url.toString();
|
: url.toString());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
files = event->mimeData()->text().split('\n');
|
files = event->mimeData()->text().split('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// differentiate ".torrent" files and others
|
// differentiate ".torrent" files/links & magnet links from others
|
||||||
QStringList torrentFiles, otherFiles;
|
QStringList torrentFiles, otherFiles;
|
||||||
foreach (const QString &file, files) {
|
foreach (const QString &file, files) {
|
||||||
if (file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive))
|
const bool isTorrentLink = (file.startsWith("magnet:", Qt::CaseInsensitive)
|
||||||
|
|| file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)
|
||||||
|
|| Utils::Misc::isUrl(file));
|
||||||
|
if (isTorrentLink)
|
||||||
torrentFiles << file;
|
torrentFiles << file;
|
||||||
else
|
else
|
||||||
otherFiles << file;
|
otherFiles << file;
|
||||||
@@ -1251,7 +1268,6 @@ void MainWindow::dropEvent(QDropEvent *event)
|
|||||||
// Download torrents
|
// Download torrents
|
||||||
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
|
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
|
||||||
foreach (const QString &file, torrentFiles) {
|
foreach (const QString &file, torrentFiles) {
|
||||||
qDebug("Dropped file %s on download list", qUtf8Printable(file));
|
|
||||||
if (useTorrentAdditionDialog)
|
if (useTorrentAdditionDialog)
|
||||||
AddNewTorrentDialog::show(file, this);
|
AddNewTorrentDialog::show(file, this);
|
||||||
else
|
else
|
||||||
@@ -1297,7 +1313,7 @@ static bool dockClickHandler(id self, SEL cmd, ...)
|
|||||||
void MainWindow::setupDockClickHandler()
|
void MainWindow::setupDockClickHandler()
|
||||||
{
|
{
|
||||||
dockMainWindowHandle = this;
|
dockMainWindowHandle = this;
|
||||||
overrideDockClickHandler(dockClickHandler);
|
MacUtils::overrideDockClickHandler(dockClickHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1556,7 +1572,7 @@ void MainWindow::showNotificationBaloon(QString title, QString msg) const
|
|||||||
if (!reply.isError())
|
if (!reply.isError())
|
||||||
return;
|
return;
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
displayNotification(title, msg);
|
MacUtils::displayNotification(title, msg);
|
||||||
#else
|
#else
|
||||||
if (m_systrayIcon && QSystemTrayIcon::supportsMessages())
|
if (m_systrayIcon && QSystemTrayIcon::supportsMessages())
|
||||||
m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON);
|
m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON);
|
||||||
@@ -1838,7 +1854,7 @@ void MainWindow::toggleAlternativeSpeeds()
|
|||||||
|
|
||||||
void MainWindow::on_actionDonateMoney_triggered()
|
void MainWindow::on_actionDonateMoney_triggered()
|
||||||
{
|
{
|
||||||
QDesktopServices::openUrl(QUrl("http://www.qbittorrent.org/donate"));
|
QDesktopServices::openUrl(QUrl("https://www.qbittorrent.org/donate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showConnectionSettings()
|
void MainWindow::showConnectionSettings()
|
||||||
|
|||||||
@@ -187,7 +187,9 @@ private slots:
|
|||||||
void toolbarTextBeside();
|
void toolbarTextBeside();
|
||||||
void toolbarTextUnder();
|
void toolbarTextUnder();
|
||||||
void toolbarFollowSystem();
|
void toolbarFollowSystem();
|
||||||
#ifndef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
void on_actionCloseWindow_triggered();
|
||||||
|
#else
|
||||||
void toggleVisibility(const QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Trigger);
|
void toggleVisibility(const QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Trigger);
|
||||||
void createSystrayDelayed();
|
void createSystrayDelayed();
|
||||||
void updateTrayIconMenu();
|
void updateTrayIconMenu();
|
||||||
|
|||||||
@@ -90,6 +90,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<addaction name="actionOpen"/>
|
<addaction name="actionOpen"/>
|
||||||
<addaction name="actionDownloadFromURL"/>
|
<addaction name="actionDownloadFromURL"/>
|
||||||
|
<addaction name="actionCloseWindow"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionExit"/>
|
<addaction name="actionExit"/>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -466,6 +467,11 @@
|
|||||||
<string>Critical Messages</string>
|
<string>Critical Messages</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionCloseWindow">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close Window</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|||||||
@@ -65,8 +65,10 @@
|
|||||||
#include "advancedsettings.h"
|
#include "advancedsettings.h"
|
||||||
#include "rss/automatedrssdownloader.h"
|
#include "rss/automatedrssdownloader.h"
|
||||||
#include "banlistoptions.h"
|
#include "banlistoptions.h"
|
||||||
|
#include "ipsubnetwhitelistoptionsdialog.h"
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
#include "scanfoldersdelegate.h"
|
#include "scanfoldersdelegate.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "ui_optionsdlg.h"
|
#include "ui_optionsdlg.h"
|
||||||
|
|
||||||
@@ -98,13 +100,21 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
m_ui->tabSelection->item(TAB_WEBUI)->setHidden(true);
|
m_ui->tabSelection->item(TAB_WEBUI)->setHidden(true);
|
||||||
#endif
|
#endif
|
||||||
m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(GuiIconProvider::instance()->getIcon("preferences-other"));
|
m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(GuiIconProvider::instance()->getIcon("preferences-other"));
|
||||||
|
|
||||||
|
// set uniform size for all icons
|
||||||
|
int maxHeight = -1;
|
||||||
|
for (int i = 0; i < m_ui->tabSelection->count(); ++i)
|
||||||
|
maxHeight = std::max(maxHeight, m_ui->tabSelection->visualItemRect(m_ui->tabSelection->item(i)).size().height());
|
||||||
for (int i = 0; i < m_ui->tabSelection->count(); ++i) {
|
for (int i = 0; i < m_ui->tabSelection->count(); ++i) {
|
||||||
// uniform size for all icons
|
const QSize size(std::numeric_limits<int>::max(), static_cast<int>(maxHeight * 1.2));
|
||||||
m_ui->tabSelection->item(i)->setSizeHint(QSize(std::numeric_limits<int>::max(), 62));
|
m_ui->tabSelection->item(i)->setSizeHint(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ui->IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
|
m_ui->IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
|
||||||
|
|
||||||
|
m_ui->labelGlobalRate->setPixmap(Utils::Gui::scaledPixmap(":/icons/slow_off.png", this, 16));
|
||||||
|
m_ui->labelAltRate->setPixmap(Utils::Gui::scaledPixmap(":/icons/slow.png", this, 16));
|
||||||
|
|
||||||
m_ui->deleteTorrentWarningIcon->setPixmap(QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(16, 16));
|
m_ui->deleteTorrentWarningIcon->setPixmap(QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(16, 16));
|
||||||
m_ui->deleteTorrentWarningIcon->hide();
|
m_ui->deleteTorrentWarningIcon->hide();
|
||||||
m_ui->deleteTorrentWarningLabel->hide();
|
m_ui->deleteTorrentWarningLabel->hide();
|
||||||
@@ -138,7 +148,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
connect(ScanFoldersModel::instance(), &QAbstractListModel::dataChanged, this, &ThisType::enableApplyButton);
|
connect(ScanFoldersModel::instance(), &QAbstractListModel::dataChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->scanFoldersView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ThisType::handleScanFolderViewSelectionChanged);
|
connect(m_ui->scanFoldersView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ThisType::handleScanFolderViewSelectionChanged);
|
||||||
|
|
||||||
connect(m_ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(applySettings(QAbstractButton*)));
|
connect(m_ui->buttonBox, &QDialogButtonBox::clicked, this, &OptionsDialog::applySettings);
|
||||||
// Languages supported
|
// Languages supported
|
||||||
initializeLanguageCombo();
|
initializeLanguageCombo();
|
||||||
|
|
||||||
@@ -258,7 +268,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
connect(m_ui->autoRunBox, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->autoRunBox, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->autoRun_txt, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->autoRun_txt, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
||||||
|
|
||||||
const QString autoRunStr = QString::fromUtf8("%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n%11")
|
const QString autoRunStr = QString("%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n%11")
|
||||||
.arg(tr("Supported parameters (case sensitive):"))
|
.arg(tr("Supported parameters (case sensitive):"))
|
||||||
.arg(tr("%N: Torrent name"))
|
.arg(tr("%N: Torrent name"))
|
||||||
.arg(tr("%L: Category"))
|
.arg(tr("%L: Category"))
|
||||||
@@ -350,6 +360,8 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
connect(m_ui->textWebUiUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->textWebUiUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->textWebUiPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->textWebUiPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->checkBypassLocalAuth, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkBypassLocalAuth, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
|
connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
|
connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, m_ui->IPSubnetWhitelistButton, &QPushButton::setEnabled);
|
||||||
connect(m_ui->checkDynDNS, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkDynDNS, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->comboDNSService, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->comboDNSService, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->domainNameTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->domainNameTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||||
@@ -442,25 +454,19 @@ void OptionsDialog::changePage(QListWidgetItem *current, QListWidgetItem *previo
|
|||||||
|
|
||||||
void OptionsDialog::loadWindowState()
|
void OptionsDialog::loadWindowState()
|
||||||
{
|
{
|
||||||
const Preferences* const pref = Preferences::instance();
|
Utils::Gui::resize(this, Preferences::instance()->getPrefSize());
|
||||||
|
|
||||||
resize(pref->getPrefSize(this->size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsDialog::loadSplitterState()
|
void OptionsDialog::loadSplitterState()
|
||||||
{
|
{
|
||||||
const Preferences* const pref = Preferences::instance();
|
const QStringList sizesStr = Preferences::instance()->getPrefHSplitterSizes();
|
||||||
|
|
||||||
const QStringList sizes_str = pref->getPrefHSplitterSizes();
|
// width has been modified, use height as width reference instead
|
||||||
QList<int> sizes;
|
const int width = Utils::Gui::scaledSize(this
|
||||||
if (sizes_str.size() == 2) {
|
, (m_ui->tabSelection->item(TAB_UI)->sizeHint().height() * 2));
|
||||||
sizes << sizes_str.first().toInt();
|
QList<int> sizes {width, (m_ui->hsplitter->width() - width)};
|
||||||
sizes << sizes_str.last().toInt();
|
if (sizesStr.size() == 2)
|
||||||
}
|
sizes = {sizesStr.first().toInt(), sizesStr.last().toInt()};
|
||||||
else {
|
|
||||||
sizes << 116;
|
|
||||||
sizes << m_ui->hsplitter->width() - 116;
|
|
||||||
}
|
|
||||||
m_ui->hsplitter->setSizes(sizes);
|
m_ui->hsplitter->setSizes(sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,7 +492,7 @@ void OptionsDialog::saveOptions()
|
|||||||
QString locale = getLocale();
|
QString locale = getLocale();
|
||||||
if (pref->getLocale() != locale) {
|
if (pref->getLocale() != locale) {
|
||||||
QTranslator *translator = new QTranslator;
|
QTranslator *translator = new QTranslator;
|
||||||
if (translator->load(QString::fromUtf8(":/lang/qbittorrent_") + locale))
|
if (translator->load(QLatin1String(":/lang/qbittorrent_") + locale))
|
||||||
qDebug("%s locale recognized, using translation.", qUtf8Printable(locale));
|
qDebug("%s locale recognized, using translation.", qUtf8Printable(locale));
|
||||||
else
|
else
|
||||||
qDebug("%s locale unrecognized, using default (en).", qUtf8Printable(locale));
|
qDebug("%s locale unrecognized, using default (en).", qUtf8Printable(locale));
|
||||||
@@ -531,7 +537,7 @@ void OptionsDialog::saveOptions()
|
|||||||
Application * const app = static_cast<Application*>(QCoreApplication::instance());
|
Application * const app = static_cast<Application*>(QCoreApplication::instance());
|
||||||
app->setFileLoggerPath(m_ui->textFileLogPath->selectedPath());
|
app->setFileLoggerPath(m_ui->textFileLogPath->selectedPath());
|
||||||
app->setFileLoggerBackup(m_ui->checkFileLogBackup->isChecked());
|
app->setFileLoggerBackup(m_ui->checkFileLogBackup->isChecked());
|
||||||
app->setFileLoggerMaxSize(m_ui->spinFileLogSize->value());
|
app->setFileLoggerMaxSize(m_ui->spinFileLogSize->value() * 1024);
|
||||||
app->setFileLoggerAge(m_ui->spinFileLogAge->value());
|
app->setFileLoggerAge(m_ui->spinFileLogAge->value());
|
||||||
app->setFileLoggerAgeType(m_ui->comboFileLogAgeType->currentIndex());
|
app->setFileLoggerAgeType(m_ui->comboFileLogAgeType->currentIndex());
|
||||||
app->setFileLoggerDeleteOld(m_ui->checkFileLogDelete->isChecked());
|
app->setFileLoggerDeleteOld(m_ui->checkFileLogDelete->isChecked());
|
||||||
@@ -655,13 +661,16 @@ void OptionsDialog::saveOptions()
|
|||||||
pref->setWebUiPort(m_ui->spinWebUiPort->value());
|
pref->setWebUiPort(m_ui->spinWebUiPort->value());
|
||||||
pref->setUPnPForWebUIPort(m_ui->checkWebUIUPnP->isChecked());
|
pref->setUPnPForWebUIPort(m_ui->checkWebUIUPnP->isChecked());
|
||||||
pref->setWebUiHttpsEnabled(m_ui->checkWebUiHttps->isChecked());
|
pref->setWebUiHttpsEnabled(m_ui->checkWebUiHttps->isChecked());
|
||||||
|
// HTTPS
|
||||||
if (m_ui->checkWebUiHttps->isChecked()) {
|
if (m_ui->checkWebUiHttps->isChecked()) {
|
||||||
pref->setWebUiHttpsCertificate(m_sslCert);
|
pref->setWebUiHttpsCertificate(m_sslCert);
|
||||||
pref->setWebUiHttpsKey(m_sslKey);
|
pref->setWebUiHttpsKey(m_sslKey);
|
||||||
}
|
}
|
||||||
|
// Authentication
|
||||||
pref->setWebUiUsername(webUiUsername());
|
pref->setWebUiUsername(webUiUsername());
|
||||||
pref->setWebUiPassword(webUiPassword());
|
pref->setWebUiPassword(webUiPassword());
|
||||||
pref->setWebUiLocalAuthEnabled(!m_ui->checkBypassLocalAuth->isChecked());
|
pref->setWebUiLocalAuthEnabled(!m_ui->checkBypassLocalAuth->isChecked());
|
||||||
|
pref->setWebUiAuthSubnetWhitelistEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
|
||||||
// DynDNS
|
// DynDNS
|
||||||
pref->setDynDNSEnabled(m_ui->checkDynDNS->isChecked());
|
pref->setDynDNSEnabled(m_ui->checkDynDNS->isChecked());
|
||||||
pref->setDynDNSService(m_ui->comboDNSService->currentIndex());
|
pref->setDynDNSService(m_ui->comboDNSService->currentIndex());
|
||||||
@@ -756,7 +765,7 @@ void OptionsDialog::loadOptions()
|
|||||||
m_ui->checkFileLogDelete->setChecked(fileLogDelete);
|
m_ui->checkFileLogDelete->setChecked(fileLogDelete);
|
||||||
m_ui->spinFileLogAge->setEnabled(fileLogDelete);
|
m_ui->spinFileLogAge->setEnabled(fileLogDelete);
|
||||||
m_ui->comboFileLogAgeType->setEnabled(fileLogDelete);
|
m_ui->comboFileLogAgeType->setEnabled(fileLogDelete);
|
||||||
m_ui->spinFileLogSize->setValue(app->fileLoggerMaxSize());
|
m_ui->spinFileLogSize->setValue(app->fileLoggerMaxSize() / 1024);
|
||||||
m_ui->spinFileLogAge->setValue(app->fileLoggerAge());
|
m_ui->spinFileLogAge->setValue(app->fileLoggerAge());
|
||||||
m_ui->comboFileLogAgeType->setCurrentIndex(app->fileLoggerAgeType());
|
m_ui->comboFileLogAgeType->setCurrentIndex(app->fileLoggerAgeType());
|
||||||
// End General preferences
|
// End General preferences
|
||||||
@@ -1052,6 +1061,8 @@ void OptionsDialog::loadOptions()
|
|||||||
m_ui->textWebUiUsername->setText(pref->getWebUiUsername());
|
m_ui->textWebUiUsername->setText(pref->getWebUiUsername());
|
||||||
m_ui->textWebUiPassword->setText(pref->getWebUiPassword());
|
m_ui->textWebUiPassword->setText(pref->getWebUiPassword());
|
||||||
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUiLocalAuthEnabled());
|
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUiLocalAuthEnabled());
|
||||||
|
m_ui->checkBypassAuthSubnetWhitelist->setChecked(pref->isWebUiAuthSubnetWhitelistEnabled());
|
||||||
|
m_ui->IPSubnetWhitelistButton->setEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
|
||||||
|
|
||||||
m_ui->checkDynDNS->setChecked(pref->isDynDNSEnabled());
|
m_ui->checkDynDNS->setChecked(pref->isDynDNSEnabled());
|
||||||
m_ui->comboDNSService->setCurrentIndex(static_cast<int>(pref->getDynDNSService()));
|
m_ui->comboDNSService->setCurrentIndex(static_cast<int>(pref->getDynDNSService()));
|
||||||
@@ -1570,7 +1581,7 @@ void OptionsDialog::on_IpFilterRefreshBtn_clicked()
|
|||||||
session->setIPFilteringEnabled(true);
|
session->setIPFilteringEnabled(true);
|
||||||
session->setIPFilterFile(""); // forcing Session reload filter file
|
session->setIPFilterFile(""); // forcing Session reload filter file
|
||||||
session->setIPFilterFile(getFilter());
|
session->setIPFilterFile(getFilter());
|
||||||
connect(session, SIGNAL(IPFilterParsed(bool, int)), SLOT(handleIPFilterParsed(bool, int)));
|
connect(session, &BitTorrent::Session::IPFilterParsed, this, &OptionsDialog::handleIPFilterParsed);
|
||||||
setCursor(QCursor(Qt::WaitCursor));
|
setCursor(QCursor(Qt::WaitCursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1582,7 +1593,7 @@ void OptionsDialog::handleIPFilterParsed(bool error, int ruleCount)
|
|||||||
else
|
else
|
||||||
QMessageBox::information(this, tr("Successfully refreshed"), tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount));
|
QMessageBox::information(this, tr("Successfully refreshed"), tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount));
|
||||||
m_refreshingIpFilter = false;
|
m_refreshingIpFilter = false;
|
||||||
disconnect(BitTorrent::Session::instance(), SIGNAL(IPFilterParsed(bool, int)), this, SLOT(handleIPFilterParsed(bool, int)));
|
disconnect(BitTorrent::Session::instance(), &BitTorrent::Session::IPFilterParsed, this, &OptionsDialog::handleIPFilterParsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OptionsDialog::languageToLocalizedString(const QLocale &locale)
|
QString OptionsDialog::languageToLocalizedString(const QLocale &locale)
|
||||||
@@ -1667,11 +1678,11 @@ bool OptionsDialog::setSslKey(const QByteArray &key)
|
|||||||
// try different formats
|
// try different formats
|
||||||
const bool isKeyValid = (!QSslKey(key, QSsl::Rsa).isNull() || !QSslKey(key, QSsl::Ec).isNull());
|
const bool isKeyValid = (!QSslKey(key, QSsl::Rsa).isNull() || !QSslKey(key, QSsl::Ec).isNull());
|
||||||
if (isKeyValid) {
|
if (isKeyValid) {
|
||||||
m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation));
|
m_ui->lblSslKeyStatus->setPixmap(Utils::Gui::scaledPixmap(":/icons/qbt-theme/security-high.png", this, 24));
|
||||||
m_sslKey = key;
|
m_sslKey = key;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation));
|
m_ui->lblSslKeyStatus->setPixmap(Utils::Gui::scaledPixmap(":/icons/qbt-theme/security-low.png", this, 24));
|
||||||
m_sslKey.clear();
|
m_sslKey.clear();
|
||||||
}
|
}
|
||||||
return isKeyValid;
|
return isKeyValid;
|
||||||
@@ -1686,11 +1697,11 @@ bool OptionsDialog::setSslCertificate(const QByteArray &cert)
|
|||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
const bool isCertValid = !QSslCertificate(cert).isNull();
|
const bool isCertValid = !QSslCertificate(cert).isNull();
|
||||||
if (isCertValid) {
|
if (isCertValid) {
|
||||||
m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation));
|
m_ui->lblSslCertStatus->setPixmap(Utils::Gui::scaledPixmap(":/icons/qbt-theme/security-high.png", this, 24));
|
||||||
m_sslCert = cert;
|
m_sslCert = cert;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation));
|
m_ui->lblSslCertStatus->setPixmap(Utils::Gui::scaledPixmap(":/icons/qbt-theme/security-low.png", this, 24));
|
||||||
m_sslCert.clear();
|
m_sslCert.clear();
|
||||||
}
|
}
|
||||||
return isCertValid;
|
return isCertValid;
|
||||||
@@ -1724,7 +1735,14 @@ bool OptionsDialog::webUIAuthenticationOk()
|
|||||||
|
|
||||||
void OptionsDialog::on_banListButton_clicked()
|
void OptionsDialog::on_banListButton_clicked()
|
||||||
{
|
{
|
||||||
//have to call dialog window
|
// call dialog window
|
||||||
BanListOptions bl(this);
|
if (BanListOptions(this).exec() == QDialog::Accepted)
|
||||||
bl.exec();
|
enableApplyButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsDialog::on_IPSubnetWhitelistButton_clicked()
|
||||||
|
{
|
||||||
|
// call dialog window
|
||||||
|
if (IPSubnetWhitelistOptionsDialog(this).exec() == QDialog::Accepted)
|
||||||
|
enableApplyButton();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ private slots:
|
|||||||
void on_IpFilterRefreshBtn_clicked();
|
void on_IpFilterRefreshBtn_clicked();
|
||||||
void handleIPFilterParsed(bool error, int ruleCount);
|
void handleIPFilterParsed(bool error, int ruleCount);
|
||||||
void on_banListButton_clicked();
|
void on_banListButton_clicked();
|
||||||
|
void on_IPSubnetWhitelistButton_clicked();
|
||||||
void on_randomButton_clicked();
|
void on_randomButton_clicked();
|
||||||
void on_addScanFolderButton_clicked();
|
void on_addScanFolderButton_clicked();
|
||||||
void on_removeScanFolderButton_clicked();
|
void on_removeScanFolderButton_clicked();
|
||||||
|
|||||||
@@ -535,16 +535,16 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="spinFileLogSize">
|
<widget class="QSpinBox" name="spinFileLogSize">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> MB</string>
|
<string> KiB</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>1000</number>
|
<number>1024000</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<number>10</number>
|
<number>65</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -1823,11 +1823,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" rowspan="2">
|
<item row="0" column="0" rowspan="2">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="labelGlobalRate"/>
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap resource="../icons.qrc">:/icons/slow_off.png</pixmap>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QCheckBox" name="checkDownloadLimit">
|
<widget class="QCheckBox" name="checkDownloadLimit">
|
||||||
@@ -1970,11 +1966,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" rowspan="2">
|
<item row="0" column="0" rowspan="2">
|
||||||
<widget class="QLabel" name="label_16">
|
<widget class="QLabel" name="labelAltRate"/>
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap resource="../icons.qrc">:/icons/slow.png</pixmap>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QCheckBox" name="checkUploadLimitAlt">
|
<widget class="QCheckBox" name="checkUploadLimitAlt">
|
||||||
@@ -2853,20 +2845,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
|||||||
<layout class="QGridLayout" name="gridLayout_11">
|
<layout class="QGridLayout" name="gridLayout_11">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="lblSslCertStatus">
|
<widget class="QLabel" name="lblSslCertStatus">
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>22</width>
|
|
||||||
<height>22</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>22</width>
|
|
||||||
<height>22</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -2906,20 +2886,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="lblSslKeyStatus">
|
<widget class="QLabel" name="lblSslKeyStatus">
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>22</width>
|
|
||||||
<height>22</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>22</width>
|
|
||||||
<height>22</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -3005,7 +2973,27 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
|||||||
<item row="4" column="0" colspan="2">
|
<item row="4" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBypassLocalAuth">
|
<widget class="QCheckBox" name="checkBypassLocalAuth">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bypass authentication for localhost</string>
|
<string>Bypass authentication for clients on localhost</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="checkBypassAuthSubnetWhitelist">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bypass authentication for clients in whitelisted IP subnets</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1" colspan="1">
|
||||||
|
<widget class="QPushButton" name="IPSubnetWhitelistButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>IP subnet whitelist...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -3289,6 +3277,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
|||||||
<tabstop>btnWebUiCrt</tabstop>
|
<tabstop>btnWebUiCrt</tabstop>
|
||||||
<tabstop>btnWebUiKey</tabstop>
|
<tabstop>btnWebUiKey</tabstop>
|
||||||
<tabstop>checkBypassLocalAuth</tabstop>
|
<tabstop>checkBypassLocalAuth</tabstop>
|
||||||
|
<tabstop>checkBypassAuthSubnetWhitelist</tabstop>
|
||||||
|
<tabstop>IPSubnetWhitelistButton</tabstop>
|
||||||
<tabstop>checkDynDNS</tabstop>
|
<tabstop>checkDynDNS</tabstop>
|
||||||
<tabstop>comboDNSService</tabstop>
|
<tabstop>comboDNSService</tabstop>
|
||||||
<tabstop>registerDNSBtn</tabstop>
|
<tabstop>registerDNSBtn</tabstop>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "previewlistdelegate.h"
|
#include "previewlistdelegate.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#define SETTINGS_KEY(name) "PreviewSelectDialog/" name
|
#define SETTINGS_KEY(name) "PreviewSelectDialog/" name
|
||||||
|
|
||||||
@@ -146,7 +147,7 @@ void PreviewSelectDialog::previewButtonClicked()
|
|||||||
void PreviewSelectDialog::saveWindowState()
|
void PreviewSelectDialog::saveWindowState()
|
||||||
{
|
{
|
||||||
// Persist dialog size
|
// Persist dialog size
|
||||||
m_storeDialogSize = this->size();
|
m_storeDialogSize = size();
|
||||||
// Persist TreeView Header state
|
// Persist TreeView Header state
|
||||||
m_storeTreeHeaderState = previewList->header()->saveState();
|
m_storeTreeHeaderState = previewList->header()->saveState();
|
||||||
}
|
}
|
||||||
@@ -154,9 +155,8 @@ void PreviewSelectDialog::saveWindowState()
|
|||||||
void PreviewSelectDialog::loadWindowState()
|
void PreviewSelectDialog::loadWindowState()
|
||||||
{
|
{
|
||||||
// Restore dialog size
|
// Restore dialog size
|
||||||
if (m_storeDialogSize.value().isValid()) {
|
Utils::Gui::resize(this, m_storeDialogSize);
|
||||||
resize(m_storeDialogSize);
|
|
||||||
}
|
|
||||||
// Restore TreeView Header state
|
// Restore TreeView Header state
|
||||||
if (!m_storeTreeHeaderState.value().isEmpty()) {
|
if (!m_storeTreeHeaderState.value().isEmpty()) {
|
||||||
m_headerStateInitialized = previewList->header()->restoreState(m_storeTreeHeaderState);
|
m_headerStateInitialized = previewList->header()->restoreState(m_storeTreeHeaderState);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "downloadedpiecesbar.h"
|
#include "downloadedpiecesbar.h"
|
||||||
@@ -127,24 +125,24 @@ bool DownloadedPiecesBar::updateImage(QImage &image)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<float> scaled_pieces = bitfieldToFloatVector(m_pieces, image2.width());
|
QVector<float> scaledPieces = bitfieldToFloatVector(m_pieces, image2.width());
|
||||||
QVector<float> scaled_pieces_dl = bitfieldToFloatVector(m_downloadedPieces, image2.width());
|
QVector<float> scaledPiecesDl = bitfieldToFloatVector(m_downloadedPieces, image2.width());
|
||||||
|
|
||||||
// filling image
|
// filling image
|
||||||
for (int x = 0; x < scaled_pieces.size(); ++x) {
|
for (int x = 0; x < scaledPieces.size(); ++x) {
|
||||||
float pieces2_val = scaled_pieces.at(x);
|
float piecesToValue = scaledPieces.at(x);
|
||||||
float pieces2_val_dl = scaled_pieces_dl.at(x);
|
float piecesToValueDl = scaledPiecesDl.at(x);
|
||||||
if (pieces2_val_dl != 0) {
|
if (piecesToValueDl != 0) {
|
||||||
float fill_ratio = pieces2_val + pieces2_val_dl;
|
float fillRatio = piecesToValue + piecesToValueDl;
|
||||||
float ratio = pieces2_val_dl / fill_ratio;
|
float ratio = piecesToValueDl / fillRatio;
|
||||||
|
|
||||||
QRgb mixedColor = mixTwoColors(pieceColor().rgb(), m_dlPieceColor.rgb(), ratio);
|
QRgb mixedColor = mixTwoColors(pieceColor().rgb(), m_dlPieceColor.rgb(), ratio);
|
||||||
mixedColor = mixTwoColors(backgroundColor().rgb(), mixedColor, fill_ratio);
|
mixedColor = mixTwoColors(backgroundColor().rgb(), mixedColor, fillRatio);
|
||||||
|
|
||||||
image2.setPixel(x, 0, mixedColor);
|
image2.setPixel(x, 0, mixedColor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
image2.setPixel(x, 0, pieceColors()[pieces2_val * 255]);
|
image2.setPixel(x, 0, pieceColors()[piecesToValue * 255]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
image = image2;
|
image = image2;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,20 +24,18 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DOWNLOADEDPIECESBAR_H
|
#ifndef DOWNLOADEDPIECESBAR_H
|
||||||
#define DOWNLOADEDPIECESBAR_H
|
#define DOWNLOADEDPIECESBAR_H
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
#include "piecesbar.h"
|
#include "piecesbar.h"
|
||||||
|
|
||||||
class DownloadedPiecesBar: public PiecesBar
|
class DownloadedPiecesBar : public PiecesBar
|
||||||
{
|
{
|
||||||
using base = PiecesBar;
|
using base = PiecesBar;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ public:
|
|||||||
COL_COUNT
|
COL_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
PeerListDelegate(QObject *parent) : QItemDelegate(parent) {}
|
PeerListDelegate(QObject *parent) : QItemDelegate(parent) {}
|
||||||
|
|
||||||
~PeerListDelegate() {}
|
~PeerListDelegate() {}
|
||||||
|
|||||||
@@ -50,13 +50,15 @@ protected:
|
|||||||
switch (sortColumn()) {
|
switch (sortColumn()) {
|
||||||
case PeerListDelegate::IP:
|
case PeerListDelegate::IP:
|
||||||
case PeerListDelegate::CLIENT: {
|
case PeerListDelegate::CLIENT: {
|
||||||
QString vL = left.data().toString();
|
const QString strL = left.data().toString();
|
||||||
QString vR = right.data().toString();
|
const QString strR = right.data().toString();
|
||||||
return Utils::String::naturalCompareCaseInsensitive(vL, vR);
|
const int result = Utils::String::naturalCompare(strL, strR, Qt::CaseInsensitive);
|
||||||
}
|
return (result < 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return QSortFilterProxyModel::lessThan(left, right);
|
||||||
};
|
};
|
||||||
|
|
||||||
return QSortFilterProxyModel::lessThan(left, right);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -180,10 +180,9 @@ void PeerListWidget::displayToggleColumnsMenu(const QPoint &)
|
|||||||
Q_ASSERT(visibleCols > 0);
|
Q_ASSERT(visibleCols > 0);
|
||||||
if (!isColumnHidden(col) && (visibleCols == 1))
|
if (!isColumnHidden(col) && (visibleCols == 1))
|
||||||
return;
|
return;
|
||||||
qDebug("Toggling column %d visibility", col);
|
|
||||||
setColumnHidden(col, !isColumnHidden(col));
|
setColumnHidden(col, !isColumnHidden(col));
|
||||||
if (!isColumnHidden(col) && (columnWidth(col) <= 5))
|
if (!isColumnHidden(col) && (columnWidth(col) <= 5))
|
||||||
setColumnWidth(col, 100);
|
resizeColumnToContents(col);
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,8 +230,8 @@ void PeerListWidget::showPeerListMenu(const QPoint &)
|
|||||||
addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer..."));
|
addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer..."));
|
||||||
emptyMenu = false;
|
emptyMenu = false;
|
||||||
}
|
}
|
||||||
QAction *banAct = 0;
|
QAction *banAct = nullptr;
|
||||||
QAction *copyPeerAct = 0;
|
QAction *copyPeerAct = nullptr;
|
||||||
if (!selectionModel()->selectedRows().isEmpty()) {
|
if (!selectionModel()->selectedRows().isEmpty()) {
|
||||||
copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy IP:port"));
|
copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy IP:port"));
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
@@ -241,7 +240,8 @@ void PeerListWidget::showPeerListMenu(const QPoint &)
|
|||||||
}
|
}
|
||||||
if (emptyMenu) return;
|
if (emptyMenu) return;
|
||||||
QAction *act = menu.exec(QCursor::pos());
|
QAction *act = menu.exec(QCursor::pos());
|
||||||
if (act == 0) return;
|
if (!act) return;
|
||||||
|
|
||||||
if (act == addPeerAct) {
|
if (act == addPeerAct) {
|
||||||
QList<BitTorrent::PeerAddress> peersList = PeersAdditionDlg::askForPeers(this);
|
QList<BitTorrent::PeerAddress> peersList = PeersAdditionDlg::askForPeers(this);
|
||||||
int peerCount = 0;
|
int peerCount = 0;
|
||||||
@@ -249,7 +249,7 @@ void PeerListWidget::showPeerListMenu(const QPoint &)
|
|||||||
if (torrent->connectPeer(addr)) {
|
if (torrent->connectPeer(addr)) {
|
||||||
qDebug("Adding peer %s...", qUtf8Printable(addr.ip.toString()));
|
qDebug("Adding peer %s...", qUtf8Printable(addr.ip.toString()));
|
||||||
Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString()));
|
Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString()));
|
||||||
peerCount++;
|
++peerCount;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Logger::instance()->addMessage(tr("The peer '%1' could not be added to this torrent.").arg(addr.ip.toString()), Log::WARNING);
|
Logger::instance()->addMessage(tr("The peer '%1' could not be added to this torrent.").arg(addr.ip.toString()), Log::WARNING);
|
||||||
@@ -277,8 +277,7 @@ void PeerListWidget::banSelectedPeers()
|
|||||||
int ret = QMessageBox::question(this, tr("Ban peer permanently"), tr("Are you sure you want to ban permanently the selected peers?"),
|
int ret = QMessageBox::question(this, tr("Ban peer permanently"), tr("Are you sure you want to ban permanently the selected peers?"),
|
||||||
tr("&Yes"), tr("&No"),
|
tr("&Yes"), tr("&No"),
|
||||||
QString(), 0, 1);
|
QString(), 0, 1);
|
||||||
if (ret)
|
if (ret) return;
|
||||||
return;
|
|
||||||
|
|
||||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||||
foreach (const QModelIndex &index, selectedIndexes) {
|
foreach (const QModelIndex &index, selectedIndexes) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,14 +24,12 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "peersadditiondlg.h"
|
#include "peersadditiondlg.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "ui_peersadditiondlg.h"
|
#include "ui_peersadditiondlg.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PEERADDITION_H
|
#ifndef PEERADDITION_H
|
||||||
@@ -42,7 +40,7 @@ namespace Ui
|
|||||||
class addPeersDialog;
|
class addPeersDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PeersAdditionDlg: public QDialog
|
class PeersAdditionDlg : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -60,7 +58,6 @@ private:
|
|||||||
|
|
||||||
Ui::addPeersDialog *m_ui;
|
Ui::addPeersDialog *m_ui;
|
||||||
QList<BitTorrent::PeerAddress> m_peersList;
|
QList<BitTorrent::PeerAddress> m_peersList;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PEERADDITION_H
|
#endif // PEERADDITION_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pieceavailabilitybar.h"
|
#include "pieceavailabilitybar.h"
|
||||||
@@ -134,12 +132,12 @@ bool PieceAvailabilityBar::updateImage(QImage &image)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<float> scaled_pieces = intToFloatVector(m_pieces, image2.width());
|
QVector<float> scaledPieces = intToFloatVector(m_pieces, image2.width());
|
||||||
|
|
||||||
// filling image
|
// filling image
|
||||||
for (int x = 0; x < scaled_pieces.size(); ++x) {
|
for (int x = 0; x < scaledPieces.size(); ++x) {
|
||||||
float pieces2_val = scaled_pieces.at(x);
|
float piecesToValue = scaledPieces.at(x);
|
||||||
image2.setPixel(x, 0, pieceColors()[pieces2_val * 255]);
|
image2.setPixel(x, 0, pieceColors()[piecesToValue * 255]);
|
||||||
}
|
}
|
||||||
image = image2;
|
image = image2;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PIECEAVAILABILITYBAR_H
|
#ifndef PIECEAVAILABILITYBAR_H
|
||||||
@@ -33,7 +31,7 @@
|
|||||||
|
|
||||||
#include "piecesbar.h"
|
#include "piecesbar.h"
|
||||||
|
|
||||||
class PieceAvailabilityBar: public PiecesBar
|
class PieceAvailabilityBar : public PiecesBar
|
||||||
{
|
{
|
||||||
using base = PiecesBar;
|
using base = PiecesBar;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace BitTorrent
|
|||||||
class TorrentHandle;
|
class TorrentHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PiecesBar: public QWidget
|
class PiecesBar : public QWidget
|
||||||
{
|
{
|
||||||
using base = QWidget;
|
using base = QWidget;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
@@ -1,33 +1,36 @@
|
|||||||
INCLUDEPATH += $$PWD
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
FORMS += $$PWD/propertieswidget.ui \
|
FORMS += \
|
||||||
$$PWD/trackersadditiondlg.ui \
|
$$PWD/peersadditiondlg.ui \
|
||||||
$$PWD/peersadditiondlg.ui
|
$$PWD/propertieswidget.ui \
|
||||||
|
$$PWD/trackersadditiondlg.ui
|
||||||
|
|
||||||
HEADERS += $$PWD/propertieswidget.h \
|
HEADERS += \
|
||||||
$$PWD/peerlistwidget.h \
|
$$PWD/downloadedpiecesbar.h \
|
||||||
$$PWD/proplistdelegate.h \
|
$$PWD/peerlistdelegate.h \
|
||||||
$$PWD/trackerlist.h \
|
$$PWD/peerlistsortmodel.h \
|
||||||
$$PWD/downloadedpiecesbar.h \
|
$$PWD/peerlistwidget.h \
|
||||||
$$PWD/peerlistdelegate.h \
|
$$PWD/peersadditiondlg.h \
|
||||||
$$PWD/peerlistsortmodel.h \
|
$$PWD/pieceavailabilitybar.h \
|
||||||
$$PWD/peersadditiondlg.h \
|
$$PWD/piecesbar.h \
|
||||||
$$PWD/trackersadditiondlg.h \
|
$$PWD/propertieswidget.h \
|
||||||
$$PWD/pieceavailabilitybar.h \
|
$$PWD/proplistdelegate.h \
|
||||||
$$PWD/proptabbar.h \
|
$$PWD/proptabbar.h \
|
||||||
$$PWD/speedwidget.h \
|
$$PWD/speedplotview.h \
|
||||||
$$PWD/speedplotview.h \
|
$$PWD/speedwidget.h \
|
||||||
$$PWD/piecesbar.h
|
$$PWD/trackerlist.h \
|
||||||
|
$$PWD/trackersadditiondlg.h
|
||||||
|
|
||||||
SOURCES += $$PWD/propertieswidget.cpp \
|
SOURCES += \
|
||||||
$$PWD/proplistdelegate.cpp \
|
$$PWD/downloadedpiecesbar.cpp \
|
||||||
$$PWD/peerlistwidget.cpp \
|
$$PWD/peerlistwidget.cpp \
|
||||||
$$PWD/trackerlist.cpp \
|
$$PWD/peersadditiondlg.cpp \
|
||||||
$$PWD/peersadditiondlg.cpp \
|
$$PWD/pieceavailabilitybar.cpp \
|
||||||
$$PWD/downloadedpiecesbar.cpp \
|
$$PWD/piecesbar.cpp \
|
||||||
$$PWD/trackersadditiondlg.cpp \
|
$$PWD/propertieswidget.cpp \
|
||||||
$$PWD/pieceavailabilitybar.cpp \
|
$$PWD/proplistdelegate.cpp \
|
||||||
$$PWD/proptabbar.cpp \
|
$$PWD/proptabbar.cpp \
|
||||||
$$PWD/speedwidget.cpp \
|
$$PWD/speedplotview.cpp \
|
||||||
$$PWD/speedplotview.cpp \
|
$$PWD/speedwidget.cpp \
|
||||||
$$PWD/piecesbar.cpp
|
$$PWD/trackerlist.cpp \
|
||||||
|
$$PWD/trackersadditiondlg.cpp
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "propertieswidget.h"
|
#include "propertieswidget.h"
|
||||||
@@ -64,89 +62,95 @@
|
|||||||
#include "torrentcontentmodel.h"
|
#include "torrentcontentmodel.h"
|
||||||
#include "trackerlist.h"
|
#include "trackerlist.h"
|
||||||
#include "transferlistwidget.h"
|
#include "transferlistwidget.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "ui_propertieswidget.h"
|
#include "ui_propertieswidget.h"
|
||||||
|
|
||||||
PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow *main_window, TransferListWidget *transferList)
|
#ifdef Q_OS_MAC
|
||||||
|
#include "macutilities.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow *mainWindow, TransferListWidget *transferList)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_ui(new Ui::PropertiesWidget())
|
, m_ui(new Ui::PropertiesWidget())
|
||||||
, transferList(transferList)
|
, m_transferList(transferList)
|
||||||
, main_window(main_window)
|
, m_mainWindow(mainWindow)
|
||||||
, m_torrent(nullptr)
|
, m_torrent(nullptr)
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
setAutoFillBackground(true);
|
setAutoFillBackground(true);
|
||||||
|
|
||||||
state = VISIBLE;
|
m_state = VISIBLE;
|
||||||
|
|
||||||
// Set Properties list model
|
// Set Properties list model
|
||||||
PropListModel = new TorrentContentFilterModel();
|
m_propListModel = new TorrentContentFilterModel();
|
||||||
m_ui->filesList->setModel(PropListModel);
|
m_ui->filesList->setModel(m_propListModel);
|
||||||
PropDelegate = new PropListDelegate(this);
|
m_propListDelegate = new PropListDelegate(this);
|
||||||
m_ui->filesList->setItemDelegate(PropDelegate);
|
m_ui->filesList->setItemDelegate(m_propListDelegate);
|
||||||
m_ui->filesList->setSortingEnabled(true);
|
m_ui->filesList->setSortingEnabled(true);
|
||||||
|
|
||||||
// Torrent content filtering
|
// Torrent content filtering
|
||||||
m_contentFilterLine = new LineEdit(this);
|
m_contentFilterLine = new LineEdit(this);
|
||||||
m_contentFilterLine->setPlaceholderText(tr("Filter files..."));
|
m_contentFilterLine->setPlaceholderText(tr("Filter files..."));
|
||||||
m_contentFilterLine->setMaximumSize(300, m_contentFilterLine->size().height());
|
m_contentFilterLine->setFixedWidth(Utils::Gui::scaledSize(this, 300));
|
||||||
connect(m_contentFilterLine, SIGNAL(textChanged(QString)), this, SLOT(filterText(QString)));
|
connect(m_contentFilterLine, SIGNAL(textChanged(QString)), this, SLOT(filterText(QString)));
|
||||||
m_ui->contentFilterLayout->insertWidget(3, m_contentFilterLine);
|
m_ui->contentFilterLayout->insertWidget(3, m_contentFilterLine);
|
||||||
|
|
||||||
// SIGNAL/SLOTS
|
// SIGNAL/SLOTS
|
||||||
connect(m_ui->filesList, SIGNAL(clicked(const QModelIndex&)), m_ui->filesList, SLOT(edit(const QModelIndex&)));
|
connect(m_ui->filesList, SIGNAL(clicked(const QModelIndex&)), m_ui->filesList, SLOT(edit(const QModelIndex&)));
|
||||||
connect(m_ui->selectAllButton, SIGNAL(clicked()), PropListModel, SLOT(selectAll()));
|
connect(m_ui->selectAllButton, SIGNAL(clicked()), m_propListModel, SLOT(selectAll()));
|
||||||
connect(m_ui->selectNoneButton, SIGNAL(clicked()), PropListModel, SLOT(selectNone()));
|
connect(m_ui->selectNoneButton, SIGNAL(clicked()), m_propListModel, SLOT(selectNone()));
|
||||||
connect(m_ui->filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&)));
|
connect(m_ui->filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&)));
|
||||||
connect(m_ui->filesList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(openDoubleClickedFile(const QModelIndex&)));
|
connect(m_ui->filesList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(openDoubleClickedFile(const QModelIndex&)));
|
||||||
connect(PropListModel, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
connect(m_propListModel, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
||||||
connect(m_ui->listWebSeeds, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayWebSeedListMenu(const QPoint&)));
|
connect(m_ui->listWebSeeds, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayWebSeedListMenu(const QPoint&)));
|
||||||
connect(transferList, SIGNAL(currentTorrentChanged(BitTorrent::TorrentHandle * const)), this, SLOT(loadTorrentInfos(BitTorrent::TorrentHandle * const)));
|
connect(transferList, SIGNAL(currentTorrentChanged(BitTorrent::TorrentHandle *const)), this, SLOT(loadTorrentInfos(BitTorrent::TorrentHandle *const)));
|
||||||
connect(PropDelegate, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
connect(m_propListDelegate, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
||||||
connect(m_ui->stackedProperties, SIGNAL(currentChanged(int)), this, SLOT(loadDynamicData()));
|
connect(m_ui->stackedProperties, SIGNAL(currentChanged(int)), this, SLOT(loadDynamicData()));
|
||||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentSavePathChanged(BitTorrent::TorrentHandle * const)), this, SLOT(updateSavePath(BitTorrent::TorrentHandle * const)));
|
connect(BitTorrent::Session::instance(), SIGNAL(torrentSavePathChanged(BitTorrent::TorrentHandle *const)), this, SLOT(updateSavePath(BitTorrent::TorrentHandle *const)));
|
||||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle * const)), this, SLOT(updateTorrentInfos(BitTorrent::TorrentHandle * const)));
|
connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle *const)), this, SLOT(updateTorrentInfos(BitTorrent::TorrentHandle *const)));
|
||||||
connect(m_ui->filesList->header(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(saveSettings()));
|
connect(m_ui->filesList->header(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(saveSettings()));
|
||||||
connect(m_ui->filesList->header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(saveSettings()));
|
connect(m_ui->filesList->header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(saveSettings()));
|
||||||
connect(m_ui->filesList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(saveSettings()));
|
connect(m_ui->filesList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(saveSettings()));
|
||||||
|
|
||||||
// set bar height relative to screen dpi
|
// set bar height relative to screen dpi
|
||||||
int barHeight = devicePixelRatio() * 18;
|
const int barHeight = Utils::Gui::scaledSize(this, 18);
|
||||||
|
|
||||||
// Downloaded pieces progress bar
|
// Downloaded pieces progress bar
|
||||||
m_ui->tempProgressBarArea->setVisible(false);
|
m_ui->tempProgressBarArea->setVisible(false);
|
||||||
downloaded_pieces = new DownloadedPiecesBar(this);
|
m_downloadedPieces = new DownloadedPiecesBar(this);
|
||||||
m_ui->groupBarLayout->addWidget(downloaded_pieces, 0, 1);
|
m_ui->groupBarLayout->addWidget(m_downloadedPieces, 0, 1);
|
||||||
downloaded_pieces->setFixedHeight(barHeight);
|
m_downloadedPieces->setFixedHeight(barHeight);
|
||||||
downloaded_pieces->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
m_downloadedPieces->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
|
||||||
// Pieces availability bar
|
// Pieces availability bar
|
||||||
m_ui->tempAvailabilityBarArea->setVisible(false);
|
m_ui->tempAvailabilityBarArea->setVisible(false);
|
||||||
pieces_availability = new PieceAvailabilityBar(this);
|
m_piecesAvailability = new PieceAvailabilityBar(this);
|
||||||
m_ui->groupBarLayout->addWidget(pieces_availability, 1, 1);
|
m_ui->groupBarLayout->addWidget(m_piecesAvailability, 1, 1);
|
||||||
pieces_availability->setFixedHeight(barHeight);
|
m_piecesAvailability->setFixedHeight(barHeight);
|
||||||
pieces_availability->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
m_piecesAvailability->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
|
||||||
// Tracker list
|
// Tracker list
|
||||||
trackerList = new TrackerList(this);
|
m_trackerList = new TrackerList(this);
|
||||||
m_ui->trackerUpButton->setIcon(GuiIconProvider::instance()->getIcon("go-up"));
|
m_ui->trackerUpButton->setIcon(GuiIconProvider::instance()->getIcon("go-up"));
|
||||||
m_ui->trackerUpButton->setIconSize(Utils::Misc::smallIconSize());
|
m_ui->trackerUpButton->setIconSize(Utils::Gui::smallIconSize());
|
||||||
m_ui->trackerDownButton->setIcon(GuiIconProvider::instance()->getIcon("go-down"));
|
m_ui->trackerDownButton->setIcon(GuiIconProvider::instance()->getIcon("go-down"));
|
||||||
m_ui->trackerDownButton->setIconSize(Utils::Misc::smallIconSize());
|
m_ui->trackerDownButton->setIconSize(Utils::Gui::smallIconSize());
|
||||||
connect(m_ui->trackerUpButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionUp()));
|
connect(m_ui->trackerUpButton, SIGNAL(clicked()), m_trackerList, SLOT(moveSelectionUp()));
|
||||||
connect(m_ui->trackerDownButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionDown()));
|
connect(m_ui->trackerDownButton, SIGNAL(clicked()), m_trackerList, SLOT(moveSelectionDown()));
|
||||||
m_ui->horizontalLayout_trackers->insertWidget(0, trackerList);
|
m_ui->horizontalLayout_trackers->insertWidget(0, m_trackerList);
|
||||||
connect(trackerList->header(), SIGNAL(sectionMoved(int,int,int)), trackerList, SLOT(saveSettings()));
|
connect(m_trackerList->header(), SIGNAL(sectionMoved(int,int,int)), m_trackerList, SLOT(saveSettings()));
|
||||||
connect(trackerList->header(), SIGNAL(sectionResized(int,int,int)), trackerList, SLOT(saveSettings()));
|
connect(m_trackerList->header(), SIGNAL(sectionResized(int,int,int)), m_trackerList, SLOT(saveSettings()));
|
||||||
connect(trackerList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), trackerList, SLOT(saveSettings()));
|
connect(m_trackerList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), m_trackerList, SLOT(saveSettings()));
|
||||||
// Peers list
|
// Peers list
|
||||||
peersList = new PeerListWidget(this);
|
m_peerList = new PeerListWidget(this);
|
||||||
m_ui->peerpage_layout->addWidget(peersList);
|
m_ui->peerpage_layout->addWidget(m_peerList);
|
||||||
connect(peersList->header(), SIGNAL(sectionMoved(int,int,int)), peersList, SLOT(saveSettings()));
|
connect(m_peerList->header(), SIGNAL(sectionMoved(int,int,int)), m_peerList, SLOT(saveSettings()));
|
||||||
connect(peersList->header(), SIGNAL(sectionResized(int,int,int)), peersList, SLOT(saveSettings()));
|
connect(m_peerList->header(), SIGNAL(sectionResized(int,int,int)), m_peerList, SLOT(saveSettings()));
|
||||||
connect(peersList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), peersList, SLOT(saveSettings()));
|
connect(m_peerList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), m_peerList, SLOT(saveSettings()));
|
||||||
// Speed widget
|
// Speed widget
|
||||||
speedWidget = new SpeedWidget(this);
|
m_speedWidget = new SpeedWidget(this);
|
||||||
m_ui->speed_layout->addWidget(speedWidget);
|
m_ui->speedLayout->addWidget(m_speedWidget);
|
||||||
// Tab bar
|
// Tab bar
|
||||||
m_tabBar = new PropTabBar();
|
m_tabBar = new PropTabBar();
|
||||||
m_tabBar->setContentsMargins(0, 5, 0, 0);
|
m_tabBar->setContentsMargins(0, 5, 0, 0);
|
||||||
@@ -156,79 +160,79 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow *main_window, Tra
|
|||||||
connect(m_tabBar, SIGNAL(visibilityToggled(bool)), SLOT(setVisibility(bool)));
|
connect(m_tabBar, SIGNAL(visibilityToggled(bool)), SLOT(setVisibility(bool)));
|
||||||
connect(m_tabBar, SIGNAL(visibilityToggled(bool)), this, SLOT(saveSettings()));
|
connect(m_tabBar, SIGNAL(visibilityToggled(bool)), this, SLOT(saveSettings()));
|
||||||
// Dynamic data refresher
|
// Dynamic data refresher
|
||||||
refreshTimer = new QTimer(this);
|
m_refreshTimer = new QTimer(this);
|
||||||
connect(refreshTimer, SIGNAL(timeout()), this, SLOT(loadDynamicData()));
|
connect(m_refreshTimer, SIGNAL(timeout()), this, SLOT(loadDynamicData()));
|
||||||
refreshTimer->start(3000); // 3sec
|
m_refreshTimer->start(3000); // 3sec
|
||||||
editHotkeyFile = new QShortcut(Qt::Key_F2, m_ui->filesList, 0, 0, Qt::WidgetShortcut);
|
m_editHotkeyFile = new QShortcut(Qt::Key_F2, m_ui->filesList, 0, 0, Qt::WidgetShortcut);
|
||||||
connect(editHotkeyFile, SIGNAL(activated()), SLOT(renameSelectedFile()));
|
connect(m_editHotkeyFile, SIGNAL(activated()), SLOT(renameSelectedFile()));
|
||||||
editHotkeyWeb = new QShortcut(Qt::Key_F2, m_ui->listWebSeeds, 0, 0, Qt::WidgetShortcut);
|
m_editHotkeyWeb = new QShortcut(Qt::Key_F2, m_ui->listWebSeeds, 0, 0, Qt::WidgetShortcut);
|
||||||
connect(editHotkeyWeb, SIGNAL(activated()), SLOT(editWebSeed()));
|
connect(m_editHotkeyWeb, SIGNAL(activated()), SLOT(editWebSeed()));
|
||||||
connect(m_ui->listWebSeeds, SIGNAL(doubleClicked(QModelIndex)), SLOT(editWebSeed()));
|
connect(m_ui->listWebSeeds, SIGNAL(doubleClicked(QModelIndex)), SLOT(editWebSeed()));
|
||||||
deleteHotkeyWeb = new QShortcut(QKeySequence::Delete, m_ui->listWebSeeds, 0, 0, Qt::WidgetShortcut);
|
m_deleteHotkeyWeb = new QShortcut(QKeySequence::Delete, m_ui->listWebSeeds, 0, 0, Qt::WidgetShortcut);
|
||||||
connect(deleteHotkeyWeb, SIGNAL(activated()), SLOT(deleteSelectedUrlSeeds()));
|
connect(m_deleteHotkeyWeb, SIGNAL(activated()), SLOT(deleteSelectedUrlSeeds()));
|
||||||
openHotkeyFile = new QShortcut(Qt::Key_Return, m_ui->filesList, 0, 0, Qt::WidgetShortcut);
|
m_openHotkeyFile = new QShortcut(Qt::Key_Return, m_ui->filesList, 0, 0, Qt::WidgetShortcut);
|
||||||
connect(openHotkeyFile, SIGNAL(activated()), SLOT(openSelectedFile()));
|
connect(m_openHotkeyFile, SIGNAL(activated()), SLOT(openSelectedFile()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertiesWidget::~PropertiesWidget()
|
PropertiesWidget::~PropertiesWidget()
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||||
delete refreshTimer;
|
delete m_refreshTimer;
|
||||||
delete trackerList;
|
delete m_trackerList;
|
||||||
delete peersList;
|
delete m_peerList;
|
||||||
delete speedWidget;
|
delete m_speedWidget;
|
||||||
delete downloaded_pieces;
|
delete m_downloadedPieces;
|
||||||
delete pieces_availability;
|
delete m_piecesAvailability;
|
||||||
delete PropListModel;
|
delete m_propListModel;
|
||||||
delete PropDelegate;
|
delete m_propListDelegate;
|
||||||
delete m_tabBar;
|
delete m_tabBar;
|
||||||
delete editHotkeyFile;
|
delete m_editHotkeyFile;
|
||||||
delete editHotkeyWeb;
|
delete m_editHotkeyWeb;
|
||||||
delete deleteHotkeyWeb;
|
delete m_deleteHotkeyWeb;
|
||||||
delete openHotkeyFile;
|
delete m_openHotkeyFile;
|
||||||
delete m_ui;
|
delete m_ui;
|
||||||
qDebug() << Q_FUNC_INFO << "EXIT";
|
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::showPiecesAvailability(bool show)
|
void PropertiesWidget::showPiecesAvailability(bool show)
|
||||||
{
|
{
|
||||||
m_ui->avail_pieces_lbl->setVisible(show);
|
m_ui->labelPiecesAvailability->setVisible(show);
|
||||||
pieces_availability->setVisible(show);
|
m_piecesAvailability->setVisible(show);
|
||||||
m_ui->avail_average_lbl->setVisible(show);
|
m_ui->labelAverageAvailabilityVal->setVisible(show);
|
||||||
if (show || !downloaded_pieces->isVisible())
|
if (show || !m_downloadedPieces->isVisible())
|
||||||
m_ui->line_2->setVisible(show);
|
m_ui->lineBelowBars->setVisible(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::showPiecesDownloaded(bool show)
|
void PropertiesWidget::showPiecesDownloaded(bool show)
|
||||||
{
|
{
|
||||||
m_ui->downloaded_pieces_lbl->setVisible(show);
|
m_ui->labelDownloadedPieces->setVisible(show);
|
||||||
downloaded_pieces->setVisible(show);
|
m_downloadedPieces->setVisible(show);
|
||||||
m_ui->progress_lbl->setVisible(show);
|
m_ui->labelProgressVal->setVisible(show);
|
||||||
if (show || !pieces_availability->isVisible())
|
if (show || !m_piecesAvailability->isVisible())
|
||||||
m_ui->line_2->setVisible(show);
|
m_ui->lineBelowBars->setVisible(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::setVisibility(bool visible)
|
void PropertiesWidget::setVisibility(bool visible)
|
||||||
{
|
{
|
||||||
if (!visible && (state == VISIBLE)) {
|
if (!visible && (m_state == VISIBLE)) {
|
||||||
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
||||||
m_ui->stackedProperties->setVisible(false);
|
m_ui->stackedProperties->setVisible(false);
|
||||||
slideSizes = hSplitter->sizes();
|
m_slideSizes = hSplitter->sizes();
|
||||||
hSplitter->handle(1)->setVisible(false);
|
hSplitter->handle(1)->setVisible(false);
|
||||||
hSplitter->handle(1)->setDisabled(true);
|
hSplitter->handle(1)->setDisabled(true);
|
||||||
QList<int> sizes = QList<int>() << hSplitter->geometry().height() - 30 << 30;
|
QList<int> sizes = QList<int>() << hSplitter->geometry().height() - 30 << 30;
|
||||||
hSplitter->setSizes(sizes);
|
hSplitter->setSizes(sizes);
|
||||||
state = REDUCED;
|
m_state = REDUCED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visible && (state == REDUCED)) {
|
if (visible && (m_state == REDUCED)) {
|
||||||
m_ui->stackedProperties->setVisible(true);
|
m_ui->stackedProperties->setVisible(true);
|
||||||
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
||||||
hSplitter->handle(1)->setDisabled(false);
|
hSplitter->handle(1)->setDisabled(false);
|
||||||
hSplitter->handle(1)->setVisible(true);
|
hSplitter->handle(1)->setVisible(true);
|
||||||
hSplitter->setSizes(slideSizes);
|
hSplitter->setSizes(m_slideSizes);
|
||||||
state = VISIBLE;
|
m_state = VISIBLE;
|
||||||
// Force refresh
|
// Force refresh
|
||||||
loadDynamicData();
|
loadDynamicData();
|
||||||
}
|
}
|
||||||
@@ -237,39 +241,39 @@ void PropertiesWidget::setVisibility(bool visible)
|
|||||||
void PropertiesWidget::clear()
|
void PropertiesWidget::clear()
|
||||||
{
|
{
|
||||||
qDebug("Clearing torrent properties");
|
qDebug("Clearing torrent properties");
|
||||||
m_ui->save_path->clear();
|
m_ui->labelSavePathVal->clear();
|
||||||
m_ui->lbl_creationDate->clear();
|
m_ui->labelCreatedOnVal->clear();
|
||||||
m_ui->label_total_pieces_val->clear();
|
m_ui->labelTotalPiecesVal->clear();
|
||||||
m_ui->hash_lbl->clear();
|
m_ui->labelHashVal->clear();
|
||||||
m_ui->comment_text->clear();
|
m_ui->labelCommentVal->clear();
|
||||||
m_ui->progress_lbl->clear();
|
m_ui->labelProgressVal->clear();
|
||||||
trackerList->clear();
|
m_ui->labelAverageAvailabilityVal->clear();
|
||||||
downloaded_pieces->clear();
|
m_ui->labelWastedVal->clear();
|
||||||
pieces_availability->clear();
|
m_ui->labelUpTotalVal->clear();
|
||||||
m_ui->avail_average_lbl->clear();
|
m_ui->labelDlTotalVal->clear();
|
||||||
m_ui->wasted->clear();
|
m_ui->labelUpLimitVal->clear();
|
||||||
m_ui->upTotal->clear();
|
m_ui->labelDlLimitVal->clear();
|
||||||
m_ui->dlTotal->clear();
|
m_ui->labelElapsedVal->clear();
|
||||||
peersList->clear();
|
m_ui->labelConnectionsVal->clear();
|
||||||
m_ui->lbl_uplimit->clear();
|
m_ui->labelReannounceInVal->clear();
|
||||||
m_ui->lbl_dllimit->clear();
|
m_ui->labelShareRatioVal->clear();
|
||||||
m_ui->lbl_elapsed->clear();
|
|
||||||
m_ui->lbl_connections->clear();
|
|
||||||
m_ui->reannounce_lbl->clear();
|
|
||||||
m_ui->shareRatio->clear();
|
|
||||||
m_ui->listWebSeeds->clear();
|
m_ui->listWebSeeds->clear();
|
||||||
|
m_ui->labelETAVal->clear();
|
||||||
|
m_ui->labelSeedsVal->clear();
|
||||||
|
m_ui->labelPeersVal->clear();
|
||||||
|
m_ui->labelDlSpeedVal->clear();
|
||||||
|
m_ui->labelUpSpeedVal->clear();
|
||||||
|
m_ui->labelTotalSizeVal->clear();
|
||||||
|
m_ui->labelCompletedOnVal->clear();
|
||||||
|
m_ui->labelLastSeenCompleteVal->clear();
|
||||||
|
m_ui->labelCreatedByVal->clear();
|
||||||
|
m_ui->labelAddedOnVal->clear();
|
||||||
|
m_trackerList->clear();
|
||||||
|
m_downloadedPieces->clear();
|
||||||
|
m_piecesAvailability->clear();
|
||||||
|
m_peerList->clear();
|
||||||
m_contentFilterLine->clear();
|
m_contentFilterLine->clear();
|
||||||
PropListModel->model()->clear();
|
m_propListModel->model()->clear();
|
||||||
m_ui->label_eta_val->clear();
|
|
||||||
m_ui->label_seeds_val->clear();
|
|
||||||
m_ui->label_peers_val->clear();
|
|
||||||
m_ui->label_dl_speed_val->clear();
|
|
||||||
m_ui->label_upload_speed_val->clear();
|
|
||||||
m_ui->label_total_size_val->clear();
|
|
||||||
m_ui->label_completed_on_val->clear();
|
|
||||||
m_ui->label_last_complete_val->clear();
|
|
||||||
m_ui->label_created_by_val->clear();
|
|
||||||
m_ui->label_added_on_val->clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitTorrent::TorrentHandle *PropertiesWidget::getCurrentTorrent() const
|
BitTorrent::TorrentHandle *PropertiesWidget::getCurrentTorrent() const
|
||||||
@@ -277,26 +281,41 @@ BitTorrent::TorrentHandle *PropertiesWidget::getCurrentTorrent() const
|
|||||||
return m_torrent;
|
return m_torrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrackerList *PropertiesWidget::getTrackerList() const
|
||||||
|
{
|
||||||
|
return m_trackerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerListWidget *PropertiesWidget::getPeerList() const
|
||||||
|
{
|
||||||
|
return m_peerList;
|
||||||
|
}
|
||||||
|
|
||||||
QTreeView *PropertiesWidget::getFilesList() const
|
QTreeView *PropertiesWidget::getFilesList() const
|
||||||
{
|
{
|
||||||
return m_ui->filesList;
|
return m_ui->filesList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpeedWidget *PropertiesWidget::getSpeedWidget() const
|
||||||
|
{
|
||||||
|
return m_speedWidget;
|
||||||
|
}
|
||||||
|
|
||||||
void PropertiesWidget::updateSavePath(BitTorrent::TorrentHandle *const torrent)
|
void PropertiesWidget::updateSavePath(BitTorrent::TorrentHandle *const torrent)
|
||||||
{
|
{
|
||||||
if (m_torrent == torrent)
|
if (torrent == m_torrent)
|
||||||
m_ui->save_path->setText(Utils::Fs::toNativePath(m_torrent->savePath()));
|
m_ui->labelSavePathVal->setText(Utils::Fs::toNativePath(m_torrent->savePath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::loadTrackers(BitTorrent::TorrentHandle *const torrent)
|
void PropertiesWidget::loadTrackers(BitTorrent::TorrentHandle *const torrent)
|
||||||
{
|
{
|
||||||
if (torrent == m_torrent)
|
if (torrent == m_torrent)
|
||||||
trackerList->loadTrackers();
|
m_trackerList->loadTrackers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::updateTorrentInfos(BitTorrent::TorrentHandle *const torrent)
|
void PropertiesWidget::updateTorrentInfos(BitTorrent::TorrentHandle *const torrent)
|
||||||
{
|
{
|
||||||
if (m_torrent == torrent)
|
if (torrent == m_torrent)
|
||||||
loadTorrentInfos(m_torrent);
|
loadTorrentInfos(m_torrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,36 +323,36 @@ void PropertiesWidget::loadTorrentInfos(BitTorrent::TorrentHandle *const torrent
|
|||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
m_torrent = torrent;
|
m_torrent = torrent;
|
||||||
downloaded_pieces->setTorrent(m_torrent);
|
m_downloadedPieces->setTorrent(m_torrent);
|
||||||
pieces_availability->setTorrent(m_torrent);
|
m_piecesAvailability->setTorrent(m_torrent);
|
||||||
if (!m_torrent) return;
|
if (!m_torrent) return;
|
||||||
|
|
||||||
// Save path
|
// Save path
|
||||||
updateSavePath(m_torrent);
|
updateSavePath(m_torrent);
|
||||||
// Hash
|
// Hash
|
||||||
m_ui->hash_lbl->setText(m_torrent->hash());
|
m_ui->labelHashVal->setText(m_torrent->hash());
|
||||||
PropListModel->model()->clear();
|
m_propListModel->model()->clear();
|
||||||
if (m_torrent->hasMetadata()) {
|
if (m_torrent->hasMetadata()) {
|
||||||
// Creation date
|
// Creation date
|
||||||
m_ui->lbl_creationDate->setText(m_torrent->creationDate().toString(Qt::DefaultLocaleShortDate));
|
m_ui->labelCreatedOnVal->setText(m_torrent->creationDate().toString(Qt::DefaultLocaleShortDate));
|
||||||
|
|
||||||
m_ui->label_total_size_val->setText(Utils::Misc::friendlyUnit(m_torrent->totalSize()));
|
m_ui->labelTotalSizeVal->setText(Utils::Misc::friendlyUnit(m_torrent->totalSize()));
|
||||||
|
|
||||||
// Comment
|
// Comment
|
||||||
m_ui->comment_text->setText(Utils::Misc::parseHtmlLinks(m_torrent->comment().toHtmlEscaped()));
|
m_ui->labelCommentVal->setText(Utils::Misc::parseHtmlLinks(m_torrent->comment().toHtmlEscaped()));
|
||||||
|
|
||||||
// URL seeds
|
// URL seeds
|
||||||
loadUrlSeeds();
|
loadUrlSeeds();
|
||||||
|
|
||||||
m_ui->label_created_by_val->setText(m_torrent->creator().toHtmlEscaped());
|
m_ui->labelCreatedByVal->setText(m_torrent->creator().toHtmlEscaped());
|
||||||
|
|
||||||
// List files in torrent
|
// List files in torrent
|
||||||
PropListModel->model()->setupModelData(m_torrent->info());
|
m_propListModel->model()->setupModelData(m_torrent->info());
|
||||||
if (PropListModel->model()->rowCount() == 1)
|
if (m_propListModel->model()->rowCount() == 1)
|
||||||
m_ui->filesList->setExpanded(PropListModel->index(0, 0), true);
|
m_ui->filesList->setExpanded(m_propListModel->index(0, 0), true);
|
||||||
|
|
||||||
// Load file priorities
|
// Load file priorities
|
||||||
PropListModel->model()->updateFilesPriorities(m_torrent->filePriorities());
|
m_propListModel->model()->updateFilesPriorities(m_torrent->filePriorities());
|
||||||
}
|
}
|
||||||
// Load dynamic data
|
// Load dynamic data
|
||||||
loadDynamicData();
|
loadDynamicData();
|
||||||
@@ -343,18 +362,16 @@ void PropertiesWidget::readSettings()
|
|||||||
{
|
{
|
||||||
const Preferences *const pref = Preferences::instance();
|
const Preferences *const pref = Preferences::instance();
|
||||||
// Restore splitter sizes
|
// Restore splitter sizes
|
||||||
QStringList sizes_str = pref->getPropSplitterSizes().split(",");
|
QStringList sizesStr = pref->getPropSplitterSizes().split(",");
|
||||||
if (sizes_str.size() == 2) {
|
if (sizesStr.size() == 2) {
|
||||||
slideSizes << sizes_str.first().toInt();
|
m_slideSizes << sizesStr.first().toInt();
|
||||||
slideSizes << sizes_str.last().toInt();
|
m_slideSizes << sizesStr.last().toInt();
|
||||||
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
||||||
hSplitter->setSizes(slideSizes);
|
hSplitter->setSizes(m_slideSizes);
|
||||||
}
|
}
|
||||||
const int current_tab = pref->getPropCurTab();
|
const int current_tab = pref->getPropCurTab();
|
||||||
const bool visible = pref->getPropVisible();
|
const bool visible = pref->getPropVisible();
|
||||||
// the following will call saveSettings but shouldn't change any state
|
m_ui->filesList->header()->restoreState(pref->getPropFileListState());
|
||||||
if (!m_ui->filesList->header()->restoreState(pref->getPropFileListState()))
|
|
||||||
m_ui->filesList->header()->resizeSection(0, 400); // Default
|
|
||||||
m_tabBar->setCurrentIndex(current_tab);
|
m_tabBar->setCurrentIndex(current_tab);
|
||||||
if (!visible)
|
if (!visible)
|
||||||
setVisibility(false);
|
setVisibility(false);
|
||||||
@@ -363,14 +380,14 @@ void PropertiesWidget::readSettings()
|
|||||||
void PropertiesWidget::saveSettings()
|
void PropertiesWidget::saveSettings()
|
||||||
{
|
{
|
||||||
Preferences *const pref = Preferences::instance();
|
Preferences *const pref = Preferences::instance();
|
||||||
pref->setPropVisible(state == VISIBLE);
|
pref->setPropVisible(m_state == VISIBLE);
|
||||||
// Splitter sizes
|
// Splitter sizes
|
||||||
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
QSplitter *hSplitter = static_cast<QSplitter *>(parentWidget());
|
||||||
QList<int> sizes;
|
QList<int> sizes;
|
||||||
if (state == VISIBLE)
|
if (m_state == VISIBLE)
|
||||||
sizes = hSplitter->sizes();
|
sizes = hSplitter->sizes();
|
||||||
else
|
else
|
||||||
sizes = slideSizes;
|
sizes = m_slideSizes;
|
||||||
qDebug("Sizes: %d", sizes.size());
|
qDebug("Sizes: %d", sizes.size());
|
||||||
if (sizes.size() == 2)
|
if (sizes.size() == 2)
|
||||||
pref->setPropSplitterSizes(QString::number(sizes.first()) + ',' + QString::number(sizes.last()));
|
pref->setPropSplitterSizes(QString::number(sizes.first()) + ',' + QString::number(sizes.last()));
|
||||||
@@ -382,118 +399,112 @@ void PropertiesWidget::saveSettings()
|
|||||||
void PropertiesWidget::reloadPreferences()
|
void PropertiesWidget::reloadPreferences()
|
||||||
{
|
{
|
||||||
// Take program preferences into consideration
|
// Take program preferences into consideration
|
||||||
peersList->updatePeerHostNameResolutionState();
|
m_peerList->updatePeerHostNameResolutionState();
|
||||||
peersList->updatePeerCountryResolutionState();
|
m_peerList->updatePeerCountryResolutionState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::loadDynamicData()
|
void PropertiesWidget::loadDynamicData()
|
||||||
{
|
{
|
||||||
// Refresh only if the torrent handle is valid and if visible
|
// Refresh only if the torrent handle is valid and visible
|
||||||
if (!m_torrent || (main_window->currentTabWidget() != transferList) || (state != VISIBLE)) return;
|
if (!m_torrent || (m_mainWindow->currentTabWidget() != m_transferList) || (m_state != VISIBLE)) return;
|
||||||
|
|
||||||
// Transfer infos
|
// Transfer infos
|
||||||
switch (m_ui->stackedProperties->currentIndex()) {
|
switch (m_ui->stackedProperties->currentIndex()) {
|
||||||
case PropTabBar::MAIN_TAB: {
|
case PropTabBar::MainTab: {
|
||||||
m_ui->wasted->setText(Utils::Misc::friendlyUnit(m_torrent->wastedSize()));
|
m_ui->labelWastedVal->setText(Utils::Misc::friendlyUnit(m_torrent->wastedSize()));
|
||||||
|
|
||||||
m_ui->upTotal->setText(tr("%1 (%2 this session)").arg(Utils::Misc::friendlyUnit(m_torrent->totalUpload()))
|
m_ui->labelUpTotalVal->setText(tr("%1 (%2 this session)").arg(Utils::Misc::friendlyUnit(m_torrent->totalUpload()))
|
||||||
.arg(Utils::Misc::friendlyUnit(m_torrent->totalPayloadUpload())));
|
.arg(Utils::Misc::friendlyUnit(m_torrent->totalPayloadUpload())));
|
||||||
|
|
||||||
m_ui->dlTotal->setText(tr("%1 (%2 this session)").arg(Utils::Misc::friendlyUnit(m_torrent->totalDownload()))
|
m_ui->labelDlTotalVal->setText(tr("%1 (%2 this session)").arg(Utils::Misc::friendlyUnit(m_torrent->totalDownload()))
|
||||||
.arg(Utils::Misc::friendlyUnit(m_torrent->totalPayloadDownload())));
|
.arg(Utils::Misc::friendlyUnit(m_torrent->totalPayloadDownload())));
|
||||||
|
|
||||||
m_ui->lbl_uplimit->setText(m_torrent->uploadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->uploadLimit(), true));
|
m_ui->labelUpLimitVal->setText(m_torrent->uploadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->uploadLimit(), true));
|
||||||
|
|
||||||
m_ui->lbl_dllimit->setText(m_torrent->downloadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->downloadLimit(), true));
|
m_ui->labelDlLimitVal->setText(m_torrent->downloadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->downloadLimit(), true));
|
||||||
|
|
||||||
QString elapsed_txt;
|
QString elapsedString;
|
||||||
if (m_torrent->isSeed())
|
if (m_torrent->isSeed())
|
||||||
elapsed_txt = tr("%1 (seeded for %2)", "e.g. 4m39s (seeded for 3m10s)")
|
elapsedString = tr("%1 (seeded for %2)", "e.g. 4m39s (seeded for 3m10s)")
|
||||||
.arg(Utils::Misc::userFriendlyDuration(m_torrent->activeTime()))
|
.arg(Utils::Misc::userFriendlyDuration(m_torrent->activeTime()))
|
||||||
.arg(Utils::Misc::userFriendlyDuration(m_torrent->seedingTime()));
|
.arg(Utils::Misc::userFriendlyDuration(m_torrent->seedingTime()));
|
||||||
else
|
else
|
||||||
elapsed_txt = Utils::Misc::userFriendlyDuration(m_torrent->activeTime());
|
elapsedString = Utils::Misc::userFriendlyDuration(m_torrent->activeTime());
|
||||||
m_ui->lbl_elapsed->setText(elapsed_txt);
|
m_ui->labelElapsedVal->setText(elapsedString);
|
||||||
|
|
||||||
m_ui->lbl_connections->setText(tr("%1 (%2 max)", "%1 and %2 are numbers, e.g. 3 (10 max)")
|
m_ui->labelConnectionsVal->setText(tr("%1 (%2 max)", "%1 and %2 are numbers, e.g. 3 (10 max)")
|
||||||
.arg(m_torrent->connectionsCount())
|
.arg(m_torrent->connectionsCount())
|
||||||
.arg(m_torrent->connectionsLimit() < 0 ? QString::fromUtf8(C_INFINITY) : QString::number(m_torrent->connectionsLimit())));
|
.arg(m_torrent->connectionsLimit() < 0 ? QString::fromUtf8(C_INFINITY) : QString::number(m_torrent->connectionsLimit())));
|
||||||
|
|
||||||
m_ui->label_eta_val->setText(Utils::Misc::userFriendlyDuration(m_torrent->eta()));
|
m_ui->labelETAVal->setText(Utils::Misc::userFriendlyDuration(m_torrent->eta()));
|
||||||
|
|
||||||
// Update next announce time
|
// Update next announce time
|
||||||
m_ui->reannounce_lbl->setText(Utils::Misc::userFriendlyDuration(m_torrent->nextAnnounce()));
|
m_ui->labelReannounceInVal->setText(Utils::Misc::userFriendlyDuration(m_torrent->nextAnnounce()));
|
||||||
|
|
||||||
// Update ratio info
|
// Update ratio info
|
||||||
const qreal ratio = m_torrent->realRatio();
|
const qreal ratio = m_torrent->realRatio();
|
||||||
m_ui->shareRatio->setText(ratio > BitTorrent::TorrentHandle::MAX_RATIO ? QString::fromUtf8(C_INFINITY) : Utils::String::fromDouble(ratio, 2));
|
m_ui->labelShareRatioVal->setText(ratio > BitTorrent::TorrentHandle::MAX_RATIO ? QString::fromUtf8(C_INFINITY) : Utils::String::fromDouble(ratio, 2));
|
||||||
|
|
||||||
m_ui->label_seeds_val->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)")
|
m_ui->labelSeedsVal->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)")
|
||||||
.arg(QString::number(m_torrent->seedsCount()))
|
.arg(QString::number(m_torrent->seedsCount()))
|
||||||
.arg(QString::number(m_torrent->totalSeedsCount())));
|
.arg(QString::number(m_torrent->totalSeedsCount())));
|
||||||
|
|
||||||
m_ui->label_peers_val->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)")
|
m_ui->labelPeersVal->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)")
|
||||||
.arg(QString::number(m_torrent->leechsCount()))
|
.arg(QString::number(m_torrent->leechsCount()))
|
||||||
.arg(QString::number(m_torrent->totalLeechersCount())));
|
.arg(QString::number(m_torrent->totalLeechersCount())));
|
||||||
|
|
||||||
m_ui->label_dl_speed_val->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)")
|
m_ui->labelDlSpeedVal->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)")
|
||||||
.arg(Utils::Misc::friendlyUnit(m_torrent->downloadPayloadRate(), true))
|
.arg(Utils::Misc::friendlyUnit(m_torrent->downloadPayloadRate(), true))
|
||||||
.arg(Utils::Misc::friendlyUnit(m_torrent->totalDownload() / (1 + m_torrent->activeTime() - m_torrent->finishedTime()), true)));
|
.arg(Utils::Misc::friendlyUnit(m_torrent->totalDownload() / (1 + m_torrent->activeTime() - m_torrent->finishedTime()), true)));
|
||||||
|
|
||||||
m_ui->label_upload_speed_val->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)")
|
m_ui->labelUpSpeedVal->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)")
|
||||||
.arg(Utils::Misc::friendlyUnit(m_torrent->uploadPayloadRate(), true))
|
.arg(Utils::Misc::friendlyUnit(m_torrent->uploadPayloadRate(), true))
|
||||||
.arg(Utils::Misc::friendlyUnit(m_torrent->totalUpload() / (1 + m_torrent->activeTime()), true)));
|
.arg(Utils::Misc::friendlyUnit(m_torrent->totalUpload() / (1 + m_torrent->activeTime()), true)));
|
||||||
|
|
||||||
m_ui->label_last_complete_val->setText(m_torrent->lastSeenComplete().isValid() ? m_torrent->lastSeenComplete().toString(Qt::DefaultLocaleShortDate) : tr("Never"));
|
m_ui->labelLastSeenCompleteVal->setText(m_torrent->lastSeenComplete().isValid() ? m_torrent->lastSeenComplete().toString(Qt::DefaultLocaleShortDate) : tr("Never"));
|
||||||
|
|
||||||
m_ui->label_completed_on_val->setText(m_torrent->completedTime().isValid() ? m_torrent->completedTime().toString(Qt::DefaultLocaleShortDate) : "");
|
m_ui->labelCompletedOnVal->setText(m_torrent->completedTime().isValid() ? m_torrent->completedTime().toString(Qt::DefaultLocaleShortDate) : "");
|
||||||
|
|
||||||
m_ui->label_added_on_val->setText(m_torrent->addedTime().toString(Qt::DefaultLocaleShortDate));
|
m_ui->labelAddedOnVal->setText(m_torrent->addedTime().toString(Qt::DefaultLocaleShortDate));
|
||||||
|
|
||||||
if (m_torrent->hasMetadata()) {
|
if (m_torrent->hasMetadata()) {
|
||||||
m_ui->label_total_pieces_val->setText(tr("%1 x %2 (have %3)", "(torrent pieces) eg 152 x 4MB (have 25)").arg(m_torrent->piecesCount()).arg(Utils::Misc::friendlyUnit(m_torrent->pieceLength())).arg(m_torrent->piecesHave()));
|
m_ui->labelTotalPiecesVal->setText(tr("%1 x %2 (have %3)", "(torrent pieces) eg 152 x 4MB (have 25)").arg(m_torrent->piecesCount()).arg(Utils::Misc::friendlyUnit(m_torrent->pieceLength())).arg(m_torrent->piecesHave()));
|
||||||
|
|
||||||
if (!m_torrent->isSeed() && !m_torrent->isPaused() && !m_torrent->isQueued() && !m_torrent->isChecking()) {
|
if (!m_torrent->isSeed() && !m_torrent->isPaused() && !m_torrent->isQueued() && !m_torrent->isChecking()) {
|
||||||
// Pieces availability
|
// Pieces availability
|
||||||
showPiecesAvailability(true);
|
showPiecesAvailability(true);
|
||||||
pieces_availability->setAvailability(m_torrent->pieceAvailability());
|
m_piecesAvailability->setAvailability(m_torrent->pieceAvailability());
|
||||||
m_ui->avail_average_lbl->setText(Utils::String::fromDouble(m_torrent->distributedCopies(), 3));
|
m_ui->labelAverageAvailabilityVal->setText(Utils::String::fromDouble(m_torrent->distributedCopies(), 3));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showPiecesAvailability(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress
|
||||||
|
qreal progress = m_torrent->progress() * 100.;
|
||||||
|
m_ui->labelProgressVal->setText(Utils::String::fromDouble(progress, 1) + "%");
|
||||||
|
m_downloadedPieces->setProgress(m_torrent->pieces(), m_torrent->downloadingPieces());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showPiecesAvailability(false);
|
showPiecesAvailability(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Progress
|
|
||||||
qreal progress = m_torrent->progress() * 100.;
|
|
||||||
m_ui->progress_lbl->setText(Utils::String::fromDouble(progress, 1) + "%");
|
|
||||||
downloaded_pieces->setProgress(m_torrent->pieces(), m_torrent->downloadingPieces());
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
showPiecesAvailability(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
case PropTabBar::TrackersTab:
|
||||||
|
|
||||||
case PropTabBar::TRACKERS_TAB: {
|
|
||||||
// Trackers
|
// Trackers
|
||||||
trackerList->loadTrackers();
|
m_trackerList->loadTrackers();
|
||||||
break;
|
break;
|
||||||
}
|
case PropTabBar::PeersTab:
|
||||||
|
|
||||||
case PropTabBar::PEERS_TAB: {
|
|
||||||
// Load peers
|
// Load peers
|
||||||
peersList->loadPeers(m_torrent);
|
m_peerList->loadPeers(m_torrent);
|
||||||
break;
|
break;
|
||||||
}
|
case PropTabBar::FilesTab:
|
||||||
|
|
||||||
case PropTabBar::FILES_TAB: {
|
|
||||||
// Files progress
|
// Files progress
|
||||||
if (m_torrent->hasMetadata()) {
|
if (m_torrent->hasMetadata()) {
|
||||||
qDebug("Updating priorities in files tab");
|
qDebug("Updating priorities in files tab");
|
||||||
m_ui->filesList->setUpdatesEnabled(false);
|
m_ui->filesList->setUpdatesEnabled(false);
|
||||||
PropListModel->model()->updateFilesProgress(m_torrent->filesProgress());
|
m_propListModel->model()->updateFilesProgress(m_torrent->filesProgress());
|
||||||
PropListModel->model()->updateFilesAvailability(m_torrent->availableFileFractions());
|
m_propListModel->model()->updateFilesAvailability(m_torrent->availableFileFractions());
|
||||||
// XXX: We don't update file priorities regularly for performance
|
// XXX: We don't update file priorities regularly for performance
|
||||||
// reasons. This means that priorities will not be updated if
|
// reasons. This means that priorities will not be updated if
|
||||||
// set from the Web UI.
|
// set from the Web UI.
|
||||||
@@ -501,8 +512,6 @@ void PropertiesWidget::loadDynamicData()
|
|||||||
m_ui->filesList->setUpdatesEnabled(true);
|
m_ui->filesList->setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -511,19 +520,19 @@ void PropertiesWidget::loadUrlSeeds()
|
|||||||
{
|
{
|
||||||
m_ui->listWebSeeds->clear();
|
m_ui->listWebSeeds->clear();
|
||||||
qDebug("Loading URL seeds");
|
qDebug("Loading URL seeds");
|
||||||
const QList<QUrl> hc_seeds = m_torrent->urlSeeds();
|
const QList<QUrl> hcSeeds = m_torrent->urlSeeds();
|
||||||
// Add url seeds
|
// Add url seeds
|
||||||
foreach (const QUrl &hc_seed, hc_seeds) {
|
foreach (const QUrl &hcSeed, hcSeeds) {
|
||||||
qDebug("Loading URL seed: %s", qUtf8Printable(hc_seed.toString()));
|
qDebug("Loading URL seed: %s", qUtf8Printable(hcSeed.toString()));
|
||||||
new QListWidgetItem(hc_seed.toString(), m_ui->listWebSeeds);
|
new QListWidgetItem(hcSeed.toString(), m_ui->listWebSeeds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index)
|
void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
if (!index.isValid()) return;
|
if (!index.isValid() || !m_torrent || !m_torrent->hasMetadata()) return;
|
||||||
if (!m_torrent || !m_torrent->hasMetadata()) return;
|
|
||||||
if (PropListModel->itemType(index) == TorrentContentModelItem::FileType)
|
if (m_propListModel->itemType(index) == TorrentContentModelItem::FileType)
|
||||||
openFile(index);
|
openFile(index);
|
||||||
else
|
else
|
||||||
openFolder(index, false);
|
openFolder(index, false);
|
||||||
@@ -531,48 +540,52 @@ void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index)
|
|||||||
|
|
||||||
void PropertiesWidget::openFile(const QModelIndex &index)
|
void PropertiesWidget::openFile(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
int i = PropListModel->getFileIndex(index);
|
int i = m_propListModel->getFileIndex(index);
|
||||||
const QDir saveDir(m_torrent->savePath(true));
|
const QDir saveDir(m_torrent->savePath(true));
|
||||||
const QString filename = m_torrent->filePath(i);
|
const QString filename = m_torrent->filePath(i);
|
||||||
const QString file_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(filename));
|
const QString filePath = Utils::Fs::expandPath(saveDir.absoluteFilePath(filename));
|
||||||
qDebug("Trying to open file at %s", qUtf8Printable(file_path));
|
qDebug("Trying to open file at %s", qUtf8Printable(filePath));
|
||||||
// Flush data
|
// Flush data
|
||||||
m_torrent->flushCache();
|
m_torrent->flushCache();
|
||||||
Utils::Misc::openPath(file_path);
|
Utils::Misc::openPath(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_folder)
|
void PropertiesWidget::openFolder(const QModelIndex &index, bool containingFolder)
|
||||||
{
|
{
|
||||||
QString absolute_path;
|
QString absolutePath;
|
||||||
// FOLDER
|
// FOLDER
|
||||||
if (PropListModel->itemType(index) == TorrentContentModelItem::FolderType) {
|
if (m_propListModel->itemType(index) == TorrentContentModelItem::FolderType) {
|
||||||
// Generate relative path to selected folder
|
// Generate relative path to selected folder
|
||||||
QStringList path_items;
|
QStringList pathItems;
|
||||||
path_items << index.data().toString();
|
pathItems << index.data().toString();
|
||||||
QModelIndex parent = PropListModel->parent(index);
|
QModelIndex parent = m_propListModel->parent(index);
|
||||||
while (parent.isValid()) {
|
while (parent.isValid()) {
|
||||||
path_items.prepend(parent.data().toString());
|
pathItems.prepend(parent.data().toString());
|
||||||
parent = PropListModel->parent(parent);
|
parent = m_propListModel->parent(parent);
|
||||||
}
|
}
|
||||||
if (path_items.isEmpty())
|
if (pathItems.isEmpty())
|
||||||
return;
|
return;
|
||||||
const QDir saveDir(m_torrent->savePath(true));
|
const QDir saveDir(m_torrent->savePath(true));
|
||||||
const QString relative_path = path_items.join("/");
|
const QString relativePath = pathItems.join("/");
|
||||||
absolute_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(relative_path));
|
absolutePath = Utils::Fs::expandPath(saveDir.absoluteFilePath(relativePath));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i = PropListModel->getFileIndex(index);
|
int i = m_propListModel->getFileIndex(index);
|
||||||
const QDir saveDir(m_torrent->savePath(true));
|
const QDir saveDir(m_torrent->savePath(true));
|
||||||
const QString relative_path = m_torrent->filePath(i);
|
const QString relativePath = m_torrent->filePath(i);
|
||||||
absolute_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(relative_path));
|
absolutePath = Utils::Fs::expandPath(saveDir.absoluteFilePath(relativePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush data
|
// Flush data
|
||||||
m_torrent->flushCache();
|
m_torrent->flushCache();
|
||||||
if (containing_folder)
|
#ifdef Q_OS_MAC
|
||||||
Utils::Misc::openFolderSelect(absolute_path);
|
MacUtils::openFiles(QSet<QString>{absolutePath});
|
||||||
|
#else
|
||||||
|
if (containingFolder)
|
||||||
|
Utils::Misc::openFolderSelect(absolutePath);
|
||||||
else
|
else
|
||||||
Utils::Misc::openPath(absolute_path);
|
Utils::Misc::openPath(absolutePath);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::displayFilesListMenu(const QPoint &)
|
void PropertiesWidget::displayFilesListMenu(const QPoint &)
|
||||||
@@ -580,8 +593,8 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
|
|||||||
if (!m_torrent) return;
|
if (!m_torrent) return;
|
||||||
|
|
||||||
QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0);
|
QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0);
|
||||||
if (selectedRows.empty())
|
if (selectedRows.empty()) return;
|
||||||
return;
|
|
||||||
QMenu myFilesLlistMenu;
|
QMenu myFilesLlistMenu;
|
||||||
QAction *actOpen = nullptr;
|
QAction *actOpen = nullptr;
|
||||||
QAction *actOpenContainingFolder = nullptr;
|
QAction *actOpenContainingFolder = nullptr;
|
||||||
@@ -606,35 +619,33 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
|
|||||||
// The selected torrent might have disappeared during exec()
|
// The selected torrent might have disappeared during exec()
|
||||||
// from the current view thus leaving invalid indices.
|
// from the current view thus leaving invalid indices.
|
||||||
const QModelIndex index = *(selectedRows.begin());
|
const QModelIndex index = *(selectedRows.begin());
|
||||||
if (!index.isValid())
|
if (!index.isValid() || !act) return;
|
||||||
return;
|
|
||||||
if (act) {
|
|
||||||
if (act == actOpen) {
|
|
||||||
openDoubleClickedFile(index);
|
|
||||||
}
|
|
||||||
else if (act == actOpenContainingFolder) {
|
|
||||||
openFolder(index, true);
|
|
||||||
}
|
|
||||||
else if (act == actRename) {
|
|
||||||
renameSelectedFile();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int prio = prio::NORMAL;
|
|
||||||
if (act == m_ui->actionHigh)
|
|
||||||
prio = prio::HIGH;
|
|
||||||
else if (act == m_ui->actionMaximum)
|
|
||||||
prio = prio::MAXIMUM;
|
|
||||||
else if (act == m_ui->actionNot_downloaded)
|
|
||||||
prio = prio::IGNORED;
|
|
||||||
|
|
||||||
qDebug("Setting files priority");
|
if (act == actOpen) {
|
||||||
foreach (QModelIndex index, selectedRows) {
|
openDoubleClickedFile(index);
|
||||||
qDebug("Setting priority(%d) for file at row %d", prio, index.row());
|
}
|
||||||
PropListModel->setData(PropListModel->index(index.row(), PRIORITY, index.parent()), prio);
|
else if (act == actOpenContainingFolder) {
|
||||||
}
|
openFolder(index, true);
|
||||||
// Save changes
|
}
|
||||||
filteredFilesChanged();
|
else if (act == actRename) {
|
||||||
|
renameSelectedFile();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int prio = prio::NORMAL;
|
||||||
|
if (act == m_ui->actionHigh)
|
||||||
|
prio = prio::HIGH;
|
||||||
|
else if (act == m_ui->actionMaximum)
|
||||||
|
prio = prio::MAXIMUM;
|
||||||
|
else if (act == m_ui->actionNot_downloaded)
|
||||||
|
prio = prio::IGNORED;
|
||||||
|
|
||||||
|
qDebug("Setting files priority");
|
||||||
|
foreach (QModelIndex index, selectedRows) {
|
||||||
|
qDebug("Setting priority(%d) for file at row %d", prio, index.row());
|
||||||
|
m_propListModel->setData(m_propListModel->index(index.row(), PRIORITY, index.parent()), prio);
|
||||||
}
|
}
|
||||||
|
// Save changes
|
||||||
|
filteredFilesChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,16 +668,16 @@ void PropertiesWidget::displayWebSeedListMenu(const QPoint &)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QAction *act = seedMenu.exec(QCursor::pos());
|
const QAction *act = seedMenu.exec(QCursor::pos());
|
||||||
if (act) {
|
if (!act) return;
|
||||||
if (act == actAdd)
|
|
||||||
askWebSeed();
|
if (act == actAdd)
|
||||||
else if (act == actDel)
|
askWebSeed();
|
||||||
deleteSelectedUrlSeeds();
|
else if (act == actDel)
|
||||||
else if (act == actCpy)
|
deleteSelectedUrlSeeds();
|
||||||
copySelectedWebSeedsToClipboard();
|
else if (act == actCpy)
|
||||||
else if (act == actEdit)
|
copySelectedWebSeedsToClipboard();
|
||||||
editWebSeed();
|
else if (act == actEdit)
|
||||||
}
|
editWebSeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::renameSelectedFile()
|
void PropertiesWidget::renameSelectedFile()
|
||||||
@@ -692,9 +703,9 @@ void PropertiesWidget::renameSelectedFile()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PropListModel->itemType(modelIndex) == TorrentContentModelItem::FileType) {
|
if (m_propListModel->itemType(modelIndex) == TorrentContentModelItem::FileType) {
|
||||||
// renaming a file
|
// renaming a file
|
||||||
const int fileIndex = PropListModel->getFileIndex(modelIndex);
|
const int fileIndex = m_propListModel->getFileIndex(modelIndex);
|
||||||
|
|
||||||
if (newName.endsWith(QB_EXT))
|
if (newName.endsWith(QB_EXT))
|
||||||
newName.chop(QB_EXT.size());
|
newName.chop(QB_EXT.size());
|
||||||
@@ -722,16 +733,16 @@ void PropertiesWidget::renameSelectedFile()
|
|||||||
qDebug("Renaming %s to %s", qUtf8Printable(oldFilePath), qUtf8Printable(newFilePath));
|
qDebug("Renaming %s to %s", qUtf8Printable(oldFilePath), qUtf8Printable(newFilePath));
|
||||||
m_torrent->renameFile(fileIndex, newFilePath);
|
m_torrent->renameFile(fileIndex, newFilePath);
|
||||||
|
|
||||||
PropListModel->setData(modelIndex, newName);
|
m_propListModel->setData(modelIndex, newName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// renaming a folder
|
// renaming a folder
|
||||||
QStringList pathItems;
|
QStringList pathItems;
|
||||||
pathItems << modelIndex.data().toString();
|
pathItems << modelIndex.data().toString();
|
||||||
QModelIndex parent = PropListModel->parent(modelIndex);
|
QModelIndex parent = m_propListModel->parent(modelIndex);
|
||||||
while (parent.isValid()) {
|
while (parent.isValid()) {
|
||||||
pathItems.prepend(parent.data().toString());
|
pathItems.prepend(parent.data().toString());
|
||||||
parent = PropListModel->parent(parent);
|
parent = m_propListModel->parent(parent);
|
||||||
}
|
}
|
||||||
const QString oldPath = pathItems.join("/");
|
const QString oldPath = pathItems.join("/");
|
||||||
pathItems.removeLast();
|
pathItems.removeLast();
|
||||||
@@ -773,7 +784,7 @@ void PropertiesWidget::renameSelectedFile()
|
|||||||
// Force recheck
|
// Force recheck
|
||||||
if (forceRecheck) m_torrent->forceRecheck();
|
if (forceRecheck) m_torrent->forceRecheck();
|
||||||
// Rename folder in torrent files model too
|
// Rename folder in torrent files model too
|
||||||
PropListModel->setData(modelIndex, newName);
|
m_propListModel->setData(modelIndex, newName);
|
||||||
// Remove old folder
|
// Remove old folder
|
||||||
const QDir oldFolder(m_torrent->savePath(true) + "/" + oldPath);
|
const QDir oldFolder(m_torrent->savePath(true) + "/" + oldPath);
|
||||||
int timeout = 10;
|
int timeout = 10;
|
||||||
@@ -799,7 +810,7 @@ void PropertiesWidget::askWebSeed()
|
|||||||
// Ask user for a new url seed
|
// Ask user for a new url seed
|
||||||
const QString url_seed = AutoExpandableDialog::getText(this, tr("New URL seed", "New HTTP source"),
|
const QString url_seed = AutoExpandableDialog::getText(this, tr("New URL seed", "New HTTP source"),
|
||||||
tr("New URL seed:"), QLineEdit::Normal,
|
tr("New URL seed:"), QLineEdit::Normal,
|
||||||
QString::fromUtf8("http://www."), &ok);
|
QLatin1String("http://www."), &ok);
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
qDebug("Adding %s web seed", qUtf8Printable(url_seed));
|
qDebug("Adding %s web seed", qUtf8Printable(url_seed));
|
||||||
if (!m_ui->listWebSeeds->findItems(url_seed, Qt::MatchFixedString).empty()) {
|
if (!m_ui->listWebSeeds->findItems(url_seed, Qt::MatchFixedString).empty()) {
|
||||||
@@ -830,52 +841,48 @@ void PropertiesWidget::deleteSelectedUrlSeeds()
|
|||||||
|
|
||||||
void PropertiesWidget::copySelectedWebSeedsToClipboard() const
|
void PropertiesWidget::copySelectedWebSeedsToClipboard() const
|
||||||
{
|
{
|
||||||
const QList<QListWidgetItem *> selected_items = m_ui->listWebSeeds->selectedItems();
|
const QList<QListWidgetItem *> selectedItems = m_ui->listWebSeeds->selectedItems();
|
||||||
if (selected_items.isEmpty())
|
if (selectedItems.isEmpty()) return;
|
||||||
return;
|
|
||||||
|
|
||||||
QStringList urls_to_copy;
|
QStringList urlsToCopy;
|
||||||
foreach (QListWidgetItem *item, selected_items)
|
foreach (QListWidgetItem *item, selectedItems)
|
||||||
urls_to_copy << item->text();
|
urlsToCopy << item->text();
|
||||||
|
|
||||||
QApplication::clipboard()->setText(urls_to_copy.join("\n"));
|
QApplication::clipboard()->setText(urlsToCopy.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::editWebSeed()
|
void PropertiesWidget::editWebSeed()
|
||||||
{
|
{
|
||||||
const QList<QListWidgetItem *> selected_items = m_ui->listWebSeeds->selectedItems();
|
const QList<QListWidgetItem *> selectedItems = m_ui->listWebSeeds->selectedItems();
|
||||||
if (selected_items.size() != 1)
|
if (selectedItems.size() != 1) return;
|
||||||
return;
|
|
||||||
|
|
||||||
const QListWidgetItem *selected_item = selected_items.last();
|
const QListWidgetItem *selectedItem = selectedItems.last();
|
||||||
const QString old_seed = selected_item->text();
|
const QString oldSeed = selectedItem->text();
|
||||||
bool result;
|
bool result;
|
||||||
const QString new_seed = AutoExpandableDialog::getText(this, tr("Web seed editing"),
|
const QString newSeed = AutoExpandableDialog::getText(this, tr("Web seed editing"),
|
||||||
tr("Web seed URL:"), QLineEdit::Normal,
|
tr("Web seed URL:"), QLineEdit::Normal,
|
||||||
old_seed, &result);
|
oldSeed, &result);
|
||||||
if (!result)
|
if (!result) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if (!m_ui->listWebSeeds->findItems(new_seed, Qt::MatchFixedString).empty()) {
|
if (!m_ui->listWebSeeds->findItems(newSeed, Qt::MatchFixedString).empty()) {
|
||||||
QMessageBox::warning(this, tr("qBittorrent"),
|
QMessageBox::warning(this, tr("qBittorrent"),
|
||||||
tr("This URL seed is already in the list."),
|
tr("This URL seed is already in the list."),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_torrent->removeUrlSeeds(QList<QUrl>() << old_seed);
|
m_torrent->removeUrlSeeds(QList<QUrl>() << oldSeed);
|
||||||
m_torrent->addUrlSeeds(QList<QUrl>() << new_seed);
|
m_torrent->addUrlSeeds(QList<QUrl>() << newSeed);
|
||||||
loadUrlSeeds();
|
loadUrlSeeds();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PropertiesWidget::applyPriorities()
|
void PropertiesWidget::applyPriorities()
|
||||||
{
|
{
|
||||||
qDebug("Saving files priorities");
|
qDebug("Saving files priorities");
|
||||||
const QVector<int> priorities = PropListModel->model()->getFilePriorities();
|
const QVector<int> priorities = m_propListModel->model()->getFilePriorities();
|
||||||
// Prioritize the files
|
// Prioritize the files
|
||||||
qDebug("prioritize files: %d", priorities[0]);
|
qDebug("prioritize files: %d", priorities[0]);
|
||||||
m_torrent->prioritizeFiles(priorities);
|
m_torrent->prioritizeFiles(priorities);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::filteredFilesChanged()
|
void PropertiesWidget::filteredFilesChanged()
|
||||||
@@ -886,10 +893,10 @@ void PropertiesWidget::filteredFilesChanged()
|
|||||||
|
|
||||||
void PropertiesWidget::filterText(const QString &filter)
|
void PropertiesWidget::filterText(const QString &filter)
|
||||||
{
|
{
|
||||||
PropListModel->setFilterRegExp(QRegExp(filter, Qt::CaseInsensitive, QRegExp::WildcardUnix));
|
m_propListModel->setFilterRegExp(QRegExp(filter, Qt::CaseInsensitive, QRegExp::WildcardUnix));
|
||||||
if (filter.isEmpty()) {
|
if (filter.isEmpty()) {
|
||||||
m_ui->filesList->collapseAll();
|
m_ui->filesList->collapseAll();
|
||||||
m_ui->filesList->expand(PropListModel->index(0, 0));
|
m_ui->filesList->expand(m_propListModel->index(0, 0));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_ui->filesList->expandAll();
|
m_ui->filesList->expandAll();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PROPERTIESWIDGET_H
|
#ifndef PROPERTIESWIDGET_H
|
||||||
@@ -36,32 +34,30 @@
|
|||||||
|
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
|
|
||||||
class TransferListWidget;
|
|
||||||
class TorrentContentFilterModel;
|
|
||||||
class PropListDelegate;
|
|
||||||
class torrent_file;
|
|
||||||
class PeerListWidget;
|
|
||||||
class TrackerList;
|
|
||||||
class SpeedWidget;
|
|
||||||
class MainWindow;
|
|
||||||
class DownloadedPiecesBar;
|
|
||||||
class PieceAvailabilityBar;
|
|
||||||
class PropTabBar;
|
|
||||||
class LineEdit;
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QAction;
|
class QAction;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
class DownloadedPiecesBar;
|
||||||
|
class LineEdit;
|
||||||
|
class MainWindow;
|
||||||
|
class PeerListWidget;
|
||||||
|
class PieceAvailabilityBar;
|
||||||
|
class PropListDelegate;
|
||||||
|
class PropTabBar;
|
||||||
|
class SpeedWidget;
|
||||||
|
class torrent_file;
|
||||||
|
class TorrentContentFilterModel;
|
||||||
|
class TrackerList;
|
||||||
|
class TransferListWidget;
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class PropertiesWidget;
|
class PropertiesWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PropertiesWidget: public QWidget
|
class PropertiesWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(PropertiesWidget)
|
Q_DISABLE_COPY(PropertiesWidget)
|
||||||
@@ -73,13 +69,13 @@ public:
|
|||||||
VISIBLE
|
VISIBLE
|
||||||
};
|
};
|
||||||
|
|
||||||
PropertiesWidget(QWidget *parent, MainWindow *main_window, TransferListWidget *transferList);
|
PropertiesWidget(QWidget *parent, MainWindow *mainWindow, TransferListWidget *transferList);
|
||||||
~PropertiesWidget();
|
~PropertiesWidget();
|
||||||
BitTorrent::TorrentHandle *getCurrentTorrent() const;
|
BitTorrent::TorrentHandle *getCurrentTorrent() const;
|
||||||
TrackerList *getTrackerList() const { return trackerList; }
|
TrackerList *getTrackerList() const;
|
||||||
PeerListWidget *getPeerList() const { return peersList; }
|
PeerListWidget *getPeerList() const;
|
||||||
QTreeView *getFilesList() const;
|
QTreeView *getFilesList() const;
|
||||||
SpeedWidget *getSpeedWidget() const { return speedWidget; }
|
SpeedWidget *getSpeedWidget() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setVisibility(bool visible);
|
void setVisibility(bool visible);
|
||||||
@@ -93,7 +89,7 @@ public slots:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
QPushButton *getButtonFromIndex(int index);
|
QPushButton *getButtonFromIndex(int index);
|
||||||
bool applyPriorities();
|
void applyPriorities();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void loadTorrentInfos(BitTorrent::TorrentHandle *const torrent);
|
void loadTorrentInfos(BitTorrent::TorrentHandle *const torrent);
|
||||||
@@ -113,28 +109,28 @@ protected slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void openFile(const QModelIndex &index);
|
void openFile(const QModelIndex &index);
|
||||||
void openFolder(const QModelIndex &index, bool containing_folder);
|
void openFolder(const QModelIndex &index, bool containingFolder);
|
||||||
|
|
||||||
Ui::PropertiesWidget *m_ui;
|
Ui::PropertiesWidget *m_ui;
|
||||||
TransferListWidget *transferList;
|
TransferListWidget *m_transferList;
|
||||||
MainWindow *main_window;
|
MainWindow *m_mainWindow;
|
||||||
BitTorrent::TorrentHandle *m_torrent;
|
BitTorrent::TorrentHandle *m_torrent;
|
||||||
QTimer *refreshTimer;
|
QTimer *m_refreshTimer;
|
||||||
SlideState state;
|
SlideState m_state;
|
||||||
TorrentContentFilterModel *PropListModel;
|
TorrentContentFilterModel *m_propListModel;
|
||||||
PropListDelegate *PropDelegate;
|
PropListDelegate *m_propListDelegate;
|
||||||
PeerListWidget *peersList;
|
PeerListWidget *m_peerList;
|
||||||
TrackerList *trackerList;
|
TrackerList *m_trackerList;
|
||||||
SpeedWidget *speedWidget;
|
SpeedWidget *m_speedWidget;
|
||||||
QList<int> slideSizes;
|
QList<int> m_slideSizes;
|
||||||
DownloadedPiecesBar *downloaded_pieces;
|
DownloadedPiecesBar *m_downloadedPieces;
|
||||||
PieceAvailabilityBar *pieces_availability;
|
PieceAvailabilityBar *m_piecesAvailability;
|
||||||
PropTabBar *m_tabBar;
|
PropTabBar *m_tabBar;
|
||||||
LineEdit *m_contentFilterLine;
|
LineEdit *m_contentFilterLine;
|
||||||
QShortcut *editHotkeyFile;
|
QShortcut *m_editHotkeyFile;
|
||||||
QShortcut *editHotkeyWeb;
|
QShortcut *m_editHotkeyWeb;
|
||||||
QShortcut *deleteHotkeyWeb;
|
QShortcut *m_deleteHotkeyWeb;
|
||||||
QShortcut *openHotkeyFile;
|
QShortcut *m_openHotkeyFile;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void filterText(const QString &filter);
|
void filterText(const QString &filter);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
<number>4</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="downloaded_pieces_lbl">
|
<widget class="QLabel" name="labelDownloadedPieces">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QLabel" name="progress_lbl">
|
<widget class="QLabel" name="labelProgressVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="avail_pieces_lbl">
|
<widget class="QLabel" name="labelPiecesAvailability">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="2">
|
||||||
<widget class="QLabel" name="avail_average_lbl">
|
<widget class="QLabel" name="labelAverageAvailabilityVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -142,7 +142,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_2">
|
<widget class="Line" name="lineBelowBars">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<number>4</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="label_dl_speed_val">
|
<widget class="QLabel" name="labelDlSpeedVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="2" column="2">
|
||||||
<widget class="QLabel" name="label_upload_speed">
|
<widget class="QLabel" name="labelUpSpeed">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="3" colspan="4">
|
<item row="2" column="3" colspan="4">
|
||||||
<widget class="QLabel" name="label_upload_speed_val">
|
<widget class="QLabel" name="labelUpSpeedVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="4">
|
<item row="2" column="4">
|
||||||
<widget class="QLabel" name="label_peers">
|
<widget class="QLabel" name="labelPeers">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
<item row="0" column="4">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="labelConnections">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="3">
|
<item row="4" column="3">
|
||||||
<widget class="QLabel" name="reannounce_lbl">
|
<widget class="QLabel" name="labelReannounceInVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QLabel" name="label_eta_val">
|
<widget class="QLabel" name="labelETAVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -261,7 +261,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="labelDlLimit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -277,7 +277,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="lbl_ratio">
|
<widget class="QLabel" name="labelRatio">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="5">
|
<item row="0" column="5">
|
||||||
<widget class="QLabel" name="lbl_connections">
|
<widget class="QLabel" name="labelConnectionsVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="5">
|
<item row="2" column="5">
|
||||||
<widget class="QLabel" name="label_peers_val">
|
<widget class="QLabel" name="labelPeersVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -319,7 +319,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="labelDownloaded">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="3" column="2">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="labelUpLimit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -351,7 +351,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="4">
|
<item row="4" column="4">
|
||||||
<widget class="QLabel" name="label_last_complete">
|
<widget class="QLabel" name="labelLastSeenComplete">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -367,7 +367,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLabel" name="lbl_dllimit">
|
<widget class="QLabel" name="labelDlLimitVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -380,7 +380,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="3" colspan="4">
|
<item row="1" column="3" colspan="4">
|
||||||
<widget class="QLabel" name="upTotal">
|
<widget class="QLabel" name="labelUpTotalVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -393,7 +393,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2">
|
<item row="4" column="2">
|
||||||
<widget class="QLabel" name="label_10">
|
<widget class="QLabel" name="labelReannounceIn">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -409,7 +409,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="5">
|
<item row="4" column="5">
|
||||||
<widget class="QLabel" name="label_last_complete_val">
|
<widget class="QLabel" name="labelLastSeenCompleteVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -422,7 +422,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="4">
|
<item row="1" column="4">
|
||||||
<widget class="QLabel" name="label_seeds">
|
<widget class="QLabel" name="labelSeeds">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -438,7 +438,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_dl_speed">
|
<widget class="QLabel" name="labelDlSpeed">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -454,7 +454,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="dlTotal">
|
<widget class="QLabel" name="labelDlTotalVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -467,7 +467,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="5">
|
<item row="3" column="5">
|
||||||
<widget class="QLabel" name="wasted">
|
<widget class="QLabel" name="labelWastedVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -480,7 +480,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="shareRatio">
|
<widget class="QLabel" name="labelShareRatioVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -493,7 +493,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="2">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="labelUploaded">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -509,7 +509,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="5">
|
<item row="1" column="5">
|
||||||
<widget class="QLabel" name="label_seeds_val">
|
<widget class="QLabel" name="labelSeedsVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -522,7 +522,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="lbl_elapsed">
|
<widget class="QLabel" name="labelElapsedVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -535,7 +535,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="labelTimeActive">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -551,7 +551,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="3">
|
<item row="3" column="3">
|
||||||
<widget class="QLabel" name="lbl_uplimit">
|
<widget class="QLabel" name="labelUpLimitVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -564,7 +564,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QLabel" name="label_eta">
|
<widget class="QLabel" name="labelETA">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -580,7 +580,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="4">
|
<item row="3" column="4">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QLabel" name="labelWasted">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -611,7 +611,7 @@
|
|||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_total_size">
|
<widget class="QLabel" name="labelTotalSize">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -627,7 +627,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_total_size_val">
|
<widget class="QLabel" name="labelTotalSizeVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -640,7 +640,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QLabel" name="label_total_pieces">
|
<widget class="QLabel" name="labelTotalPieces">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -656,7 +656,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QLabel" name="label_total_pieces_val">
|
<widget class="QLabel" name="labelTotalPiecesVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -669,7 +669,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
<item row="0" column="4">
|
||||||
<widget class="QLabel" name="label_created_by">
|
<widget class="QLabel" name="labelCreatedBy">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -685,7 +685,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="5">
|
<item row="0" column="5">
|
||||||
<widget class="QLabel" name="label_created_by_val">
|
<widget class="QLabel" name="labelCreatedByVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -698,7 +698,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_added_on">
|
<widget class="QLabel" name="labelAddedOn">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -714,7 +714,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="label_added_on_val">
|
<widget class="QLabel" name="labelAddedOnVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -727,7 +727,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="2">
|
||||||
<widget class="QLabel" name="label_completed_on">
|
<widget class="QLabel" name="labelCompletedOn">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -743,7 +743,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="3">
|
<item row="1" column="3">
|
||||||
<widget class="QLabel" name="label_completed_on_val">
|
<widget class="QLabel" name="labelCompletedOnVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -756,7 +756,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="4">
|
<item row="1" column="4">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="labelCreatedOn">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -772,7 +772,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="5">
|
<item row="1" column="5">
|
||||||
<widget class="QLabel" name="lbl_creationDate">
|
<widget class="QLabel" name="labelCreatedOnVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -785,7 +785,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="hash_lbl2">
|
<widget class="QLabel" name="labelHash">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -801,7 +801,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" colspan="5">
|
<item row="2" column="1" colspan="5">
|
||||||
<widget class="QLabel" name="hash_lbl">
|
<widget class="QLabel" name="labelHashVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -817,7 +817,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="savePath_lbl">
|
<widget class="QLabel" name="labelSavePath">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -833,7 +833,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1" colspan="5">
|
<item row="3" column="1" colspan="5">
|
||||||
<widget class="QLabel" name="save_path">
|
<widget class="QLabel" name="labelSavePathVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -852,7 +852,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="comment_lbl2">
|
<widget class="QLabel" name="labelComment">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -868,7 +868,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1" colspan="5">
|
<item row="4" column="1" colspan="5">
|
||||||
<widget class="QLabel" name="comment_text">
|
<widget class="QLabel" name="labelCommentVal">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -1000,6 +1000,9 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="pageContents">
|
<widget class="QWidget" name="pageContents">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -1062,7 +1065,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="pageSpeed">
|
<widget class="QWidget" name="pageSpeed">
|
||||||
<layout class="QVBoxLayout" name="speed_layout">
|
<layout class="QVBoxLayout" name="speedLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "proplistdelegate.h"
|
#include "proplistdelegate.h"
|
||||||
@@ -83,53 +81,53 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
|||||||
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong()));
|
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong()));
|
||||||
break;
|
break;
|
||||||
case PROGRESS: {
|
case PROGRESS: {
|
||||||
if (index.data().toDouble() < 0)
|
if (index.data().toDouble() < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
QStyleOptionProgressBar newopt;
|
QStyleOptionProgressBar newopt;
|
||||||
qreal progress = index.data().toDouble() * 100.;
|
qreal progress = index.data().toDouble() * 100.;
|
||||||
newopt.rect = opt.rect;
|
newopt.rect = opt.rect;
|
||||||
newopt.text = ((progress == 100.0) ? QString("100%") : Utils::String::fromDouble(progress, 1) + "%");
|
newopt.text = ((progress == 100.0) ? QString("100%") : Utils::String::fromDouble(progress, 1) + "%");
|
||||||
newopt.progress = int(progress);
|
newopt.progress = int(progress);
|
||||||
newopt.maximum = 100;
|
newopt.maximum = 100;
|
||||||
newopt.minimum = 0;
|
newopt.minimum = 0;
|
||||||
newopt.textVisible = true;
|
newopt.textVisible = true;
|
||||||
if (index.sibling(index.row(), PRIORITY).data().toInt() == prio::IGNORED) {
|
if (index.sibling(index.row(), PRIORITY).data().toInt() == prio::IGNORED) {
|
||||||
newopt.state &= ~QStyle::State_Enabled;
|
newopt.state &= ~QStyle::State_Enabled;
|
||||||
newopt.palette = progressBarDisabledPalette();
|
newopt.palette = progressBarDisabledPalette();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
newopt.state |= QStyle::State_Enabled;
|
newopt.state |= QStyle::State_Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter);
|
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter);
|
||||||
#else
|
#else
|
||||||
// XXX: To avoid having the progress text on the right of the bar
|
// XXX: To avoid having the progress text on the right of the bar
|
||||||
QProxyStyle("fusion").drawControl(QStyle::CE_ProgressBar, &newopt, painter, 0);
|
QProxyStyle("fusion").drawControl(QStyle::CE_ProgressBar, &newopt, painter, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PRIORITY: {
|
|
||||||
QString text = "";
|
|
||||||
switch (index.data().toInt()) {
|
|
||||||
case prio::MIXED:
|
|
||||||
text = tr("Mixed", "Mixed (priorities");
|
|
||||||
break;
|
|
||||||
case prio::IGNORED:
|
|
||||||
text = tr("Not downloaded");
|
|
||||||
break;
|
|
||||||
case prio::HIGH:
|
|
||||||
text = tr("High", "High (priority)");
|
|
||||||
break;
|
|
||||||
case prio::MAXIMUM:
|
|
||||||
text = tr("Maximum", "Maximum (priority)");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
text = tr("Normal", "Normal (priority)");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
QItemDelegate::drawDisplay(painter, opt, option.rect, text);
|
break;
|
||||||
|
case PRIORITY: {
|
||||||
|
QString text = "";
|
||||||
|
switch (index.data().toInt()) {
|
||||||
|
case prio::MIXED:
|
||||||
|
text = tr("Mixed", "Mixed (priorities");
|
||||||
|
break;
|
||||||
|
case prio::IGNORED:
|
||||||
|
text = tr("Not downloaded");
|
||||||
|
break;
|
||||||
|
case prio::HIGH:
|
||||||
|
text = tr("High", "High (priority)");
|
||||||
|
break;
|
||||||
|
case prio::MAXIMUM:
|
||||||
|
text = tr("Maximum", "Maximum (priority)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
text = tr("Normal", "Normal (priority)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QItemDelegate::drawDisplay(painter, opt, option.rect, text);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVAILABILITY: {
|
case AVAILABILITY: {
|
||||||
@@ -174,16 +172,16 @@ void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
|
|||||||
|
|
||||||
QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
|
QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.column() != PRIORITY) return 0;
|
if (index.column() != PRIORITY) return nullptr;
|
||||||
|
|
||||||
if (m_properties) {
|
if (m_properties) {
|
||||||
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent();
|
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent();
|
||||||
if (!torrent || !torrent->hasMetadata() || torrent->isSeed())
|
if (!torrent || !torrent->hasMetadata() || torrent->isSeed())
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index.data().toInt() == prio::MIXED)
|
if (index.data().toInt() == prio::MIXED)
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
QComboBox *editor = new QComboBox(parent);
|
QComboBox *editor = new QComboBox(parent);
|
||||||
editor->setFocusPolicy(Qt::StrongFocus);
|
editor->setFocusPolicy(Qt::StrongFocus);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PROPLISTDELEGATE_H
|
#ifndef PROPLISTDELEGATE_H
|
||||||
@@ -33,10 +31,10 @@
|
|||||||
|
|
||||||
#include <QItemDelegate>
|
#include <QItemDelegate>
|
||||||
|
|
||||||
class QPainter;
|
|
||||||
class QModelIndex;
|
|
||||||
class QStyleOptionViewItem;
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
class QModelIndex;
|
||||||
|
class QPainter;
|
||||||
|
class QStyleOptionViewItem;
|
||||||
class PropertiesWidget;
|
class PropertiesWidget;
|
||||||
|
|
||||||
// Defines for properties list columns
|
// Defines for properties list columns
|
||||||
@@ -50,7 +48,7 @@ enum PropColumn
|
|||||||
AVAILABILITY
|
AVAILABILITY
|
||||||
};
|
};
|
||||||
|
|
||||||
class PropListDelegate: public QItemDelegate
|
class PropListDelegate : public QItemDelegate
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -72,5 +70,4 @@ private:
|
|||||||
PropertiesWidget *m_properties;
|
PropertiesWidget *m_properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // PROPLISTDELEGATE_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2010 Christophe Dumez
|
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,120 +24,121 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "proptabbar.h"
|
||||||
|
|
||||||
#include <QButtonGroup>
|
#include <QButtonGroup>
|
||||||
|
#include <QKeySequence>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
#include <QKeySequence>
|
|
||||||
|
|
||||||
#include "proptabbar.h"
|
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
|
|
||||||
PropTabBar::PropTabBar(QWidget *parent) :
|
PropTabBar::PropTabBar(QWidget *parent)
|
||||||
QHBoxLayout(parent), m_currentIndex(-1)
|
: QHBoxLayout(parent)
|
||||||
|
, m_currentIndex(-1)
|
||||||
{
|
{
|
||||||
setAlignment(Qt::AlignLeft | Qt::AlignCenter);
|
setAlignment(Qt::AlignLeft | Qt::AlignCenter);
|
||||||
setSpacing(3);
|
setSpacing(3);
|
||||||
m_btnGroup = new QButtonGroup(this);
|
m_btnGroup = new QButtonGroup(this);
|
||||||
// General tab
|
// General tab
|
||||||
QPushButton *main_infos_button = new QPushButton(
|
QPushButton *mainInfosButton = new QPushButton(
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
GuiIconProvider::instance()->getIcon("document-properties"),
|
GuiIconProvider::instance()->getIcon("document-properties"),
|
||||||
#endif
|
#endif
|
||||||
tr("General"), parent);
|
tr("General"), parent);
|
||||||
main_infos_button->setShortcut(Qt::ALT + Qt::Key_G);
|
mainInfosButton->setShortcut(Qt::ALT + Qt::Key_G);
|
||||||
addWidget(main_infos_button);
|
addWidget(mainInfosButton);
|
||||||
m_btnGroup->addButton(main_infos_button, MAIN_TAB);
|
m_btnGroup->addButton(mainInfosButton, MainTab);
|
||||||
// Trackers tab
|
// Trackers tab
|
||||||
QPushButton *trackers_button = new QPushButton(
|
QPushButton *trackersButton = new QPushButton(
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
GuiIconProvider::instance()->getIcon("network-server"),
|
GuiIconProvider::instance()->getIcon("network-server"),
|
||||||
#endif
|
#endif
|
||||||
tr("Trackers"), parent);
|
tr("Trackers"), parent);
|
||||||
trackers_button->setShortcut(Qt::ALT + Qt::Key_C);
|
trackersButton->setShortcut(Qt::ALT + Qt::Key_C);
|
||||||
addWidget(trackers_button);
|
addWidget(trackersButton);
|
||||||
m_btnGroup->addButton(trackers_button, TRACKERS_TAB);
|
m_btnGroup->addButton(trackersButton, TrackersTab);
|
||||||
// Peers tab
|
// Peers tab
|
||||||
QPushButton *peers_button = new QPushButton(
|
QPushButton *peersButton = new QPushButton(
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
GuiIconProvider::instance()->getIcon("edit-find-user"),
|
GuiIconProvider::instance()->getIcon("edit-find-user"),
|
||||||
#endif
|
#endif
|
||||||
tr("Peers"), parent);
|
tr("Peers"), parent);
|
||||||
peers_button->setShortcut(Qt::ALT + Qt::Key_R);
|
peersButton->setShortcut(Qt::ALT + Qt::Key_R);
|
||||||
addWidget(peers_button);
|
addWidget(peersButton);
|
||||||
m_btnGroup->addButton(peers_button, PEERS_TAB);
|
m_btnGroup->addButton(peersButton, PeersTab);
|
||||||
// URL seeds tab
|
// URL seeds tab
|
||||||
QPushButton *urlseeds_button = new QPushButton(
|
QPushButton *URLSeedsButton = new QPushButton(
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
GuiIconProvider::instance()->getIcon("network-server"),
|
GuiIconProvider::instance()->getIcon("network-server"),
|
||||||
#endif
|
#endif
|
||||||
tr("HTTP Sources"), parent);
|
tr("HTTP Sources"), parent);
|
||||||
urlseeds_button->setShortcut(Qt::ALT + Qt::Key_B);
|
URLSeedsButton->setShortcut(Qt::ALT + Qt::Key_B);
|
||||||
addWidget(urlseeds_button);
|
addWidget(URLSeedsButton);
|
||||||
m_btnGroup->addButton(urlseeds_button, URLSEEDS_TAB);
|
m_btnGroup->addButton(URLSeedsButton, URLSeedsTab);
|
||||||
// Files tab
|
// Files tab
|
||||||
QPushButton *files_button = new QPushButton(
|
QPushButton *filesButton = new QPushButton(
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
GuiIconProvider::instance()->getIcon("inode-directory"),
|
GuiIconProvider::instance()->getIcon("inode-directory"),
|
||||||
#endif
|
#endif
|
||||||
tr("Content"), parent);
|
tr("Content"), parent);
|
||||||
files_button->setShortcut(Qt::ALT + Qt::Key_Z);
|
filesButton->setShortcut(Qt::ALT + Qt::Key_Z);
|
||||||
addWidget(files_button);
|
addWidget(filesButton);
|
||||||
m_btnGroup->addButton(files_button, FILES_TAB);
|
m_btnGroup->addButton(filesButton, FilesTab);
|
||||||
// Spacer
|
// Spacer
|
||||||
addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
|
addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
|
||||||
// Speed tab
|
// Speed tab
|
||||||
QPushButton *speed_button = new QPushButton(
|
QPushButton *speedButton = new QPushButton(
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
GuiIconProvider::instance()->getIcon("office-chart-line"),
|
GuiIconProvider::instance()->getIcon("office-chart-line"),
|
||||||
#endif
|
#endif
|
||||||
tr("Speed"), parent);
|
tr("Speed"), parent);
|
||||||
speed_button->setShortcut(Qt::ALT + Qt::Key_D);
|
speedButton->setShortcut(Qt::ALT + Qt::Key_D);
|
||||||
addWidget(speed_button);
|
addWidget(speedButton);
|
||||||
m_btnGroup->addButton(speed_button, SPEED_TAB);
|
m_btnGroup->addButton(speedButton, SpeedTab);
|
||||||
// SIGNAL/SLOT
|
// SIGNAL/SLOT
|
||||||
connect(m_btnGroup, SIGNAL(buttonClicked(int)), SLOT(setCurrentIndex(int)));
|
connect(m_btnGroup, SIGNAL(buttonClicked(int)), SLOT(setCurrentIndex(int)));
|
||||||
// Disable buttons focus
|
// Disable buttons focus
|
||||||
foreach (QAbstractButton *btn, m_btnGroup->buttons()) {
|
foreach (QAbstractButton *btn, m_btnGroup->buttons())
|
||||||
btn->setFocusPolicy(Qt::NoFocus);
|
btn->setFocusPolicy(Qt::NoFocus);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PropTabBar::~PropTabBar() {
|
PropTabBar::~PropTabBar()
|
||||||
delete m_btnGroup;
|
{
|
||||||
|
delete m_btnGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PropTabBar::currentIndex() const
|
int PropTabBar::currentIndex() const
|
||||||
{
|
{
|
||||||
return m_currentIndex;
|
return m_currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropTabBar::setCurrentIndex(int index)
|
void PropTabBar::setCurrentIndex(int index)
|
||||||
{
|
{
|
||||||
if (index >= m_btnGroup->buttons().size())
|
if (index >= m_btnGroup->buttons().size())
|
||||||
index = 0;
|
index = 0;
|
||||||
// If asked to hide or if the currently selected tab is clicked
|
// If asked to hide or if the currently selected tab is clicked
|
||||||
if (index < 0 || m_currentIndex == index) {
|
if (index < 0 || m_currentIndex == index) {
|
||||||
if (m_currentIndex >= 0) {
|
if (m_currentIndex >= 0) {
|
||||||
m_btnGroup->button(m_currentIndex)->setDown(false);
|
m_btnGroup->button(m_currentIndex)->setDown(false);
|
||||||
m_currentIndex = -1;
|
m_currentIndex = -1;
|
||||||
emit visibilityToggled(false);
|
emit visibilityToggled(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
// Unselect previous tab
|
||||||
}
|
if (m_currentIndex >= 0) {
|
||||||
// Unselect previous tab
|
m_btnGroup->button(m_currentIndex)->setDown(false);
|
||||||
if (m_currentIndex >= 0) {
|
}
|
||||||
m_btnGroup->button(m_currentIndex)->setDown(false);
|
else {
|
||||||
} else {
|
// Nothing was selected, show!
|
||||||
// Nothing was selected, show!
|
emit visibilityToggled(true);
|
||||||
emit visibilityToggled(true);
|
}
|
||||||
}
|
// Select the new button
|
||||||
// Select the new button
|
m_btnGroup->button(index)->setDown(true);
|
||||||
m_btnGroup->button(index)->setDown(true);
|
m_currentIndex = index;
|
||||||
m_currentIndex = index;
|
// Emit the signal
|
||||||
// Emit the signal
|
emit tabChanged(index);
|
||||||
emit tabChanged(index);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2010 Christophe Dumez
|
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PROPTABBAR_H
|
#ifndef PROPTABBAR_H
|
||||||
@@ -33,9 +31,7 @@
|
|||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QButtonGroup;
|
class QButtonGroup;
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
class PropTabBar : public QHBoxLayout
|
class PropTabBar : public QHBoxLayout
|
||||||
{
|
{
|
||||||
@@ -43,24 +39,30 @@ class PropTabBar : public QHBoxLayout
|
|||||||
Q_DISABLE_COPY(PropTabBar)
|
Q_DISABLE_COPY(PropTabBar)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum PropertyTab {MAIN_TAB, TRACKERS_TAB, PEERS_TAB, URLSEEDS_TAB, FILES_TAB, SPEED_TAB};
|
enum PropertyTab
|
||||||
|
{
|
||||||
|
MainTab,
|
||||||
|
TrackersTab,
|
||||||
|
PeersTab,
|
||||||
|
URLSeedsTab,
|
||||||
|
FilesTab,
|
||||||
|
SpeedTab
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
explicit PropTabBar(QWidget *parent = nullptr);
|
||||||
explicit PropTabBar(QWidget *parent = 0);
|
~PropTabBar();
|
||||||
~PropTabBar();
|
int currentIndex() const;
|
||||||
int currentIndex() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void tabChanged(int index);
|
void tabChanged(int index);
|
||||||
void visibilityToggled(bool visible);
|
void visibilityToggled(bool visible);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setCurrentIndex(int index);
|
void setCurrentIndex(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QButtonGroup *m_btnGroup;
|
QButtonGroup *m_btnGroup;
|
||||||
int m_currentIndex;
|
int m_currentIndex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PROPTABBAR_H
|
#endif // PROPTABBAR_H
|
||||||
|
|||||||
@@ -191,20 +191,20 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
|||||||
Utils::Misc::friendlyUnit(0, true)
|
Utils::Misc::friendlyUnit(0, true)
|
||||||
};
|
};
|
||||||
|
|
||||||
int yAxeWidth = 0;
|
int yAxisWidth = 0;
|
||||||
for (const QString &label : speedLabels)
|
for (const QString &label : speedLabels)
|
||||||
if (fontMetrics.width(label) > yAxeWidth)
|
if (fontMetrics.width(label) > yAxisWidth)
|
||||||
yAxeWidth = fontMetrics.width(label);
|
yAxisWidth = fontMetrics.width(label);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const QString &label : speedLabels) {
|
for (const QString &label : speedLabels) {
|
||||||
QRectF labelRect(rect.topLeft() + QPointF(-yAxeWidth, (i++) * 0.25 * rect.height() - fontMetrics.height()),
|
QRectF labelRect(rect.topLeft() + QPointF(-yAxisWidth, (i++) * 0.25 * rect.height() - fontMetrics.height()),
|
||||||
QSizeF(2 * yAxeWidth, fontMetrics.height()));
|
QSizeF(2 * yAxisWidth, fontMetrics.height()));
|
||||||
painter.drawText(labelRect, label, Qt::AlignRight | Qt::AlignTop);
|
painter.drawText(labelRect, label, Qt::AlignRight | Qt::AlignTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw grid lines
|
// draw grid lines
|
||||||
rect.adjust(yAxeWidth + 4, 0, 0, 0);
|
rect.adjust(yAxisWidth + 4, 0, 0, 0);
|
||||||
|
|
||||||
QPen gridPen;
|
QPen gridPen;
|
||||||
gridPen.setStyle(Qt::DashLine);
|
gridPen.setStyle(Qt::DashLine);
|
||||||
@@ -236,18 +236,16 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
|||||||
boost::circular_buffer<PointData> &queue = getCurrentData();
|
boost::circular_buffer<PointData> &queue = getCurrentData();
|
||||||
|
|
||||||
for (int id = UP; id < NB_GRAPHS; ++id) {
|
for (int id = UP; id < NB_GRAPHS; ++id) {
|
||||||
|
|
||||||
if (!m_properties[static_cast<GraphID>(id)].enable)
|
if (!m_properties[static_cast<GraphID>(id)].enable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QVector<QPoint> points;
|
QVector<QPoint> points;
|
||||||
|
|
||||||
for (int i = int(queue.size()) - 1, j = 0; i >= 0 && j <= m_viewablePointsCount; --i, ++j) {
|
for (int i = int(queue.size()) - 1, j = 0; i >= 0 && j <= m_viewablePointsCount; --i, ++j) {
|
||||||
|
|
||||||
int new_x = rect.right() - j * xTickSize;
|
int newX = rect.right() - j * xTickSize;
|
||||||
int new_y = rect.bottom() - queue[i].y[id] * yMultiplier;
|
int newY = rect.bottom() - queue[i].y[id] * yMultiplier;
|
||||||
|
|
||||||
points.push_back(QPoint(new_x, new_y));
|
points.push_back(QPoint(newX, newY));
|
||||||
}
|
}
|
||||||
|
|
||||||
painter.setPen(m_properties[static_cast<GraphID>(id)].pen);
|
painter.setPen(m_properties[static_cast<GraphID>(id)].pen);
|
||||||
@@ -260,7 +258,6 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
|||||||
double legendHeight = 0;
|
double legendHeight = 0;
|
||||||
int legendWidth = 0;
|
int legendWidth = 0;
|
||||||
for (const auto &property : m_properties) {
|
for (const auto &property : m_properties) {
|
||||||
|
|
||||||
if (!property.enable)
|
if (!property.enable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -276,7 +273,6 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (const auto &property : m_properties) {
|
for (const auto &property : m_properties) {
|
||||||
|
|
||||||
if (!property.enable)
|
if (!property.enable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -293,10 +289,12 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
|||||||
|
|
||||||
SpeedPlotView::GraphProperties::GraphProperties()
|
SpeedPlotView::GraphProperties::GraphProperties()
|
||||||
: enable(false)
|
: enable(false)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen, bool enable)
|
SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen, bool enable)
|
||||||
: name(name)
|
: name(name)
|
||||||
, pen(pen)
|
, pen(pen)
|
||||||
, enable(enable)
|
, enable(enable)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
DHT_DOWN,
|
DHT_DOWN,
|
||||||
TRACKER_UP,
|
TRACKER_UP,
|
||||||
TRACKER_DOWN,
|
TRACKER_DOWN,
|
||||||
|
|
||||||
NB_GRAPHS
|
NB_GRAPHS
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ public:
|
|||||||
void replot();
|
void replot();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum PeriodInSeconds
|
enum PeriodInSeconds
|
||||||
@@ -110,6 +111,9 @@ private:
|
|||||||
bool enable;
|
bool enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int maxYValue();
|
||||||
|
boost::circular_buffer<PointData> &getCurrentData();
|
||||||
|
|
||||||
boost::circular_buffer<PointData> m_data5Min;
|
boost::circular_buffer<PointData> m_data5Min;
|
||||||
boost::circular_buffer<PointData> m_data30Min;
|
boost::circular_buffer<PointData> m_data30Min;
|
||||||
boost::circular_buffer<PointData> m_data6Hour;
|
boost::circular_buffer<PointData> m_data6Hour;
|
||||||
@@ -120,10 +124,6 @@ private:
|
|||||||
|
|
||||||
int m_counter30Min;
|
int m_counter30Min;
|
||||||
int m_counter6Hour;
|
int m_counter6Hour;
|
||||||
|
|
||||||
int maxYValue();
|
|
||||||
|
|
||||||
boost::circular_buffer<PointData> &getCurrentData();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SPEEDPLOTVIEW_H
|
#endif // SPEEDPLOTVIEW_H
|
||||||
|
|||||||
@@ -38,10 +38,10 @@
|
|||||||
|
|
||||||
#include <libtorrent/session_status.hpp>
|
#include <libtorrent/session_status.hpp>
|
||||||
|
|
||||||
#include "propertieswidget.h"
|
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/sessionstatus.h"
|
#include "base/bittorrent/sessionstatus.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
|
#include "propertieswidget.h"
|
||||||
|
|
||||||
ComboBoxMenuButton::ComboBoxMenuButton(QWidget *parent, QMenu *menu)
|
ComboBoxMenuButton::ComboBoxMenuButton(QWidget *parent, QMenu *menu)
|
||||||
: QComboBox(parent)
|
: QComboBox(parent)
|
||||||
@@ -61,6 +61,7 @@ SpeedWidget::SpeedWidget(PropertiesWidget *parent)
|
|||||||
{
|
{
|
||||||
m_layout = new QVBoxLayout(this);
|
m_layout = new QVBoxLayout(this);
|
||||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
m_layout->setSpacing(3);
|
||||||
|
|
||||||
m_hlayout = new QHBoxLayout();
|
m_hlayout = new QHBoxLayout();
|
||||||
m_hlayout->setContentsMargins(0, 0, 0, 0);
|
m_hlayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
#ifndef SPEEDWIDGET_H
|
#ifndef SPEEDWIDGET_H
|
||||||
#define SPEEDWIDGET_H
|
#define SPEEDWIDGET_H
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
#include "speedplotview.h"
|
#include "speedplotview.h"
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ class PropertiesWidget;
|
|||||||
class ComboBoxMenuButton : public QComboBox
|
class ComboBoxMenuButton : public QComboBox
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ComboBoxMenuButton(QWidget *parent, QMenu *menu);
|
ComboBoxMenuButton(QWidget *parent, QMenu *menu);
|
||||||
virtual void showPopup();
|
virtual void showPopup();
|
||||||
@@ -56,6 +57,7 @@ private:
|
|||||||
class SpeedWidget : public QWidget
|
class SpeedWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpeedWidget(PropertiesWidget *parent);
|
SpeedWidget(PropertiesWidget *parent);
|
||||||
~SpeedWidget();
|
~SpeedWidget();
|
||||||
|
|||||||
@@ -399,13 +399,13 @@ void TrackerList::copyTrackerUrl()
|
|||||||
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
|
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
|
||||||
if (selectedTrackerItems.isEmpty()) return;
|
if (selectedTrackerItems.isEmpty()) return;
|
||||||
|
|
||||||
QStringList URLsToCopy;
|
QStringList urlsToCopy;
|
||||||
foreach (QTreeWidgetItem *item, selectedTrackerItems) {
|
foreach (QTreeWidgetItem *item, selectedTrackerItems) {
|
||||||
QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
|
QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
|
||||||
qDebug() << QString("Copy: ") + trackerURL;
|
qDebug() << QString("Copy: ") + trackerURL;
|
||||||
URLsToCopy << trackerURL;
|
urlsToCopy << trackerURL;
|
||||||
}
|
}
|
||||||
QApplication::clipboard()->setText(URLsToCopy.join("\n"));
|
QApplication::clipboard()->setText(urlsToCopy.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -420,10 +420,10 @@ void TrackerList::deleteSelectedTrackers()
|
|||||||
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
|
QList<QTreeWidgetItem *> selectedTrackerItems = getSelectedTrackerItems();
|
||||||
if (selectedTrackerItems.isEmpty()) return;
|
if (selectedTrackerItems.isEmpty()) return;
|
||||||
|
|
||||||
QStringList URLsToRemove;
|
QStringList urlsToRemove;
|
||||||
foreach (QTreeWidgetItem *item, selectedTrackerItems) {
|
foreach (QTreeWidgetItem *item, selectedTrackerItems) {
|
||||||
QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
|
QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString();
|
||||||
URLsToRemove << trackerURL;
|
urlsToRemove << trackerURL;
|
||||||
m_trackerItems.remove(trackerURL);
|
m_trackerItems.remove(trackerURL);
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
@@ -432,7 +432,7 @@ void TrackerList::deleteSelectedTrackers()
|
|||||||
QList<BitTorrent::TrackerEntry> remainingTrackers;
|
QList<BitTorrent::TrackerEntry> remainingTrackers;
|
||||||
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||||
foreach (const BitTorrent::TrackerEntry &entry, trackers) {
|
foreach (const BitTorrent::TrackerEntry &entry, trackers) {
|
||||||
if (!URLsToRemove.contains(entry.url()))
|
if (!urlsToRemove.contains(entry.url()))
|
||||||
remainingTrackers.push_back(entry);
|
remainingTrackers.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,9 +627,8 @@ void TrackerList::displayToggleColumnsMenu(const QPoint &)
|
|||||||
Q_ASSERT(visibleColumnsCount() > 0);
|
Q_ASSERT(visibleColumnsCount() > 0);
|
||||||
if (!isColumnHidden(col) && (visibleColumnsCount() == 1))
|
if (!isColumnHidden(col) && (visibleColumnsCount() == 1))
|
||||||
return;
|
return;
|
||||||
qDebug("Toggling column %d visibility", col);
|
|
||||||
setColumnHidden(col, !isColumnHidden(col));
|
setColumnHidden(col, !isColumnHidden(col));
|
||||||
if (!isColumnHidden(col) && (columnWidth(col) <= 5))
|
if (!isColumnHidden(col) && (columnWidth(col) <= 5))
|
||||||
setColumnWidth(col, 100);
|
resizeColumnToContents(col);
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,22 +24,20 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
#include "trackersadditiondlg.h"
|
#include "trackersadditiondlg.h"
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QStringList>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
|
||||||
#include "base/utils/fs.h"
|
|
||||||
#include "base/net/downloadmanager.h"
|
|
||||||
#include "base/net/downloadhandler.h"
|
|
||||||
#include "base/bittorrent/trackerentry.h"
|
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
|
#include "base/bittorrent/trackerentry.h"
|
||||||
|
#include "base/net/downloadhandler.h"
|
||||||
|
#include "base/net/downloadmanager.h"
|
||||||
|
#include "base/utils/fs.h"
|
||||||
|
#include "base/utils/misc.h"
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
#include "ui_trackersadditiondlg.h"
|
#include "ui_trackersadditiondlg.h"
|
||||||
|
|
||||||
@@ -75,14 +73,14 @@ void TrackersAdditionDlg::on_uTorrentListButton_clicked()
|
|||||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_ui->list_url->text(), true);
|
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_ui->list_url->text(), true);
|
||||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString)));
|
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString)));
|
||||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString)));
|
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString)));
|
||||||
//Just to show that it takes times
|
// Just to show that it takes times
|
||||||
setCursor(Qt::WaitCursor);
|
setCursor(Qt::WaitCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackersAdditionDlg::parseUTorrentList(const QString &, const QString &path)
|
void TrackersAdditionDlg::parseUTorrentList(const QString &, const QString &path)
|
||||||
{
|
{
|
||||||
QFile list_file(path);
|
QFile listFile(path);
|
||||||
if (!list_file.open(QFile::ReadOnly)) {
|
if (!listFile.open(QFile::ReadOnly)) {
|
||||||
QMessageBox::warning(this, tr("I/O Error"), tr("Error while trying to open the downloaded file."), QMessageBox::Ok);
|
QMessageBox::warning(this, tr("I/O Error"), tr("Error while trying to open the downloaded file."), QMessageBox::Ok);
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
m_ui->uTorrentListButton->setEnabled(true);
|
m_ui->uTorrentListButton->setEnabled(true);
|
||||||
@@ -94,8 +92,8 @@ void TrackersAdditionDlg::parseUTorrentList(const QString &, const QString &path
|
|||||||
QList<BitTorrent::TrackerEntry> existingTrackers = m_torrent->trackers();
|
QList<BitTorrent::TrackerEntry> existingTrackers = m_torrent->trackers();
|
||||||
// Load from current user list
|
// Load from current user list
|
||||||
QStringList tmp = m_ui->trackers_list->toPlainText().split("\n");
|
QStringList tmp = m_ui->trackers_list->toPlainText().split("\n");
|
||||||
foreach (const QString &user_url, tmp) {
|
foreach (const QString &userURL, tmp) {
|
||||||
BitTorrent::TrackerEntry userTracker(user_url);
|
BitTorrent::TrackerEntry userTracker(userURL);
|
||||||
if (!existingTrackers.contains(userTracker))
|
if (!existingTrackers.contains(userTracker))
|
||||||
existingTrackers << userTracker;
|
existingTrackers << userTracker;
|
||||||
}
|
}
|
||||||
@@ -104,8 +102,8 @@ void TrackersAdditionDlg::parseUTorrentList(const QString &, const QString &path
|
|||||||
if (!m_ui->trackers_list->toPlainText().isEmpty() && !m_ui->trackers_list->toPlainText().endsWith("\n"))
|
if (!m_ui->trackers_list->toPlainText().isEmpty() && !m_ui->trackers_list->toPlainText().endsWith("\n"))
|
||||||
m_ui->trackers_list->insertPlainText("\n");
|
m_ui->trackers_list->insertPlainText("\n");
|
||||||
int nb = 0;
|
int nb = 0;
|
||||||
while (!list_file.atEnd()) {
|
while (!listFile.atEnd()) {
|
||||||
const QString line = list_file.readLine().trimmed();
|
const QString line = listFile.readLine().trimmed();
|
||||||
if (line.isEmpty()) continue;
|
if (line.isEmpty()) continue;
|
||||||
BitTorrent::TrackerEntry newTracker(line);
|
BitTorrent::TrackerEntry newTracker(line);
|
||||||
if (!existingTrackers.contains(newTracker)) {
|
if (!existingTrackers.contains(newTracker)) {
|
||||||
@@ -114,7 +112,7 @@ void TrackersAdditionDlg::parseUTorrentList(const QString &, const QString &path
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean up
|
// Clean up
|
||||||
list_file.close();
|
listFile.close();
|
||||||
Utils::Fs::forceRemove(path);
|
Utils::Fs::forceRemove(path);
|
||||||
//To restore the cursor ...
|
//To restore the cursor ...
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
* modify file(s), you may extend this exception to your version of the file(s),
|
* 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
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*
|
|
||||||
* Contact : chris@qbittorrent.org
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TRACKERSADDITION_H
|
#ifndef TRACKERSADDITION_H
|
||||||
@@ -67,4 +65,4 @@ private:
|
|||||||
BitTorrent::TorrentHandle *const m_torrent;
|
BitTorrent::TorrentHandle *const m_torrent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // TRACKERSADDITION_H
|
||||||
|
|||||||
@@ -53,9 +53,15 @@
|
|||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
#include "autoexpandabledialog.h"
|
#include "autoexpandabledialog.h"
|
||||||
#include "ui_automatedrssdownloader.h"
|
#include "ui_automatedrssdownloader.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
const QString EXT_JSON {QStringLiteral(".json")};
|
||||||
|
const QString EXT_LEGACY {QStringLiteral(".rssrules")};
|
||||||
|
|
||||||
AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
|
AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
|
, m_formatFilterJSON(QString("%1 (*%2)").arg(tr("Rules")).arg(EXT_JSON))
|
||||||
|
, m_formatFilterLegacy(QString("%1 (*%2)").arg(tr("Rules (legacy)")).arg(EXT_LEGACY))
|
||||||
, m_ui(new Ui::AutomatedRssDownloader)
|
, m_ui(new Ui::AutomatedRssDownloader)
|
||||||
, m_currentRuleItem(nullptr)
|
, m_currentRuleItem(nullptr)
|
||||||
{
|
{
|
||||||
@@ -150,14 +156,14 @@ AutomatedRssDownloader::~AutomatedRssDownloader()
|
|||||||
void AutomatedRssDownloader::loadSettings()
|
void AutomatedRssDownloader::loadSettings()
|
||||||
{
|
{
|
||||||
const Preferences *const pref = Preferences::instance();
|
const Preferences *const pref = Preferences::instance();
|
||||||
resize(pref->getRssGeometrySize(this->size()));
|
Utils::Gui::resize(this, pref->getRssGeometrySize());
|
||||||
m_ui->hsplitter->restoreState(pref->getRssHSplitterSizes());
|
m_ui->hsplitter->restoreState(pref->getRssHSplitterSizes());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutomatedRssDownloader::saveSettings()
|
void AutomatedRssDownloader::saveSettings()
|
||||||
{
|
{
|
||||||
Preferences *const pref = Preferences::instance();
|
Preferences *const pref = Preferences::instance();
|
||||||
pref->setRssGeometrySize(this->size());
|
pref->setRssGeometrySize(size());
|
||||||
pref->setRssHSplitterSizes(m_ui->hsplitter->saveState());
|
pref->setRssHSplitterSizes(m_ui->hsplitter->saveState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +312,7 @@ void AutomatedRssDownloader::initCategoryCombobox()
|
|||||||
{
|
{
|
||||||
// Load torrent categories
|
// Load torrent categories
|
||||||
QStringList categories = BitTorrent::Session::instance()->categories().keys();
|
QStringList categories = BitTorrent::Session::instance()->categories().keys();
|
||||||
std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive);
|
std::sort(categories.begin(), categories.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
||||||
m_ui->comboCategory->addItem("");
|
m_ui->comboCategory->addItem("");
|
||||||
m_ui->comboCategory->addItems(categories);
|
m_ui->comboCategory->addItems(categories);
|
||||||
}
|
}
|
||||||
@@ -384,31 +390,73 @@ void AutomatedRssDownloader::on_browseSP_clicked()
|
|||||||
|
|
||||||
void AutomatedRssDownloader::on_exportBtn_clicked()
|
void AutomatedRssDownloader::on_exportBtn_clicked()
|
||||||
{
|
{
|
||||||
// if (m_editableRuleList->isEmpty()) {
|
if (RSS::AutoDownloader::instance()->rules().isEmpty()) {
|
||||||
// QMessageBox::warning(this, tr("Invalid action"), tr("The list is empty, there is nothing to export."));
|
QMessageBox::warning(this, tr("Invalid action")
|
||||||
// return;
|
, tr("The list is empty, there is nothing to export."));
|
||||||
// }
|
return;
|
||||||
// // Ask for a save path
|
}
|
||||||
// QString save_path = QFileDialog::getSaveFileName(this, tr("Where would you like to save the list?"), QDir::homePath(), tr("Rules list (*.rssrules)"));
|
|
||||||
// if (save_path.isEmpty()) return;
|
QString selectedFilter {m_formatFilterJSON};
|
||||||
// if (!save_path.endsWith(".rssrules", Qt::CaseInsensitive))
|
QString path = QFileDialog::getSaveFileName(
|
||||||
// save_path += ".rssrules";
|
this, tr("Export RSS rules"), QDir::homePath()
|
||||||
// if (!m_editableRuleList->serialize(save_path)) {
|
, QString("%1;;%2").arg(m_formatFilterJSON).arg(m_formatFilterLegacy), &selectedFilter);
|
||||||
// QMessageBox::warning(this, tr("I/O Error"), tr("Failed to create the destination file"));
|
if (path.isEmpty()) return;
|
||||||
// return;
|
|
||||||
// }
|
const RSS::AutoDownloader::RulesFileFormat format {
|
||||||
|
(selectedFilter == m_formatFilterJSON)
|
||||||
|
? RSS::AutoDownloader::RulesFileFormat::JSON
|
||||||
|
: RSS::AutoDownloader::RulesFileFormat::Legacy
|
||||||
|
};
|
||||||
|
|
||||||
|
if (format == RSS::AutoDownloader::RulesFileFormat::JSON) {
|
||||||
|
if (!path.endsWith(EXT_JSON, Qt::CaseInsensitive))
|
||||||
|
path += EXT_JSON;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!path.endsWith(EXT_LEGACY, Qt::CaseInsensitive))
|
||||||
|
path += EXT_LEGACY;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file {path};
|
||||||
|
if (!file.open(QFile::WriteOnly)
|
||||||
|
|| (file.write(RSS::AutoDownloader::instance()->exportRules(format)) == -1)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("I/O Error")
|
||||||
|
, tr("Failed to create the destination file. Reason: %1").arg(file.errorString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutomatedRssDownloader::on_importBtn_clicked()
|
void AutomatedRssDownloader::on_importBtn_clicked()
|
||||||
{
|
{
|
||||||
// // Ask for filter path
|
QString selectedFilter {m_formatFilterJSON};
|
||||||
// QString load_path = QFileDialog::getOpenFileName(this, tr("Please point to the RSS download rules file"), QDir::homePath(), tr("Rules list") + QString(" (*.rssrules *.filters)"));
|
QString path = QFileDialog::getOpenFileName(
|
||||||
// if (load_path.isEmpty() || !QFile::exists(load_path)) return;
|
this, tr("Import RSS rules"), QDir::homePath()
|
||||||
// // Load it
|
, QString("%1;;%2").arg(m_formatFilterJSON).arg(m_formatFilterLegacy), &selectedFilter);
|
||||||
// if (!m_editableRuleList->unserialize(load_path)) {
|
if (path.isEmpty() || !QFile::exists(path))
|
||||||
// QMessageBox::warning(this, tr("Import Error"), tr("Failed to import the selected rules file"));
|
return;
|
||||||
// return;
|
|
||||||
// }
|
QFile file {path};
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("I/O Error")
|
||||||
|
, tr("Failed to open the file. Reason: %1").arg(file.errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RSS::AutoDownloader::RulesFileFormat format {
|
||||||
|
(selectedFilter == m_formatFilterJSON)
|
||||||
|
? RSS::AutoDownloader::RulesFileFormat::JSON
|
||||||
|
: RSS::AutoDownloader::RulesFileFormat::Legacy
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
RSS::AutoDownloader::instance()->importRules(file.readAll(),format);
|
||||||
|
}
|
||||||
|
catch (const RSS::ParsingError &error) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("Import Error")
|
||||||
|
, tr("Failed to import the selected rules file. Reason: %1").arg(error.message()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutomatedRssDownloader::displayRulesListMenu()
|
void AutomatedRssDownloader::displayRulesListMenu()
|
||||||
@@ -708,6 +756,7 @@ void AutomatedRssDownloader::handleRuleChanged(const QString &ruleName)
|
|||||||
|
|
||||||
void AutomatedRssDownloader::handleRuleAboutToBeRemoved(const QString &ruleName)
|
void AutomatedRssDownloader::handleRuleAboutToBeRemoved(const QString &ruleName)
|
||||||
{
|
{
|
||||||
|
m_currentRuleItem = nullptr;
|
||||||
delete m_itemsByRuleName.take(ruleName);
|
delete m_itemsByRuleName.take(ruleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ private:
|
|||||||
void updateFeedList();
|
void updateFeedList();
|
||||||
void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles);
|
void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles);
|
||||||
|
|
||||||
|
const QString m_formatFilterJSON;
|
||||||
|
const QString m_formatFilterLegacy;
|
||||||
|
|
||||||
Ui::AutomatedRssDownloader *m_ui;
|
Ui::AutomatedRssDownloader *m_ui;
|
||||||
QListWidgetItem *m_currentRuleItem;
|
QListWidgetItem *m_currentRuleItem;
|
||||||
QShortcut *m_editHotkey;
|
QShortcut *m_editHotkey;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user