1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-10-14 11:52:15 +02:00

Compare commits

...

29 Commits

Author SHA1 Message Date
sledgehammer999
480e3f02ca Bump to 4.5.0 2022-11-26 23:16:23 +02:00
sledgehammer999
6b05c716a8 Update Changelog 2022-11-26 23:13:55 +02:00
sledgehammer999
c697829b1b Sync translations from Transifex and run lupdate 2022-11-26 23:12:44 +02:00
sledgehammer999
9a2ec6912b Merge pull request #18061 from sledgehammer999/fix_blocker
Temporarily fix blocker for v4_5_x
2022-11-26 23:09:34 +02:00
sledgehammer999
7601163d32 Revert "Destroy object within appropriate thread"
Temporary solution for #18059

This reverts commit 4f2ac34440.
2022-11-26 21:31:13 +02:00
sledgehammer999
8e2bda2b7a Update Changelog 2022-11-21 01:14:46 +02:00
sledgehammer999
1761f6c58e Update Changelog 2022-11-21 01:14:46 +02:00
sledgehammer999
419cdde4e1 Merge pull request #18043 from glassez/backport1
Prevent object from being used after destruction
2022-11-20 20:57:50 +02:00
sledgehammer999
6ec46a90d1 Merge pull request #18042 from glassez/backport
Revert "Use another workaround to update files tree view"
2022-11-20 20:57:37 +02:00
Vladimir Golovnev (Glassez)
f4051034d7 Prevent object from being used after destruction 2022-11-20 15:06:03 +03:00
Vladimir Golovnev (glassez)
1a8ba00f2c Revert "Use another workaround to update files tree view"
This reverts commit 0f82c16936.
2022-11-20 13:54:42 +03:00
Vladimir Golovnev
de4c1c9265 Don't miss to store metadata of new torrent
PR #18032.
2022-11-19 07:06:52 +03:00
sledgehammer999
bff9189e52 Merge pull request #18014 from sledgehammer999/maybe_backport
Backports to v4_5_x
2022-11-14 17:16:32 +02:00
Vladimir Golovnev
076b3628b1 Save correct resume data when added new torrent
PR #18003.
2022-11-13 21:30:39 +02:00
Vladimir Golovnev (Glassez)
75ccce705e Correctly handle model resetting 2022-11-13 21:30:38 +02:00
Vladimir Golovnev (Glassez)
964bf31775 Use another workaround to update files tree view 2022-11-13 21:30:38 +02:00
Vladimir Golovnev
507ced2fa2 Avoid blocking call when changing libtorrent session settings
We don't really need to get currently used settings pack in order to apply changes to session settings. It is enough to apply settings pack that contains only updated settings.

PR #17989.
2022-11-13 21:30:37 +02:00
Chocobo1
e62f9ef56a Move increment out of loop 2022-11-13 21:28:28 +02:00
Chocobo1
a5a242377b Clean up code 2022-11-13 21:28:28 +02:00
Chocobo1
0758109d15 Reserve space before appending elements 2022-11-13 21:28:28 +02:00
Chocobo1
3970d91d19 Fix typos 2022-11-13 21:28:27 +02:00
BallsOfSpaghetti
4e98b7f0cf Add confirmation to resume/pause all
This adds a confirmation dialog to Pause All and Resume All. First I wanted to only add it in Tray, but honestly, clicking around in the menu, using hotkeys might trigger it just as easy.

Closes #17683.
PR #17945.
2022-11-13 21:28:27 +02:00
sledgehammer999
27a69d9cca Fine tune translations loading for Chinese locales
Closes #17506
2022-11-13 21:28:26 +02:00
Chocobo1
d884ec1731 Add port forwarding option for embedded tracker
Closes #17781.
PR #17981.
2022-11-13 21:28:26 +02:00
Vladimir Golovnev
62b2959cb4 Don't use extra variable to distinguish restored torrents
PR #17984.
2022-11-13 21:28:26 +02:00
Hanabishi
2bdc91c53f Implement Peer ID Client column for Peers tab
PR #17940.
2022-11-13 21:28:25 +02:00
Chocobo1
d829df99aa Revise interface of port forwarder
This eases the usage of port forwarder as the caller code doesn't need
to store previous used port and now can rely on port forwarder doing
all the hard work.

PR #17967.
2022-11-13 21:28:19 +02:00
Vladimir Golovnev
4f2ac34440 Destroy object within appropriate thread
PR #18012.
2022-11-13 08:30:42 +03:00
Vladimir Golovnev
94e9e9fdb2 Delete database file only after it is released
PR #18011.
2022-11-13 08:29:50 +03:00
157 changed files with 74733 additions and 76869 deletions

View File

@@ -3,7 +3,7 @@ host = https://www.transifex.com
[qbittorrent.qbittorrent_master]
file_filter = src/lang/qbittorrent_<lang>.ts
lang_map = pt: pt_PT
lang_map = pt: pt_PT, zh: zh_CN
source_file = src/lang/qbittorrent_en.ts
source_lang = en
type = QT
@@ -19,7 +19,7 @@ mode = developer
[qbittorrent.qbittorrent_webui]
file_filter = src/webui/www/translations/webui_<lang>.ts
lang_map = pt: pt_PT
lang_map = pt: pt_PT, zh: zh_CN
source_file = src/webui/www/translations/webui_en.ts
source_lang = en
type = QT

View File

@@ -1,4 +1,84 @@
Unreleased - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.5.0
Sat Nov 26 2022 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.5.0
- FEATURE: Add `Auto resize columns` functionality (Chocobo1)
- FEATURE: Allow to use Category paths in `Manual` mode (glassez)
- FEATURE: Allow to disable Automatic mode when default "temp" path changed (glassez)
- FEATURE: Add tuning options related to performance warnings (Chocobo1)
- FEATURE: Add right click menu for status filters (An0n)
- FEATURE: Allow setting the number of maximum active checking torrents (An0n)
- FEATURE: Add option to toggle filters sidebar (AbeniMatteo)
- FEATURE: Allow to set `working set limit` on non-Windows OS (Chocobo1)
- FEATURE: Add `Export .torrent` action (Chocobo1)
- FEATURE: Add keyboard navigation keys (itlezy)
- FEATURE: Allow to use POSIX-compliant disk IO type (Coda)
- FEATURE: Add `Filter files` field in new torrent dialog (thalieht)
- FEATURE: Implement new icon/color theme (now-im, xavier2k6)
- FEATURE: Add file name filter/blacklist (mxtsdev, thalieht)
- FEATURE: Add support for custom SMTP ports (Emil M George)
- FEATURE: Split the OS cache settings into Disk IO read/write modes (summer)
- FEATURE: When duplicate torrent is added set metadata to existing one (glassez)
- FEATURE: Greatly improve startup time with many torrents (glassez, jagannatharjun)
- FEATURE: Add keyboard shortcut to Download URL dialog (Chocobo1)
- FEATURE: Add ability to run external program on torrent added (glassez)
- FEATURE: Add infohash and download path columns (tristanleboss)
- FEATURE: Allow to set torrent stop condition (glassez, thalieht)
- FEATURE: Add a `Moving` status filter (tristanleboss)
- FEATURE: Change color palettes for both dark, light themes (Chocobo1)
- FEATURE: Add a `Use proxy for hostname lookup` option (Nathan Lewis)
- FEATURE: Introduce a `change listen port` cmd option (BallsOfSpaghetti)
- FEATURE: Implement `Peer ID Client` column for `Peers` tab (Hanabishi)
- FEATURE: Add port forwarding option for embedded tracker (Chocobo1)
- BUGFIX: Store hybrid torrents using `torrent ID` as basename (glassez)
- BUGFIX: Enable Combobox editor for the `Mixed` file download priority (Aleksandr Cupacenko)
- BUGFIX: Allow shortcut folders for the Open and Save directory dialogs (Aleksandr Cupacenko)
- BUGFIX: Rename content tab `Size` column to `Total Size` (Aleksandr Cupacenko)
- BUGFIX: Fix scrolling to the lowermost visible torrent (Aleksandr Cupacenko)
- BUGFIX: Allow changing file priorities for finished torrents (An0n)
- BUGFIX: Focus save path when Manual mode is selected initially (Aleksandr Cupacenko)
- BUGFIX: Disable force reannounce when it is not possible (An0n)
- BUGFIX: Add horizontal scrolling for tracker list and torrent content (NotTsunami)
- BUGFIX: Enlarge "speed limits" icons (Chocobo1)
- BUGFIX: Change Downloaded to Times Downloaded in trackers tab (An0n)
- BUGFIX: Remove artificial max limits from `Torrent Queueing` related options (Chocobo1)
- BUGFIX: Preserve `skip hash check` when there is no metadata (glassez)
- BUGFIX: Fix DHT/PeX/LSD status when it is globally disabled (Kacper Michajłow)
- BUGFIX: Fix rate calculation when interval is too low (glassez)
- BUGFIX: Add tooltip message when system tray icon isn't available (Chocobo1)
- BUGFIX: Improve sender field in mail notifications (Dmitry Vodopyanov)
- BUGFIX: Fix "Add torrent dialog" spill-over on smaller screens (Chocobo1)
- BUGFIX: Fix peer count issue when tracker responds with zero figure (summer)
- BUGFIX: Don't merge trackers by default (glassez)
- BUGFIX: Don't inhibit system sleep/auto shutdown for torrents stuck at downloading metadata (summer)
- BUGFIX: Allow to pause a checking torrent from context menu (summer)
- BUGFIX: Allow to use subnet notation in reverse proxy list (Chocobo1)
- BUGFIX: Fine tune translations loading for Chinese locales (sledgehammer999)
- BUGFIX: Fix torrent content checkboxes not updated properly (Chocobo1)
- BUGFIX: Correctly load state of `Use another path for incomplete torrents` in Watched folders (glassez)
- BUGFIX: Add confirmation to resume/pause all (BallsOfSpaghetti)
- BUGFIX: Fix wrong count of errored trackers (Chocobo1)
- WEBUI: Allow blank lines in multipart form-data input (Aleksandr Cupacenko)
- WEBUI: Make various dialogs resizable (Chocobo1)
- WEBUI: Fix wrong v2 hash string displayed (Chocobo1)
- WEBUI: WebAPI: return correct status (Requi)
- WEBUI: Fix empty selection in language combobox (Chocobo1)
- WEBUI: Store WebUI port setting in human readable number (Chocobo1)
- WEBUI: Add support for exporting .torrent (Tom Piccirello)
- WEBUI: WebAPI: Add endpoint to set speed limit mode (glassez)
- WEBUI: Improve progress bar rendering (Mike Lei)
- WEBUI: Add transfer list refresh interval settings (summer)
- WEBUI: Use natural sort (Chocobo1)
- WEBUI: Apply i18n translation only to built-in WebUI (Chocobo1)
- WEBUI: Alert when HTTPS settings are incomplete (Chocobo1)
- WEBUI: Handle drag and drop events (Chocobo1)
- WEBUI: Fix wrong behavior for shutdown action (Chocobo1)
- WEBUI: Don't disable combobox for file priority (Chocobo1)
- RSS: Increase limit of maximum number of articles per feed (summer)
- WINDOWS: Fix `Open destination folder` delay on Windows (Andrew)
- WINDOWS: NSIS: Update Russian, Estonian, Japanese, Dutch, Portuguese BR, German and Indonesian translations (Andrei Stepanov, Priit Uring, maboroshin, Thomas De Rocker, Ícaro, schnurlos, Faisal A. F. Rahman)
- LINUX: Mark as single window app in .desktop file (Nicolas Fella)
- LINUX: Add Dockerfile (Amanuense-del-diavolo, Tom Piccirello, Chocobo1)
- LINUX: Remove option of using icons from system theme (now-im)
- MACOS: Fix wrong background color in properties widget (NotTsunami)
- OTHER: Binary distributions of qbittorrent are GPLv3+ licensed (sledgehammer999)
Thu Jan 06 2022 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.4.0
- FEATURE: Support for v2 torrents along with libtorrent 2.0.x support (glassez, Chocobo1)

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for qbittorrent v4.5.0beta1.
# Generated by GNU Autoconf 2.71 for qbittorrent v4.5.0.
#
# Report bugs to <bugs.qbittorrent.org>.
#
@@ -611,8 +611,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='qbittorrent'
PACKAGE_TARNAME='qbittorrent'
PACKAGE_VERSION='v4.5.0beta1'
PACKAGE_STRING='qbittorrent v4.5.0beta1'
PACKAGE_VERSION='v4.5.0'
PACKAGE_STRING='qbittorrent v4.5.0'
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
PACKAGE_URL='https://www.qbittorrent.org/'
@@ -1329,7 +1329,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.5.0beta1 to adapt to many kinds of systems.
\`configure' configures qbittorrent v4.5.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1400,7 +1400,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of qbittorrent v4.5.0beta1:";;
short | recursive ) echo "Configuration of qbittorrent v4.5.0:";;
esac
cat <<\_ACEOF
@@ -1533,7 +1533,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
qbittorrent configure v4.5.0beta1
qbittorrent configure v4.5.0
generated by GNU Autoconf 2.71
Copyright (C) 2021 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.5.0beta1, which was
It was created by qbittorrent $as_me v4.5.0, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -4779,7 +4779,7 @@ fi
# Define the identity of the package.
PACKAGE='qbittorrent'
VERSION='v4.5.0beta1'
VERSION='v4.5.0'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -7237,7 +7237,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.5.0beta1, which was
This file was extended by qbittorrent $as_me v4.5.0, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -7297,7 +7297,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
qbittorrent config.status v4.5.0beta1
qbittorrent config.status v4.5.0
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"

View File

@@ -1,4 +1,4 @@
AC_INIT([qbittorrent], [v4.5.0beta1], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_INIT([qbittorrent], [v4.5.0], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
: ${CFLAGS=""}

View File

@@ -74,6 +74,6 @@
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
<content_rating type="oars-1.1"/>
<releases>
<release version="4.5.0" date="2022-01-06"/>
<release version="4.5.0" date="2022-11-26"/>
</releases>
</component>

View File

@@ -98,7 +98,7 @@ Name[is]=qBittorrent
Comment[it]=Scarica e condividi file tramite BitTorrent
GenericName[it]=Client BitTorrent
Name[it]=qBittorrent
Comment[ja]=BitTorrent でファイルをダウンロードおよび共有します
Comment[ja]=BitTorrent でファイルをダウンロードおよび共有
GenericName[ja]=BitTorrent クライアント
Name[ja]=qBittorrent
Comment[ka]=გადმოტვირთეთ და გააზიარეთ ფაილები BitTorrent-ის საშუალებით

View File

@@ -882,7 +882,7 @@ void Application::createStartupProgressDialog()
m_startupProgressDialog = new QProgressDialog(tr("Loading torrents..."), tr("Exit"), 0, 100);
m_startupProgressDialog->setAttribute(Qt::WA_DeleteOnClose);
m_startupProgressDialog->setWindowFlag(Qt::WindowMinimizeButtonHint);
m_startupProgressDialog->setMinimumDuration(0); // Show dialog immediatelly by default
m_startupProgressDialog->setMinimumDuration(0); // Show dialog immediately by default
m_startupProgressDialog->setAutoReset(false);
m_startupProgressDialog->setAutoClose(false);

View File

@@ -210,7 +210,6 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
return nonstd::make_unexpected(tr("Cannot parse resume data: invalid format"));
LoadTorrentParams torrentParams;
torrentParams.restored = true;
torrentParams.category = fromLTString(resumeDataRoot.dict_find_string_value("qBt-category"));
torrentParams.name = fromLTString(resumeDataRoot.dict_find_string_value("qBt-name"));
torrentParams.hasSeedStatus = resumeDataRoot.dict_find_int_value("qBt-seedStatus");

View File

@@ -196,7 +196,6 @@ namespace BitTorrent
LoadTorrentParams parseQueryResultRow(const QSqlQuery &query)
{
LoadTorrentParams resumeData;
resumeData.restored = true;
resumeData.name = query.value(DB_COLUMN_NAME.name).toString();
resumeData.category = query.value(DB_COLUMN_CATEGORY.name).toString();
const QString tagsData = query.value(DB_COLUMN_TAGS.name).toString();

View File

@@ -58,7 +58,5 @@ namespace BitTorrent
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
bool restored = false; // is existing torrent job?
};
}

View File

@@ -181,6 +181,31 @@ QString PeerInfo::client() const
return QString::fromStdString(m_nativeInfo.client);
}
QString PeerInfo::peerIdClient() const
{
// when peer ID is not known yet it contains only zero bytes,
// do not create string in such case, return empty string instead
if (m_nativeInfo.pid.is_all_zeros())
return {};
QString result;
// interesting part of a typical peer ID is first 8 chars
for (int i = 0; i < 8; ++i)
{
const std::uint8_t c = m_nativeInfo.pid[i];
// ensure that the peer ID slice consists only of printable ASCII characters,
// this should filter out most of the improper IDs
if ((c < 32) || (c > 126))
return tr("Unknown");
result += QChar::fromLatin1(c);
}
return result;
}
qreal PeerInfo::progress() const
{
return m_nativeInfo.progress;

View File

@@ -78,6 +78,7 @@ namespace BitTorrent
PeerAddress address() const;
QString client() const;
QString peerIdClient() const;
qreal progress() const;
int payloadUpSpeed() const;
int payloadDownSpeed() const;

View File

@@ -30,6 +30,7 @@
#include <libtorrent/session.hpp>
#include "base/algorithm.h"
#include "base/logger.h"
PortForwarderImpl::PortForwarderImpl(lt::session *provider, QObject *parent)
@@ -63,45 +64,64 @@ void PortForwarderImpl::setEnabled(const bool enabled)
m_storeActive = enabled;
}
void PortForwarderImpl::addPort(const quint16 port)
void PortForwarderImpl::setPorts(const QString &profile, QSet<quint16> ports)
{
if (m_mappedPorts.contains(port))
return;
if (isEnabled())
m_mappedPorts.insert(port, m_provider->add_port_mapping(lt::session::tcp, port, port));
else
m_mappedPorts.insert(port, {});
}
void PortForwarderImpl::deletePort(const quint16 port)
{
const auto iter = m_mappedPorts.find(port);
if (iter == m_mappedPorts.end())
return;
if (isEnabled())
PortMapping &portMapping = m_portProfiles[profile];
Algorithm::removeIf(portMapping, [this, &ports](const quint16 port, const std::vector<lt::port_mapping_t> &handles)
{
for (const lt::port_mapping_t &portMapping : *iter)
m_provider->delete_port_mapping(portMapping);
// keep existing forwardings
const bool isAlreadyMapped = ports.remove(port);
if (isAlreadyMapped)
return false;
// remove outdated forwardings
for (const lt::port_mapping_t &handle : handles)
m_provider->delete_port_mapping(handle);
m_forwardedPorts.remove(port);
return true;
});
// add new forwardings
for (const quint16 port : ports)
{
// port already forwarded/taken by other profile, don't do anything
if (m_forwardedPorts.contains(port))
continue;
if (isEnabled())
portMapping.insert(port, m_provider->add_port_mapping(lt::session::tcp, port, port));
else
portMapping.insert(port, {});
m_forwardedPorts.insert(port);
}
m_mappedPorts.erase(iter);
if (portMapping.isEmpty())
m_portProfiles.remove(profile);
}
void PortForwarderImpl::removePorts(const QString &profile)
{
setPorts(profile, {});
}
void PortForwarderImpl::start()
{
lt::settings_pack settingsPack = m_provider->get_settings();
lt::settings_pack settingsPack;
settingsPack.set_bool(lt::settings_pack::enable_upnp, true);
settingsPack.set_bool(lt::settings_pack::enable_natpmp, true);
m_provider->apply_settings(settingsPack);
m_provider->apply_settings(std::move(settingsPack));
for (auto iter = m_mappedPorts.begin(); iter != m_mappedPorts.end(); ++iter)
for (auto profileIter = m_portProfiles.begin(); profileIter != m_portProfiles.end(); ++profileIter)
{
Q_ASSERT(iter.value().empty());
PortMapping &portMapping = profileIter.value();
for (auto iter = portMapping.begin(); iter != portMapping.end(); ++iter)
{
Q_ASSERT(iter.value().empty());
const quint16 port = iter.key();
iter.value() = m_provider->add_port_mapping(lt::session::tcp, port, port);
const quint16 port = iter.key();
iter.value() = m_provider->add_port_mapping(lt::session::tcp, port, port);
}
}
LogMsg(tr("UPnP/NAT-PMP support: ON"), Log::INFO);
@@ -109,14 +129,18 @@ void PortForwarderImpl::start()
void PortForwarderImpl::stop()
{
lt::settings_pack settingsPack = m_provider->get_settings();
lt::settings_pack settingsPack;
settingsPack.set_bool(lt::settings_pack::enable_upnp, false);
settingsPack.set_bool(lt::settings_pack::enable_natpmp, false);
m_provider->apply_settings(settingsPack);
m_provider->apply_settings(std::move(settingsPack));
// don't clear m_mappedPorts so a later `start()` call can restore the port forwarding
for (auto iter = m_mappedPorts.begin(); iter != m_mappedPorts.end(); ++iter)
iter.value().clear();
// don't clear m_portProfiles so a later `start()` call can restore the port forwardings
for (auto profileIter = m_portProfiles.begin(); profileIter != m_portProfiles.end(); ++profileIter)
{
PortMapping &portMapping = profileIter.value();
for (auto iter = portMapping.begin(); iter != portMapping.end(); ++iter)
iter.value().clear();
}
LogMsg(tr("UPnP/NAT-PMP support: OFF"), Log::INFO);
}

View File

@@ -34,6 +34,7 @@
#include <libtorrent/portmap.hpp>
#include <QHash>
#include <QSet>
#include "base/net/portforwarder.h"
#include "base/settingvalue.h"
@@ -50,8 +51,8 @@ public:
bool isEnabled() const override;
void setEnabled(bool enabled) override;
void addPort(quint16 port) override;
void deletePort(quint16 port) override;
void setPorts(const QString &profile, QSet<quint16> ports) override;
void removePorts(const QString &profile) override;
private:
void start();
@@ -59,5 +60,8 @@ private:
CachedSettingValue<bool> m_storeActive;
lt::session *const m_provider = nullptr;
QHash<quint16, std::vector<lt::port_mapping_t>> m_mappedPorts;
using PortMapping = QHash<quint16, std::vector<lt::port_mapping_t>>; // <port, handles>
QHash<QString, PortMapping> m_portProfiles;
QSet<quint16> m_forwardedPorts;
};

View File

@@ -80,6 +80,7 @@
#include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/net/proxyconfigurationmanager.h"
#include "base/preferences.h"
#include "base/profile.h"
#include "base/torrentfileguard.h"
#include "base/torrentfilter.h"
@@ -548,8 +549,6 @@ SessionImpl::SessionImpl(QObject *parent)
if (isExcludedFileNamesEnabled())
populateExcludedFileNamesRegExpList();
enableTracker(isTrackerEnabled());
connect(Net::ProxyConfigurationManager::instance()
, &Net::ProxyConfigurationManager::proxyConfigurationChanged
, this, &SessionImpl::configureDeferred);
@@ -569,11 +568,14 @@ SessionImpl::SessionImpl(QObject *parent)
m_ioThread->start();
initMetrics();
loadStatistics();
// initialize PortForwarder instance
new PortForwarderImpl(m_nativeSession);
initMetrics();
loadStatistics();
// start embedded tracker
enableTracker(isTrackerEnabled());
prepareStartup();
}
@@ -1055,25 +1057,25 @@ void SessionImpl::adjustLimits()
{
if (isQueueingSystemEnabled())
{
lt::settings_pack settingsPack = m_nativeSession->get_settings();
adjustLimits(settingsPack);
m_nativeSession->apply_settings(settingsPack);
lt::settings_pack settingsPack;
// Internally increase the queue limits to ensure that the magnet is started
settingsPack.set_int(lt::settings_pack::active_downloads, adjustLimit(maxActiveDownloads()));
settingsPack.set_int(lt::settings_pack::active_limit, adjustLimit(maxActiveTorrents()));
m_nativeSession->apply_settings(std::move(settingsPack));
}
}
void SessionImpl::applyBandwidthLimits()
{
lt::settings_pack settingsPack = m_nativeSession->get_settings();
applyBandwidthLimits(settingsPack);
m_nativeSession->apply_settings(settingsPack);
lt::settings_pack settingsPack;
settingsPack.set_int(lt::settings_pack::download_rate_limit, downloadSpeedLimit());
settingsPack.set_int(lt::settings_pack::upload_rate_limit, uploadSpeedLimit());
m_nativeSession->apply_settings(std::move(settingsPack));
}
void SessionImpl::configure()
{
lt::settings_pack settingsPack = m_nativeSession->get_settings();
loadLTSettings(settingsPack);
m_nativeSession->apply_settings(settingsPack);
m_nativeSession->apply_settings(loadLTSettings());
configureComponents();
m_deferredConfigureScheduled = false;
@@ -1390,7 +1392,12 @@ void SessionImpl::endStartup(ResumeSessionContext *context)
context->startupStorage->deleteLater();
if (context->currentStorageType == ResumeDataStorageType::Legacy)
Utils::Fs::removeFile(dbPath);
{
connect(context->startupStorage, &QObject::destroyed, [dbPath]
{
Utils::Fs::removeFile(dbPath);
});
}
}
context->deleteLater();
@@ -1419,10 +1426,11 @@ void SessionImpl::endStartup(ResumeSessionContext *context)
void SessionImpl::initializeNativeSession()
{
const std::string peerId = lt::generate_fingerprint(PEER_ID, QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD);
lt::settings_pack pack = loadLTSettings();
lt::settings_pack pack;
const std::string peerId = lt::generate_fingerprint(PEER_ID, QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD);
pack.set_str(lt::settings_pack::peer_fingerprint, peerId);
pack.set_bool(lt::settings_pack::listen_system_port_fallback, false);
pack.set_str(lt::settings_pack::user_agent, USER_AGENT.toStdString());
pack.set_bool(lt::settings_pack::use_dht_as_fallback, false);
@@ -1439,8 +1447,7 @@ void SessionImpl::initializeNativeSession()
pack.set_bool(lt::settings_pack::enable_set_file_valid_data, true);
#endif
loadLTSettings(pack);
lt::session_params sessionParams {pack, {}};
lt::session_params sessionParams {std::move(pack), {}};
#ifdef QBT_USES_LIBTORRENT2
switch (diskIOType())
{
@@ -1498,28 +1505,14 @@ void SessionImpl::processBannedIPs(lt::ip_filter &filter)
}
}
void SessionImpl::adjustLimits(lt::settings_pack &settingsPack) const
int SessionImpl::adjustLimit(const int limit) const
{
// Internally increase the queue limits to ensure that the magnet is started
const auto adjustLimit = [this](const int limit) -> int
{
if (limit <= -1)
return limit;
// check for overflow: (limit + m_extraLimit) < std::numeric_limits<int>::max()
return (m_extraLimit < (std::numeric_limits<int>::max() - limit))
? (limit + m_extraLimit)
: std::numeric_limits<int>::max();
};
settingsPack.set_int(lt::settings_pack::active_downloads, adjustLimit(maxActiveDownloads()));
settingsPack.set_int(lt::settings_pack::active_limit, adjustLimit(maxActiveTorrents()));
}
void SessionImpl::applyBandwidthLimits(lt::settings_pack &settingsPack) const
{
const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled();
settingsPack.set_int(lt::settings_pack::download_rate_limit, altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit());
settingsPack.set_int(lt::settings_pack::upload_rate_limit, altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit());
if (limit <= -1)
return limit;
// check for overflow: (limit + m_extraLimit) < std::numeric_limits<int>::max()
return (m_extraLimit < (std::numeric_limits<int>::max() - limit))
? (limit + m_extraLimit)
: std::numeric_limits<int>::max();
}
void SessionImpl::initMetrics()
@@ -1564,8 +1557,10 @@ void SessionImpl::initMetrics()
m_metricIndices.disk.diskJobTime = findMetricIndex("disk.disk_job_time");
}
void SessionImpl::loadLTSettings(lt::settings_pack &settingsPack)
lt::settings_pack SessionImpl::loadLTSettings() const
{
lt::settings_pack settingsPack;
const lt::alert_category_t alertMask = lt::alert::error_notification
| lt::alert::file_progress_notification
| lt::alert::ip_block_notification
@@ -1583,8 +1578,10 @@ void SessionImpl::loadLTSettings(lt::settings_pack &settingsPack)
// It will not take affect until the listen_interfaces settings is updated
settingsPack.set_int(lt::settings_pack::listen_queue_size, socketBacklogSize());
configureNetworkInterfaces(settingsPack);
applyBandwidthLimits(settingsPack);
applyNetworkInterfacesSettings(settingsPack);
settingsPack.set_int(lt::settings_pack::download_rate_limit, downloadSpeedLimit());
settingsPack.set_int(lt::settings_pack::upload_rate_limit, uploadSpeedLimit());
// The most secure, rc4 only so that all streams are encrypted
settingsPack.set_int(lt::settings_pack::allowed_enc_level, lt::settings_pack::pe_rc4);
@@ -1719,7 +1716,9 @@ void SessionImpl::loadLTSettings(lt::settings_pack &settingsPack)
// Queueing System
if (isQueueingSystemEnabled())
{
adjustLimits(settingsPack);
// Internally increase the queue limits to ensure that the magnet is started
settingsPack.set_int(lt::settings_pack::active_downloads, adjustLimit(maxActiveDownloads()));
settingsPack.set_int(lt::settings_pack::active_limit, adjustLimit(maxActiveTorrents()));
settingsPack.set_int(lt::settings_pack::active_seeds, maxActiveUploads());
settingsPack.set_bool(lt::settings_pack::dont_count_slow_torrents, ignoreSlowTorrentsForQueueing());
@@ -1835,9 +1834,11 @@ void SessionImpl::loadLTSettings(lt::settings_pack &settingsPack)
settingsPack.set_int(lt::settings_pack::seed_choking_algorithm, lt::settings_pack::anti_leech);
break;
}
return settingsPack;
}
void SessionImpl::configureNetworkInterfaces(lt::settings_pack &settingsPack)
void SessionImpl::applyNetworkInterfacesSettings(lt::settings_pack &settingsPack) const
{
if (m_listenInterfaceConfigured)
return;
@@ -1980,16 +1981,27 @@ void SessionImpl::configurePeerClasses()
void SessionImpl::enableTracker(const bool enable)
{
const QString profile = u"embeddedTracker"_qs;
auto *portForwarder = Net::PortForwarder::instance();
if (enable)
{
if (!m_tracker)
m_tracker = new Tracker(this);
m_tracker->start();
const auto *pref = Preferences::instance();
if (pref->isTrackerPortForwardingEnabled())
portForwarder->setPorts(profile, {static_cast<quint16>(pref->getTrackerPort())});
else
portForwarder->removePorts(profile);
}
else
{
delete m_tracker;
portForwarder->removePorts(profile);
}
}
@@ -2753,9 +2765,6 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
p.flags |= lt::torrent_flags::duplicate_is_error;
// Prevent torrent from saving initial resume data twice
p.flags &= ~lt::torrent_flags::need_save_resume;
p.added_time = std::time(nullptr);
// Limits
@@ -2898,10 +2907,8 @@ void SessionImpl::saveResumeData()
saveTorrentsQueue();
for (const TorrentImpl *torrent : asConst(m_torrents))
{
torrent->nativeHandle().save_resume_data(lt::torrent_handle::only_if_modified);
++m_numResumeData;
}
m_numResumeData += m_torrents.size();
QElapsedTimer timer;
timer.start();
@@ -5207,9 +5214,9 @@ TorrentImpl *SessionImpl::createTorrent(const lt::torrent_handle &nativeHandle,
if (const InfoHash infoHash = torrent->infoHash(); infoHash.isHybrid())
m_hybridTorrentsByAltID.insert(TorrentID::fromSHA1Hash(infoHash.v1()), torrent);
if (!params.restored)
if (isRestored())
{
m_resumeDataStorage->store(torrent->id(), params);
torrent->saveResumeData(lt::torrent_handle::save_info_dict);
// The following is useless for newly added magnet
if (torrent->hasMetadata())
@@ -5225,7 +5232,7 @@ TorrentImpl *SessionImpl::createTorrent(const lt::torrent_handle &nativeHandle,
m_seedingLimitTimer->start();
}
if (params.restored)
if (!isRestored())
{
LogMsg(tr("Restored torrent. Torrent: \"%1\"").arg(torrent->name()));
}

View File

@@ -474,11 +474,10 @@ namespace BitTorrent
Q_INVOKABLE void configure();
void configureComponents();
void initializeNativeSession();
void loadLTSettings(lt::settings_pack &settingsPack);
void configureNetworkInterfaces(lt::settings_pack &settingsPack);
lt::settings_pack loadLTSettings() const;
void applyNetworkInterfacesSettings(lt::settings_pack &settingsPack) const;
void configurePeerClasses();
void adjustLimits(lt::settings_pack &settingsPack) const;
void applyBandwidthLimits(lt::settings_pack &settingsPack) const;
int adjustLimit(int limit) const;
void initMetrics();
void adjustLimits();
void applyBandwidthLimits();
@@ -553,7 +552,7 @@ namespace BitTorrent
bool m_deferredConfigureScheduled = false;
bool m_IPFilteringConfigured = false;
bool m_listenInterfaceConfigured = false;
mutable bool m_listenInterfaceConfigured = false;
CachedSettingValue<bool> m_isDHTEnabled;
CachedSettingValue<bool> m_isLSDEnabled;

View File

@@ -690,9 +690,9 @@ bool TorrentImpl::needSaveResumeData() const
return m_nativeStatus.need_save_resume;
}
void TorrentImpl::saveResumeData()
void TorrentImpl::saveResumeData(lt::resume_data_flags_t flags)
{
m_nativeHandle.save_resume_data();
m_nativeHandle.save_resume_data(flags);
m_session->handleTorrentSaveResumeDataRequested(this);
}

View File

@@ -245,7 +245,7 @@ namespace BitTorrent
void handleStateUpdate(const lt::torrent_status &nativeStatus);
void handleCategoryOptionsChanged();
void handleAppendExtensionToggled();
void saveResumeData();
void saveResumeData(lt::resume_data_flags_t flags = {});
void handleMoveStorageJobFinished(const Path &path, bool hasOutstandingJob);
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
void updatePeerCount(const QString &trackerURL, const TrackerEntry::Endpoint &endpoint, int count);

View File

@@ -203,12 +203,12 @@ Tracker::Tracker(QObject *parent)
bool Tracker::start()
{
const QHostAddress ip = QHostAddress::Any;
const int port = Preferences::instance()->getTrackerPort();
if (m_server->isListening())
{
if (m_server->serverPort() == port)
if (const int oldPort = m_server->serverPort()
; oldPort == port)
{
// Already listening on the right port, just return
return true;
@@ -218,9 +218,9 @@ bool Tracker::start()
m_server->close();
}
// Listen on the predefined port
// Listen on port
const QHostAddress ip = QHostAddress::Any;
const bool listenSuccess = m_server->listen(ip, port);
if (listenSuccess)
{
LogMsg(tr("Embedded Tracker: Now listening on IP: %1, port: %2")

View File

@@ -124,7 +124,7 @@ namespace
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
request.setRawHeader("Referer", request.url().toEncoded().data());
#ifdef QT_NO_COMPRESS
// The macro "QT_NO_COMPRESS" defined in QT will disable the zlib releated features
// The macro "QT_NO_COMPRESS" defined in QT will disable the zlib related features
// and reply data auto-decompression in QT will also be disabled. But we can support
// gzip encoding and manually decompress the reply data.
request.setRawHeader("Accept-Encoding", "gzip");

View File

@@ -29,6 +29,9 @@
#pragma once
#include <QObject>
#include <QSet>
class QString;
namespace Net
{
@@ -45,8 +48,8 @@ namespace Net
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void addPort(quint16 port) = 0;
virtual void deletePort(quint16 port) = 0;
virtual void setPorts(const QString &profile, QSet<quint16> ports) = 0;
virtual void removePorts(const QString &profile) = 0;
private:
static PortForwarder *m_instance;

View File

@@ -1164,6 +1164,16 @@ void Preferences::setTrackerPort(const int port)
setValue(u"Preferences/Advanced/trackerPort"_qs, port);
}
bool Preferences::isTrackerPortForwardingEnabled() const
{
return value(u"Preferences/Advanced/trackerPortForwarding"_qs, false);
}
void Preferences::setTrackerPortForwardingEnabled(const bool enabled)
{
setValue(u"Preferences/Advanced/trackerPortForwarding"_qs, enabled);
}
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
bool Preferences::isUpdateCheckEnabled() const
{

View File

@@ -299,6 +299,8 @@ public:
#endif
int getTrackerPort() const;
void setTrackerPort(int port);
bool isTrackerPortForwardingEnabled() const;
void setTrackerPortForwardingEnabled(bool enabled);
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
bool isUpdateCheckEnabled() const;
void setUpdateCheckEnabled(bool enabled);

View File

@@ -277,9 +277,11 @@ void Feed::handleParsingFinished(const RSS::Private::ParsingResult &result)
void Feed::load()
{
QMetaObject::invokeMethod(m_serializer, [this]()
QMetaObject::invokeMethod(m_serializer
, [serializer = m_serializer, url = m_url
, path = (m_session->dataFileStorage()->storageDir() / m_dataFileName)]
{
m_serializer->load((m_session->dataFileStorage()->storageDir() / m_dataFileName), m_url);
serializer->load(path, url);
});
}
@@ -297,9 +299,11 @@ void Feed::store()
for (Article *article :asConst(m_articles))
articlesData.push_back(article->data());
QMetaObject::invokeMethod(m_serializer, [this, articlesData]()
QMetaObject::invokeMethod(m_serializer
, [articlesData, serializer = m_serializer
, path = (m_session->dataFileStorage()->storageDir() / m_dataFileName)]
{
m_serializer->store((m_session->dataFileStorage()->storageDir() / m_dataFileName), articlesData);
serializer->store(path, articlesData);
});
}

View File

@@ -32,7 +32,7 @@
#define QBT_VERSION_MINOR 5
#define QBT_VERSION_BUGFIX 0
#define QBT_VERSION_BUILD 0
#define QBT_VERSION_STATUS "beta1" // Should be empty for stable releases!
#define QBT_VERSION_STATUS "" // Should be empty for stable releases!
#define QBT__STRINGIFY(x) #x
#define QBT_STRINGIFY(x) QBT__STRINGIFY(x)

View File

@@ -97,6 +97,7 @@ namespace
// embedded tracker
TRACKER_STATUS,
TRACKER_PORT,
TRACKER_PORT_FORWARDING,
// libtorrent section
LIBTORRENT_HEADER,
ASYNC_IO_THREADS,
@@ -292,7 +293,9 @@ void AdvancedSettings::saveAdvancedSettings() const
// Tracker
pref->setTrackerPort(m_spinBoxTrackerPort.value());
pref->setTrackerPortForwardingEnabled(m_checkBoxTrackerPortForwarding.isChecked());
session->setTrackerEnabled(m_checkBoxTrackerStatus.isChecked());
// Choking algorithm
session->setChokingAlgorithm(m_comboBoxChokingAlgorithm.currentData().value<BitTorrent::ChokingAlgorithm>());
// Seed choking algorithm
@@ -732,6 +735,9 @@ void AdvancedSettings::loadAdvancedSettings()
m_spinBoxTrackerPort.setMaximum(65535);
m_spinBoxTrackerPort.setValue(pref->getTrackerPort());
addRow(TRACKER_PORT, tr("Embedded tracker port"), &m_spinBoxTrackerPort);
// Tracker port forwarding
m_checkBoxTrackerPortForwarding.setChecked(pref->isTrackerPortForwardingEnabled());
addRow(TRACKER_PORT_FORWARDING, tr("Enable port forwarding for embedded tracker"), &m_checkBoxTrackerPortForwarding);
// Choking algorithm
m_comboBoxChokingAlgorithm.addItem(tr("Fixed slots"), QVariant::fromValue(BitTorrent::ChokingAlgorithm::FixedSlots));
m_comboBoxChokingAlgorithm.addItem(tr("Upload rate based"), QVariant::fromValue(BitTorrent::ChokingAlgorithm::RateBased));

View File

@@ -68,7 +68,7 @@ private:
m_spinBoxSavePathHistoryLength, m_spinBoxPeerTurnover, m_spinBoxPeerTurnoverCutoff, m_spinBoxPeerTurnoverInterval, m_spinBoxRequestQueueSize;
QCheckBox m_checkBoxOsCache, m_checkBoxRecheckCompleted, m_checkBoxResolveCountries, m_checkBoxResolveHosts,
m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxReannounceWhenAddressChanged, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus,
m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers,
m_checkBoxTrackerPortForwarding, m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers,
m_checkBoxMultiConnectionsPerIp, m_checkBoxValidateHTTPSTrackerCertificate, m_checkBoxSSRFMitigation, m_checkBoxBlockPeersOnPrivilegedPorts, m_checkBoxPieceExtentAffinity,
m_checkBoxSuggestMode, m_checkBoxSpeedWidgetEnabled, m_checkBoxIDNSupport;
QComboBox m_comboBoxInterface, m_comboBoxInterfaceAddress, m_comboBoxDiskIOReadMode, m_comboBoxDiskIOWriteMode, m_comboBoxUtpMixedMode, m_comboBoxChokingAlgorithm,

View File

@@ -89,7 +89,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
, m_properties(parent)
{
// Load settings
loadSettings();
const bool columnLoaded = loadSettings();
// Visual settings
setUniformRowHeights(true);
setRootIsDecorated(false);
@@ -109,6 +109,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
m_listModel->setHeaderData(PeerListColumns::FLAGS, Qt::Horizontal, tr("Flags"));
m_listModel->setHeaderData(PeerListColumns::CONNECTION, Qt::Horizontal, tr("Connection"));
m_listModel->setHeaderData(PeerListColumns::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application"));
m_listModel->setHeaderData(PeerListColumns::PEERID_CLIENT, Qt::Horizontal, tr("Peer ID Client", "i.e.: Client resolved from Peer ID"));
m_listModel->setHeaderData(PeerListColumns::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
m_listModel->setHeaderData(PeerListColumns::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed"));
m_listModel->setHeaderData(PeerListColumns::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed"));
@@ -130,8 +131,16 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent)
m_proxyModel->setSourceModel(m_listModel);
m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
setModel(m_proxyModel);
hideColumn(PeerListColumns::IP_HIDDEN);
hideColumn(PeerListColumns::COL_COUNT);
// Default hidden columns
if (!columnLoaded)
{
hideColumn(PeerListColumns::PEERID_CLIENT);
}
m_resolveCountries = Preferences::instance()->resolvePeerCountries();
if (!m_resolveCountries)
hideColumn(PeerListColumns::COUNTRY);
@@ -371,9 +380,9 @@ void PeerListWidget::clear()
m_listModel->removeRows(0, nbrows);
}
void PeerListWidget::loadSettings()
bool PeerListWidget::loadSettings()
{
header()->restoreState(Preferences::instance()->getPeerListState());
return header()->restoreState(Preferences::instance()->getPeerListState());
}
void PeerListWidget::saveSettings() const
@@ -461,6 +470,8 @@ void PeerListWidget::updatePeer(const BitTorrent::Torrent *torrent, const BitTor
setModelData(row, PeerListColumns::FLAGS, peer.flags(), peer.flags(), {}, peer.flagsDescription());
const QString client = peer.client().toHtmlEscaped();
setModelData(row, PeerListColumns::CLIENT, client, client, {}, client);
const QString peerIdClient = peer.peerIdClient().toHtmlEscaped();
setModelData(row, PeerListColumns::PEERID_CLIENT, peerIdClient, peerIdClient);
setModelData(row, PeerListColumns::PROGRESS, (Utils::String::fromDouble(peer.progress() * 100, 1) + u'%'), peer.progress(), intDataTextAlignment);
const QString downSpeed = (hideValues && (peer.payloadDownSpeed() <= 0)) ? QString {} : Utils::Misc::friendlyUnit(peer.payloadDownSpeed(), true);
setModelData(row, PeerListColumns::DOWN_SPEED, downSpeed, peer.payloadDownSpeed(), intDataTextAlignment);

View File

@@ -66,6 +66,7 @@ public:
CONNECTION,
FLAGS,
CLIENT,
PEERID_CLIENT,
PROGRESS,
DOWN_SPEED,
UP_SPEED,
@@ -87,7 +88,7 @@ public:
void clear();
private slots:
void loadSettings();
bool loadSettings();
void saveSettings() const;
void displayColumnHeaderMenu();
void showPeerListMenu();

View File

@@ -48,7 +48,7 @@ StatusBar::StatusBar(QWidget *parent)
{
#ifndef Q_OS_MACOS
// Redefining global stylesheet breaks certain elements on mac like tabs.
// Qt checks whether the stylesheet class inherts("QMacStyle") and this becomes false.
// Qt checks whether the stylesheet class inherits("QMacStyle") and this becomes false.
setStyleSheet(u"QStatusBar::item { border-width: 0; }"_qs);
#endif

View File

@@ -541,7 +541,8 @@ void TorrentContentModel::setupModelData(const BitTorrent::AbstractFileStorage &
if (filesCount <= 0)
return;
emit layoutAboutToBeChanged();
beginResetModel();
// Initialize files_index array
qDebug("Torrent contains %d files", filesCount);
m_filesIndex.reserve(filesCount);
@@ -588,7 +589,8 @@ void TorrentContentModel::setupModelData(const BitTorrent::AbstractFileStorage &
lastParent->appendChild(fileItem);
m_filesIndex.push_back(fileItem);
}
emit layoutChanged();
endResetModel();
}
void TorrentContentModel::notifySubtreeUpdated(const QModelIndex &index, const QVector<ColumnInterval> &columns)

View File

@@ -79,25 +79,19 @@ void TorrentContentTreeView::keyPressEvent(QKeyEvent *event)
event->accept();
QModelIndex current = currentNameCell();
QVariant value = current.data(Qt::CheckStateRole);
const QVariant value = currentNameCell().data(Qt::CheckStateRole);
if (!value.isValid())
{
Q_ASSERT(false);
return;
}
Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
? Qt::Unchecked : Qt::Checked);
const Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked)
? Qt::Unchecked : Qt::Checked;
const QModelIndexList selection = selectionModel()->selectedRows(TorrentContentModelItem::COL_NAME);
for (const QModelIndex &index : selection)
{
Q_ASSERT(index.column() == TorrentContentModelItem::COL_NAME);
model()->setData(index, state, Qt::CheckStateRole);
}
}
void TorrentContentTreeView::renameSelectedFile(BitTorrent::AbstractFileStorage &fileStorage)
@@ -142,16 +136,16 @@ void TorrentContentTreeView::renameSelectedFile(BitTorrent::AbstractFileStorage
}
}
QModelIndex TorrentContentTreeView::currentNameCell()
QModelIndex TorrentContentTreeView::currentNameCell() const
{
QModelIndex current = currentIndex();
const QModelIndex current = currentIndex();
if (!current.isValid())
{
Q_ASSERT(false);
return {};
}
return model()->index(current.row(), TorrentContentModelItem::COL_NAME, current.parent());
return current.siblingAtColumn(TorrentContentModelItem::COL_NAME);
}
void TorrentContentTreeView::wheelEvent(QWheelEvent *event)

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