1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-10-09 18:32:15 +02:00

Compare commits

...

24 Commits

Author SHA1 Message Date
sledgehammer999
118af03534 Bump to 4.2.1 2019-12-18 00:49:09 +02:00
sledgehammer999
596a71e03d Update Changelog 2019-12-18 00:44:50 +02:00
sledgehammer999
dab392645d Sync translations from Transifex and run lupdate 2019-12-18 00:33:46 +02:00
sledgehammer999
2d1fa9e154 Bump Web API version 2019-12-18 00:33:44 +02:00
sledgehammer999
3a63fabe9c Don't unnecessarily delete OS files in folders 2019-12-18 00:18:53 +02:00
sledgehammer999
3129712f03 Use the incomplete folder where appropriate
Restored torrents already have the correct path saved in their fastresume. Don't override it.
Magnets and new torrents have to be set explicitly to the incomplete folder if it is enabled.

Closes #11552
2019-12-18 00:18:52 +02:00
Tester798
66baf64e17 Enable portable mode if "profile" directory exists
Enable portable mode if "profile" directory exists in the app dir.
Remove "--portable" command line argument.
Add logging of current profile config directory.
Closes #9445.
2019-12-18 00:18:51 +02:00
Prince Gupta
1bdeab398a Align Properties tab bar correctly on window resize 2019-12-18 00:18:50 +02:00
sledgehammer999
2bda2a37e3 Rework the listening IP/interface selection code
Closes #11561
2019-12-18 00:18:48 +02:00
Chocobo1
027b605fc0 Enable "Apply rate limit to peers on LAN" option by default
Because some ISP will deploy Carrier Grade NAT (means assigning private
IP address to user) and thus accidentally circumvent the speed limiter.

https://www.a10networks.com/blog/carrier-grade-nat/
2019-12-18 00:18:47 +02:00
nl6720
87e1c80e28 Fix quoting of alert() in client.js
Fix alert() I broke in #11615 .
2019-12-18 00:18:46 +02:00
Thomas Piccirello
2d3efbc711 Add ability to rename torrent files from the WebUI
Renaming folders is not yet supported. Closes #8892.
2019-12-18 00:18:45 +02:00
Thomas Piccirello
8e394e0cdb Fix incorrect function being used 2019-12-18 00:18:44 +02:00
nl6720
0623c623d5 Mention lack of HTTPS in WebUI magnet link warning
According to Mozilla docs, registerProtocolHandler() is only
available when using secure contexts (i.e. HTTPS for everything
outside localhost).
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/registerProtocolHandler

The message "Your browser does not support this feature" does not
make this obvious and can lead to confusion if the user is using a
modern browser.
2019-12-18 00:18:42 +02:00
Luigi Baldoni
307d8ec360 Remove -march=native optimisation 2019-12-18 00:18:41 +02:00
Chocobo1
5a518d2f35 Fix incorrect translation displayed after language change
It is expected in WebUI that the language change applies immediately
(without a program restart) and this static caching prevents that.
2019-12-18 00:18:40 +02:00
Chocobo1
93fe20afcd Fix HTML elements size in search tab
Specifying a height/width value might cut the displayed text or
obstruct centering the text in the button, so let it auto decide
instead.
Closes #11553.
2019-12-18 00:18:39 +02:00
Chocobo1
7f217110cd Fix missing translations in search plugins dialog
Closes #11551.
2019-12-18 00:18:37 +02:00
Andrei Stepanov
4e7b33fadf Update russian.nsi 2019-12-18 00:18:36 +02:00
Chocobo1
7926d1755f Fix inconsistent icon for deleting torrent
Closes #11565.
2019-12-18 00:18:35 +02:00
Chocobo1
3a13a3d5ca Show torrent error message in transfer list 2019-12-18 00:18:34 +02:00
Chocobo1
caa8e1658a Fix stuck in wrong torrent state
Before this patch, adding the torrent in
https://github.com/qbittorrent/qBittorrent/issues/11511 and the torrrent
state will stay in torrent_status::checking_resume_data forever.
This is not the correct state since the `torrent_status.errc` field is
non-zero and this commit fixes it.
2019-12-18 00:18:33 +02:00
warren
890ccb7b84 Expand single-item folders in torrent content 2019-12-18 00:18:25 +02:00
sledgehammer999
912b076707 Bump to 4.2.0 2019-12-03 01:19:18 +02:00
140 changed files with 20767 additions and 15204 deletions

View File

@@ -1,3 +1,23 @@
Wed Dec 18 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.1
- FEATURE: Enable portable mode if "profile" directory exists (Tester798)
- FEATURE: Enable "Apply rate limit to peers on LAN" option by default (Chocobo1)
- BUGFIX: Sync translations from Transifex and run lupdate (sledgehammer999)
- BUGFIX: Don't unnecessarily delete OS files in folders (sledgehammer999)
- BUGFIX: Use the incomplete folder where appropriate (sledgehammer999)
- BUGFIX: Align Properties tab bar correctly on window resize (Prince Gupta)
- BUGFIX: Rework the listening IP/interface selection code (sledgehammer999)
- BUGFIX: Fix inconsistent icon for deleting torrent (Chocobo1)
- BUGFIX: Show torrent error message in transfer list (Chocobo1)
- BUGFIX: Fix stuck in wrong torrent state (Chocobo1)
- BUGFIX: Expand single-item folders in torrent content (warren)
- WEBUI: Bump Web API version (sledgehammer999)
- WEBUI: Add ability to rename torrent files from the WebUI (Thomas Piccirello)
- WEBUI: Mention lack of HTTPS in WebUI magnet link warning (nl6720)
- WEBUI: Fix HTML elements size in search tab (Chocobo1)
- SEARCH: Fix incorrect translation displayed after language change (Chocobo1)
- SEARCH: Fix missing translations in search plugins dialog (Chocobo1)
- WINDOWS: Update russian translation of the installer (Andrei Stepanov)
Tue Dec 03 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.2.0
- FEATURE: Libtorrent 1.2.x series are supported now (glassez)
- FEATURE: Add OpenSSL version to GUI and stackdump (Chocobo1)

View File

@@ -74,18 +74,17 @@ macro(qbt_set_compiler_options)
string(APPEND CMAKE_CXX_FLAGS " ${_GCC_COMMON_C_AND_CXX_FLAGS_STRING} ${_GCC_COMMON_CXX_FLAGS_STRING}")
# check whether we can enable -Og optimization for debug build
# also let's enable -march=native for debug builds
check_cxx_compiler_flag(-Og _DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED)
if (_DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED)
set(QBT_ADDITONAL_FLAGS "-Og -g3 -march=native -pipe" CACHE STRING
set(QBT_ADDITONAL_FLAGS "-Og -g3 -pipe" CACHE STRING
"Additional qBittorent compile flags")
set(QBT_ADDITONAL_CXX_FLAGS "-Og -g3 -march=native -pipe" CACHE STRING
set(QBT_ADDITONAL_CXX_FLAGS "-Og -g3 -pipe" CACHE STRING
"Additional qBittorent C++ compile flags")
else(_DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED)
set(QBT_ADDITONAL_FLAGS "-O0 -g3 -march=native -pipe" CACHE STRING
set(QBT_ADDITONAL_FLAGS "-O0 -g3 -pipe" CACHE STRING
"Additional qBittorent compile flags")
set(QBT_ADDITONAL_CXX_FLAGS "-O0 -g3 -march=native -pipe" CACHE STRING
set(QBT_ADDITONAL_CXX_FLAGS "-O0 -g3 -pipe" CACHE STRING
"Additional qBittorent C++ compile flags")
endif (_DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED)
endif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")

24
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for qbittorrent v4.2.0alpha.
# Generated by GNU Autoconf 2.69 for qbittorrent v4.2.1.
#
# Report bugs to <bugs.qbittorrent.org>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='qbittorrent'
PACKAGE_TARNAME='qbittorrent'
PACKAGE_VERSION='v4.2.0alpha'
PACKAGE_STRING='qbittorrent v4.2.0alpha'
PACKAGE_VERSION='v4.2.1'
PACKAGE_STRING='qbittorrent v4.2.1'
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
PACKAGE_URL='https://www.qbittorrent.org/'
@@ -1302,7 +1302,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures qbittorrent v4.2.0alpha to adapt to many kinds of systems.
\`configure' configures qbittorrent v4.2.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1373,7 +1373,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of qbittorrent v4.2.0alpha:";;
short | recursive ) echo "Configuration of qbittorrent v4.2.1:";;
esac
cat <<\_ACEOF
@@ -1509,7 +1509,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
qbittorrent configure v4.2.0alpha
qbittorrent configure v4.2.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1648,7 +1648,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by qbittorrent $as_me v4.2.0alpha, which was
It was created by qbittorrent $as_me v4.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3826,7 +3826,7 @@ fi
# Define the identity of the package.
PACKAGE='qbittorrent'
VERSION='v4.2.0alpha'
VERSION='v4.2.1'
cat >>confdefs.h <<_ACEOF
@@ -6343,7 +6343,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by qbittorrent $as_me v4.2.0alpha, which was
This file was extended by qbittorrent $as_me v4.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6401,7 +6401,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
qbittorrent config.status v4.2.0alpha
qbittorrent config.status v4.2.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -7659,7 +7659,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by qbittorrent $as_me v4.2.0alpha, which was
This file was extended by qbittorrent $as_me v4.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -7717,7 +7717,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
qbittorrent config.status v4.2.0alpha
qbittorrent config.status v4.2.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@@ -1,4 +1,4 @@
AC_INIT([qbittorrent], [v4.2.0alpha], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_INIT([qbittorrent], [v4.2.1], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC

2
dist/mac/Info.plist vendored
View File

@@ -55,7 +55,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>4.2.0</string>
<string>4.2.1</string>
<key>CFBundleExecutable</key>
<string>@EXECUTABLE@</string>
<key>CFBundleIdentifier</key>

View File

@@ -9,23 +9,23 @@ LangString inst_startmenu ${LANG_RUSSIAN} "Создать ярлык в меню
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_RUSSIAN} "Открывать торрент-файлы с помощью qBittorrent"
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_RUSSIAN} "Открывать magnet-ссылки с помощью qBittorrent"
LangString inst_magnet ${LANG_RUSSIAN} "Открывать магнет-ссылки с помощью qBittorrent"
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_RUSSIAN} "Добавить в список исключений брандмауера"
LangString inst_firewall ${LANG_RUSSIAN} "Добавить в список исключений брандмауэра"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_RUSSIAN} "Добавление в список исключений брандмауера"
LangString inst_firewallinfo ${LANG_RUSSIAN} "Добавление в список исключений брандмауэра"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_RUSSIAN} "qBittorrent запущен. Пожалуйста, закройте qBittorrent и перезапустите программу установки."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_RUSSIAN} "Обнаружена предыдущая установка. Она будет деинсталлирована без удаления пользовательских настроек."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_RUSSIAN} "Деинсталлируем старую версию."
LangString inst_unist ${LANG_RUSSIAN} "Деинсталлируется старая версия."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
LangString launch_qbt ${LANG_RUSSIAN} "Запустить qBittorrent."
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_RUSSIAN} "Этот установщик работает только на 64-битных версиях Windows."
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
LangString inst_requires_win7 ${LANG_RUSSIAN} "This qBittorrent version requires at least Windows 7."
LangString inst_requires_win7 ${LANG_RUSSIAN} "Для работы этой версии qBittorrent требуется Windows 7 или выше."
;------------------------------------
@@ -42,9 +42,9 @@ LangString remove_registry ${LANG_RUSSIAN} "Удалить данные из р
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
LangString remove_conf ${LANG_RUSSIAN} "Удалить пользовательские настройки"
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_RUSSIAN} "Удалить из списка исключений брандмауера"
LangString remove_firewall ${LANG_RUSSIAN} "Удалить из списка исключений брандмауэра"
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_RUSSIAN} "Удаление из списка исключений брандмауера"
LangString remove_firewallinfo ${LANG_RUSSIAN} "Удаление из списка исключений брандмауэра"
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_RUSSIAN} "Удалить сохранённые торрент-файлы"
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
@@ -52,4 +52,4 @@ LangString uninst_warning ${LANG_RUSSIAN} "qBittorrent запущен. Пожа
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_RUSSIAN} "Ассоциации торрент-файлов не сброшены. Уже ассоциированы с:"
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_RUSSIAN} "Ассоциации magnet-ссылок не сброшены. Уже ассоциированы с:"
LangString uninst_mag_warn ${LANG_RUSSIAN} "Ассоциации магнет-ссылок не сброшены. Уже ассоциированы с:"

View File

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

View File

@@ -144,13 +144,13 @@ Application::Application(const QString &id, int &argc, char **argv)
QPixmapCache::setCacheLimit(PIXMAP_CACHE_SIZE);
#endif
validateCommandLineParameters();
const bool portableModeEnabled = m_commandLineArgs.profileDir.isEmpty() && QDir(QCoreApplication::applicationDirPath()).exists(DEFAULT_PORTABLE_MODE_PROFILE_DIR);
const QString profileDir = m_commandLineArgs.portableMode
const QString profileDir = portableModeEnabled
? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR)
: m_commandLineArgs.profileDir;
Profile::initialize(profileDir, m_commandLineArgs.configurationName,
m_commandLineArgs.relativeFastresumePaths || m_commandLineArgs.portableMode);
(m_commandLineArgs.relativeFastresumePaths || portableModeEnabled));
Logger::initInstance();
SettingsStorage::initInstance();
@@ -171,6 +171,14 @@ Application::Application(const QString &id, int &argc, char **argv)
m_fileLogger = new FileLogger(fileLoggerPath(), isFileLoggerBackup(), fileLoggerMaxSize(), isFileLoggerDeleteOld(), fileLoggerAge(), static_cast<FileLogger::FileLogAgeType>(fileLoggerAgeType()));
Logger::instance()->addMessage(tr("qBittorrent %1 started", "qBittorrent v3.2.0alpha started").arg(QBT_VERSION));
if (portableModeEnabled) {
Logger::instance()->addMessage(tr("Running in portable mode. Auto detected profile folder at: %1").arg(profileDir));
if (m_commandLineArgs.relativeFastresumePaths)
Logger::instance()->addMessage(tr("Redundant command line flag detected: \"%1\". Portable mode implies relative fastresume.").arg("--relative-fastresume"), Log::WARNING); // to avoid translating the `--relative-fastresume` string
}
else {
Logger::instance()->addMessage(tr("Using config directory: %1").arg(Profile::instance().location(SpecialFolder::Config)));
}
}
Application::~Application()
@@ -737,12 +745,3 @@ void Application::cleanup()
Utils::Misc::shutdownComputer(m_shutdownAct);
}
}
void Application::validateCommandLineParameters()
{
if (m_commandLineArgs.portableMode && !m_commandLineArgs.profileDir.isEmpty())
throw CommandLineParameterError(tr("Portable mode and explicit profile directory options are mutually exclusive"));
if (m_commandLineArgs.portableMode && m_commandLineArgs.relativeFastresumePaths)
Logger::instance()->addMessage(tr("Portable mode implies relative fastresume"), Log::WARNING);
}

View File

@@ -144,5 +144,4 @@ private:
void processParams(const QStringList &params);
void runExternalProgram(const BitTorrent::TorrentHandle *torrent) const;
void sendNotificationEmail(const BitTorrent::TorrentHandle *torrent);
void validateCommandLineParameters();
};

View File

@@ -318,7 +318,6 @@ namespace
constexpr const IntOption WEBUI_PORT_OPTION {"webui-port"};
constexpr const StringOption PROFILE_OPTION {"profile"};
constexpr const StringOption CONFIGURATION_OPTION {"configuration"};
constexpr const BoolOption PORTABLE_OPTION {"portable"};
constexpr const BoolOption RELATIVE_FASTRESUME {"relative-fastresume"};
constexpr const StringOption SAVE_PATH_OPTION {"save-path"};
constexpr const TriStateBoolOption PAUSED_OPTION {"add-paused", true};
@@ -332,7 +331,6 @@ namespace
QBtCommandLineParameters::QBtCommandLineParameters(const QProcessEnvironment &env)
: showHelp(false)
, relativeFastresumePaths(RELATIVE_FASTRESUME.value(env))
, portableMode(PORTABLE_OPTION.value(env))
, skipChecking(SKIP_HASH_CHECK_OPTION.value(env))
, sequential(SEQUENTIAL_OPTION.value(env))
, firstLastPiecePriority(FIRST_AND_LAST_OPTION.value(env))
@@ -437,9 +435,6 @@ QBtCommandLineParameters parseCommandLine(const QStringList &args)
else if (arg == RELATIVE_FASTRESUME) {
result.relativeFastresumePaths = true;
}
else if (arg == PORTABLE_OPTION) {
result.portableMode = true;
}
else if (arg == CONFIGURATION_OPTION) {
result.configurationName = CONFIGURATION_OPTION.value(arg);
}
@@ -544,9 +539,6 @@ QString makeUsage(const QString &prgName)
stream << RELATIVE_FASTRESUME.usage()
<< wrapText(QObject::tr("Hack into libtorrent fastresume files and make file paths relative "
"to the profile directory")) << '\n';
stream << PORTABLE_OPTION.usage()
<< wrapText(QObject::tr("Shortcut for %1", "Shortcut for --profile=<exe dir>/profile --relative-fastresume")
.arg(QLatin1String("--profile=<exe dir>/profile --relative-fastresume"))) << '\n';
stream << Option::padUsageText(QObject::tr("files or URLs"))
<< wrapText(QObject::tr("Download the torrents passed by the user")) << '\n'
<< '\n';

View File

@@ -42,7 +42,7 @@ class QProcessEnvironment;
struct QBtCommandLineParameters
{
bool showHelp, relativeFastresumePaths, portableMode, skipChecking, sequential, firstLastPiecePriority;
bool showHelp, relativeFastresumePaths, skipChecking, sequential, firstLastPiecePriority;
#if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
bool showVersion;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -303,8 +303,6 @@ namespace BitTorrent
void setNetworkInterfaceName(const QString &name);
QString networkInterfaceAddress() const;
void setNetworkInterfaceAddress(const QString &address);
bool isIPv6Enabled() const;
void setIPv6Enabled(bool enabled);
int encryption() const;
void setEncryption(int state);
bool isProxyPeerConnectionsEnabled() const;
@@ -532,6 +530,7 @@ namespace BitTorrent
void configureComponents();
void initializeNativeSession();
void loadLTSettings(lt::settings_pack &settingsPack);
void configureNetworkInterfaces(lt::settings_pack &settingsPack);
void configurePeerClasses();
void adjustLimits(lt::settings_pack &settingsPack);
void applyBandwidthLimits(lt::settings_pack &settingsPack) const;
@@ -662,7 +661,6 @@ namespace BitTorrent
CachedSettingValue<QString> m_networkInterface;
CachedSettingValue<QString> m_networkInterfaceName;
CachedSettingValue<QString> m_networkInterfaceAddress;
CachedSettingValue<bool> m_isIPv6Enabled;
CachedSettingValue<int> m_encryption;
CachedSettingValue<bool> m_isProxyPeerConnectionsEnabled;
CachedSettingValue<ChokingAlgorithm> m_chokingAlgorithm;

View File

@@ -899,7 +899,10 @@ TorrentState TorrentHandle::state() const
void TorrentHandle::updateState()
{
if (m_nativeStatus.state == lt::torrent_status::checking_resume_data) {
if (hasError()) {
m_state = TorrentState::Error;
}
else if (m_nativeStatus.state == lt::torrent_status::checking_resume_data) {
m_state = TorrentState::CheckingResumeData;
}
else if (isMoveInProgress()) {
@@ -908,8 +911,6 @@ void TorrentHandle::updateState()
else if (isPaused()) {
if (hasMissingFiles())
m_state = TorrentState::MissingFiles;
else if (hasError())
m_state = TorrentState::Error;
else
m_state = isSeed() ? TorrentState::PausedUploading : TorrentState::PausedDownloading;
}
@@ -961,12 +962,7 @@ bool TorrentHandle::hasMissingFiles() const
bool TorrentHandle::hasError() const
{
#if (LIBTORRENT_VERSION_NUM < 10200)
return (m_nativeStatus.paused && m_nativeStatus.errc);
#else
return ((m_nativeStatus.flags & lt::torrent_flags::paused)
&& m_nativeStatus.errc);
#endif
return static_cast<bool>(m_nativeStatus.errc);
}
bool TorrentHandle::hasFilteredPieces() const

View File

@@ -318,7 +318,7 @@ SearchHandler *SearchPluginManager::startSearch(const QString &pattern, const QS
QString SearchPluginManager::categoryFullName(const QString &categoryName)
{
static const QHash<QString, QString> categoryTable {
const QHash<QString, QString> categoryTable {
{"all", tr("All categories")},
{"movies", tr("Movies")},
{"tv", tr("TV shows")},

View File

@@ -86,7 +86,6 @@ namespace
{"BitTorrent/Session/BandwidthSchedulerEnabled", "Preferences/Scheduler/Enabled"},
{"BitTorrent/Session/Port", "Preferences/Connection/PortRangeMin"},
{"BitTorrent/Session/UseRandomPort", "Preferences/General/UseRandomPort"},
{"BitTorrent/Session/IPv6Enabled", "Preferences/Connection/InterfaceListenIPv6"},
{"BitTorrent/Session/Interface", "Preferences/Connection/Interface"},
{"BitTorrent/Session/InterfaceName", "Preferences/Connection/InterfaceName"},
{"BitTorrent/Session/InterfaceAddress", "Preferences/Connection/InterfaceAddress"},

View File

@@ -99,9 +99,13 @@ QString Utils::Fs::folderName(const QString &filePath)
}
/**
* This function will first remove system cache files, e.g. `Thumbs.db`,
* `.DS_Store`. Then will try to remove the whole tree if the tree consist
* only of folders
* This function will first check if there are only system cache files, e.g. `Thumbs.db`,
* `.DS_Store` and/or only temp files that end with '~', e.g. `filename~`.
* If they are the only files it will try to remove them and delete the folder.
* This action will be performed for each subfolder starting from the deepest folder.
* There is an inherent race condition here. A file might appear after it is checked
* that only the above mentioned "useless" files exist but before the whole folder is removed.
* In this case, the folder will not be removed but the "useless" files will be deleted.
*/
bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
{
@@ -110,12 +114,12 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
const QStringList deleteFilesList = {
// Windows
"Thumbs.db",
"desktop.ini",
QLatin1String("Thumbs.db"),
QLatin1String("desktop.ini"),
// Linux
".directory",
QLatin1String(".directory"),
// Mac OS
".DS_Store"
QLatin1String(".DS_Store")
};
// travel from the deepest folder and remove anything unwanted on the way out.
@@ -128,18 +132,25 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
, [](const QString &l, const QString &r) { return l.count('/') > r.count('/'); });
for (const QString &p : asConst(dirList)) {
// remove unwanted files
for (const QString &f : deleteFilesList) {
forceRemove(p + f);
}
// remove temp files on linux (file ends with '~'), e.g. `filename~`
const QDir dir(p);
// A deeper folder may have not been removed in the previous iteration
// so don't remove anything from this folder either.
if (!dir.isEmpty(QDir::Dirs | QDir::NoDotAndDotDot))
continue;
const QStringList tmpFileList = dir.entryList(QDir::Files);
for (const QString &f : tmpFileList) {
if (f.endsWith('~'))
forceRemove(p + f);
}
// deleteFilesList contains unwanted files, usually created by the OS
// temp files on linux usually end with '~', e.g. `filename~`
const bool hasOtherFiles = std::any_of(tmpFileList.cbegin(), tmpFileList.cend(), [&deleteFilesList](const QString &f)
{
return (!f.endsWith('~') && !deleteFilesList.contains(f, Qt::CaseInsensitive));
});
if (hasOtherFiles)
continue;
for (const QString &f : tmpFileList)
forceRemove(p + f);
// remove directory if empty
dir.rmdir(p);

View File

@@ -28,6 +28,7 @@
#include "net.h"
#include <QNetworkInterface>
#include <QSslCertificate>
#include <QSslKey>
#include <QString>
@@ -91,6 +92,37 @@ namespace Utils
return subnet.first.toString() + '/' + QString::number(subnet.second);
}
QHostAddress canonicalIPv6Addr(const QHostAddress &addr)
{
// Link-local IPv6 textual address always contains a scope id (or zone index)
// The scope id is appended to the IPv6 address using the '%' character
// The scope id can be either a interface name or an interface number
// Examples:
// fe80::1%ethernet_17
// fe80::1%13
// The interface number is the mandatory supported way
// Unfortunately for us QHostAddress::toString() outputs (at least on Windows)
// the interface name, and libtorrent/boost.asio only support an interface number
// as scope id. Furthermore, QHostAddress doesn't have any convenient method to
// affect this, so we jump through hoops here.
if (addr.protocol() != QAbstractSocket::IPv6Protocol)
return QHostAddress{addr.toIPv6Address()};
// QHostAddress::setScopeId(addr.scopeId()); // Even though the docs say that setScopeId
// will convert a name to a number, this doesn't happen. Probably a Qt bug.
const QString scopeIdTxt = addr.scopeId();
if (scopeIdTxt.isEmpty())
return addr;
const int id = QNetworkInterface::interfaceIndexFromName(scopeIdTxt);
if (id == 0) // This failure might mean that the scope id was already a number
return addr;
QHostAddress canonical(addr.toIPv6Address());
canonical.setScopeId(QString::number(id));
return canonical;
}
QList<QSslCertificate> loadSSLCertificate(const QByteArray &data)
{
const QList<QSslCertificate> certs {QSslCertificate::fromData(data)};

View File

@@ -50,6 +50,7 @@ namespace Utils
bool isLoopbackAddress(const QHostAddress &addr);
bool isIPInRange(const QHostAddress &addr, const QVector<Subnet> &subnets);
QString subnetToString(const Subnet &subnet);
QHostAddress canonicalIPv6Addr(const QHostAddress &addr);
const int MAX_SSL_FILE_SIZE = 1024 * 1024;
QList<QSslCertificate> loadSSLCertificate(const QByteArray &data);

View File

@@ -625,8 +625,12 @@ void AddNewTorrentDialog::setupTreeview()
m_ui->contentTreeView->hideColumn(REMAINING);
m_ui->contentTreeView->hideColumn(AVAILABILITY);
// Expand root folder
m_ui->contentTreeView->setExpanded(m_contentModel->index(0, 0), true);
// Expand single-item folders recursively
QModelIndex currentIndex;
while (m_contentModel->rowCount(currentIndex) == 1) {
currentIndex = m_contentModel->index(0, 0, currentIndex);
m_ui->contentTreeView->setExpanded(currentIndex, true);
}
}
updateDiskSpaceLabel();

View File

@@ -68,7 +68,6 @@ enum AdvSettingsRows
NETWORK_IFACE,
//Optional network address
NETWORK_IFACE_ADDRESS,
NETWORK_LISTEN_IPV6,
// behavior
SAVE_RESUME_DATA_INTERVAL,
CONFIRM_RECHECK_TORRENT,
@@ -227,18 +226,14 @@ void AdvancedSettings::saveAdvancedSettings()
}
// Interface address
if (m_comboBoxInterfaceAddress.currentIndex() == 0) {
// All addresses (default)
session->setNetworkInterfaceAddress({});
}
else {
QHostAddress ifaceAddr(m_comboBoxInterfaceAddress.currentText().trimmed());
ifaceAddr.isNull() ? session->setNetworkInterfaceAddress({}) : session->setNetworkInterfaceAddress(ifaceAddr.toString());
}
session->setIPv6Enabled(m_checkBoxListenIPv6.isChecked());
// Construct a QHostAddress to filter malformed strings
const QHostAddress ifaceAddr(m_comboBoxInterfaceAddress.currentData().toString().trimmed());
session->setNetworkInterfaceAddress(ifaceAddr.toString());
// Announce IP
QHostAddress addr(m_lineEditAnnounceIP.text().trimmed());
session->setAnnounceIP(addr.isNull() ? "" : addr.toString());
// Construct a QHostAddress to filter malformed strings
const QHostAddress addr(m_lineEditAnnounceIP.text().trimmed());
session->setAnnounceIP(addr.toString());
// Program notification
MainWindow *const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();
@@ -295,33 +290,35 @@ void AdvancedSettings::updateInterfaceAddressCombo()
// Clear all items and reinsert them, default to all
m_comboBoxInterfaceAddress.clear();
m_comboBoxInterfaceAddress.addItem(tr("All addresses"));
m_comboBoxInterfaceAddress.setCurrentIndex(0);
m_comboBoxInterfaceAddress.addItem(tr("All addresses"), {});
m_comboBoxInterfaceAddress.addItem(tr("All IPv4 addresses"), QLatin1String("0.0.0.0"));
m_comboBoxInterfaceAddress.addItem(tr("All IPv6 addresses"), QLatin1String("::"));
auto populateCombo = [this, &currentAddress](const QString &ip, const QAbstractSocket::NetworkLayerProtocol &protocol)
const auto populateCombo = [this, &currentAddress](const QHostAddress &addr)
{
Q_ASSERT((protocol == QAbstractSocket::IPv4Protocol) || (protocol == QAbstractSocket::IPv6Protocol));
// Only take ipv4 for now?
if ((protocol != QAbstractSocket::IPv4Protocol) && (protocol != QAbstractSocket::IPv6Protocol))
return;
m_comboBoxInterfaceAddress.addItem(ip);
//Try to select the last added one
if (ip == currentAddress)
m_comboBoxInterfaceAddress.setCurrentIndex(m_comboBoxInterfaceAddress.count() - 1);
if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
const QString str = addr.toString();
m_comboBoxInterfaceAddress.addItem(str, str);
}
else if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
const QString str = Utils::Net::canonicalIPv6Addr(addr).toString();
m_comboBoxInterfaceAddress.addItem(str, str);
}
};
if (ifaceName.isEmpty()) {
for (const QHostAddress &ip : asConst(QNetworkInterface::allAddresses()))
populateCombo(ip.toString(), ip.protocol());
for (const QHostAddress &addr : asConst(QNetworkInterface::allAddresses()))
populateCombo(addr);
}
else {
const QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName);
const QList<QNetworkAddressEntry> addresses = iface.addressEntries();
for (const QNetworkAddressEntry &entry : addresses) {
const QHostAddress ip = entry.ip();
populateCombo(ip.toString(), ip.protocol());
}
for (const QNetworkAddressEntry &entry : addresses)
populateCombo(entry.ip());
}
const int index = m_comboBoxInterfaceAddress.findData(currentAddress);
m_comboBoxInterfaceAddress.setCurrentIndex(std::max(index, 0));
}
void AdvancedSettings::loadAdvancedSettings()
@@ -524,9 +521,6 @@ void AdvancedSettings::loadAdvancedSettings()
// Network interface address
updateInterfaceAddressCombo();
addRow(NETWORK_IFACE_ADDRESS, tr("Optional IP Address to bind to (requires restart)"), &m_comboBoxInterfaceAddress);
// Listen on IPv6 address
m_checkBoxListenIPv6.setChecked(session->isIPv6Enabled());
addRow(NETWORK_LISTEN_IPV6, tr("Listen on IPv6 address (requires restart)"), &m_checkBoxListenIPv6);
// Announce IP
m_lineEditAnnounceIP.setText(session->announceIP());
addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &m_lineEditAnnounceIP);

View File

@@ -63,7 +63,7 @@ private:
m_spinBoxSendBufferWatermarkFactor, m_spinBoxSocketBacklogSize, m_spinBoxSavePathHistoryLength;
QCheckBox m_checkBoxOsCache, m_checkBoxRecheckCompleted, m_checkBoxResolveCountries, m_checkBoxResolveHosts, m_checkBoxSuperSeeding,
m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus,
m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxListenIPv6, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers,
m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers,
m_checkBoxMultiConnectionsPerIp, m_checkBoxSuggestMode, m_checkBoxCoalesceRW, m_checkBoxSpeedWidgetEnabled;
QComboBox m_comboBoxInterface, m_comboBoxInterfaceAddress, m_comboBoxUtpMixedMode, m_comboBoxChokingAlgorithm, m_comboBoxSeedChokingAlgorithm;
QLineEdit m_lineEditAnnounceIP;

View File

@@ -194,13 +194,15 @@ void PropertiesWidget::showPiecesDownloaded(bool show)
void PropertiesWidget::setVisibility(bool visible)
{
if (!visible && (m_state == VISIBLE)) {
const int tabBarHeight = m_tabBar->geometry().height(); // take height before hiding
auto *hSplitter = static_cast<QSplitter *>(parentWidget());
m_ui->stackedProperties->setVisible(false);
m_slideSizes = hSplitter->sizes();
hSplitter->handle(1)->setVisible(false);
hSplitter->handle(1)->setDisabled(true);
QList<int> sizes = QList<int>() << hSplitter->geometry().height() - 30 << 30;
const QList<int> sizes {(hSplitter->geometry().height() - tabBarHeight), tabBarHeight};
hSplitter->setSizes(sizes);
setMaximumSize(maximumSize().width(), tabBarHeight);
m_state = REDUCED;
return;
}
@@ -212,6 +214,7 @@ void PropertiesWidget::setVisibility(bool visible)
hSplitter->handle(1)->setVisible(true);
hSplitter->setSizes(m_slideSizes);
m_state = VISIBLE;
setMaximumSize(maximumSize().width(), QWIDGETSIZE_MAX);
// Force refresh
loadDynamicData();
}
@@ -322,8 +325,13 @@ void PropertiesWidget::loadTorrentInfos(BitTorrent::TorrentHandle *const torrent
// List files in torrent
m_propListModel->model()->setupModelData(m_torrent->info());
if (m_propListModel->model()->rowCount() == 1)
m_ui->filesList->setExpanded(m_propListModel->index(0, 0), true);
// Expand single-item folders recursively
QModelIndex currentIndex;
while (m_propListModel->rowCount(currentIndex) == 1) {
currentIndex = m_propListModel->index(0, 0, currentIndex);
m_ui->filesList->setExpanded(currentIndex, true);
}
// Load file priorities
m_propListModel->model()->updateFilesPriorities(m_torrent->filePriorities());

View File

@@ -100,7 +100,10 @@ void TransferListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
break;
case TransferListModel::TR_STATUS: {
const auto state = index.data().value<BitTorrent::TorrentState>();
const QString errorMsg = index.data(Qt::UserRole).toString();
QString display = getStatusString(state);
if (state == BitTorrent::TorrentState::Error)
display += (": " + errorMsg);
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
}
break;

View File

@@ -184,7 +184,7 @@ QVariant TransferListModel::data(const QModelIndex &index, const int role) const
case TR_PROGRESS:
return torrent->progress();
case TR_STATUS:
return QVariant::fromValue(torrent->state());
return (role == Qt::DisplayRole) ? QVariant::fromValue(torrent->state()) : torrent->error();
case TR_SEEDS:
return (role == Qt::DisplayRole) ? torrent->seedsCount() : torrent->totalSeedsCount();
case TR_PEERS:

View File

@@ -857,7 +857,7 @@ void TransferListWidget::displayListMenu(const QPoint &)
connect(actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents);
auto *actionForceStart = new QAction(UIThemeManager::instance()->getIcon("media-seek-forward"), tr("Force Resume", "Force Resume/start the torrent"), listMenu);
connect(actionForceStart, &QAction::triggered, this, &TransferListWidget::forceStartSelectedTorrents);
auto *actionDelete = new QAction(UIThemeManager::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), listMenu);
auto *actionDelete = new QAction(UIThemeManager::instance()->getIcon("list-remove"), tr("Delete", "Delete the torrent"), listMenu);
connect(actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents);
auto *actionPreviewFile = new QAction(UIThemeManager::instance()->getIcon("view-preview"), tr("Preview file..."), listMenu);
connect(actionPreviewFile, &QAction::triggered, this, &TransferListWidget::previewSelectedTorrents);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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