From f39e06667295796d2d65ef836d6f73cd463f252c Mon Sep 17 00:00:00 2001 From: thalieht Date: Fri, 24 Jan 2025 11:11:19 +0200 Subject: [PATCH 1/7] Fix torrent content checkbox state under certain conditions PR #22190. Closes #22189. --- src/gui/torrentcontentmodel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp index 694e75958..adcd778bf 100644 --- a/src/gui/torrentcontentmodel.cpp +++ b/src/gui/torrentcontentmodel.cpp @@ -398,7 +398,9 @@ QVariant TorrentContentModel::data(const QModelIndex &index, const int role) con const bool hasIgnored = std::any_of(childItems.cbegin(), childItems.cend() , [](const TorrentContentModelItem *childItem) { - return (childItem->priority() == BitTorrent::DownloadPriority::Ignored); + const auto prio = childItem->priority(); + return ((prio == BitTorrent::DownloadPriority::Ignored) + || (prio == BitTorrent::DownloadPriority::Mixed)); }); return hasIgnored ? Qt::PartiallyChecked : Qt::Checked; From 69321f0e94e7ce3890aed8f9872e6530ae274327 Mon Sep 17 00:00:00 2001 From: thalieht Date: Mon, 27 Jan 2025 08:40:44 +0200 Subject: [PATCH 2/7] Hide zero and infinity values in peer list only when that setting is set to `Always` PR #22205. Closes #21998. --- src/gui/properties/peerlistwidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp index 87acbc666..511a3bd1e 100644 --- a/src/gui/properties/peerlistwidget.cpp +++ b/src/gui/properties/peerlistwidget.cpp @@ -420,7 +420,8 @@ void PeerListWidget::loadPeers(const BitTorrent::Torrent *torrent) for (auto i = m_peerItems.cbegin(); i != m_peerItems.cend(); ++i) existingPeers.insert(i.key()); - const bool hideZeroValues = Preferences::instance()->getHideZeroValues(); + const Preferences *pref = Preferences::instance(); + const bool hideZeroValues = (pref->getHideZeroValues() && (pref->getHideZeroComboValues() == 0)); for (const BitTorrent::PeerInfo &peer : peers) { const PeerEndpoint peerEndpoint {peer.address(), peer.connectionType()}; From 09fb92466a1f16898f05065ef7d73ae5e0f29450 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Sat, 11 Jan 2025 10:17:38 +0300 Subject: [PATCH 3/7] Handle Qt style options uniformly PR #22133. Closes #22061. --- src/gui/optionsdialog.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 3dc0d113f..81c3305f3 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023-2024 Vladimir Golovnev + * Copyright (C) 2023-2025 Vladimir Golovnev * Copyright (C) 2024 Jonathan Ketchker * Copyright (C) 2006 Christophe Dumez * @@ -456,10 +456,7 @@ void OptionsDialog::saveBehaviorTabOptions() const pref->setLocale(locale); #ifdef Q_OS_WIN - if (const QVariant systemStyle = m_ui->comboStyle->currentData(); systemStyle.isValid()) - pref->setStyle(systemStyle.toString()); - else - pref->setStyle(m_ui->comboStyle->currentText()); + pref->setStyle(m_ui->comboStyle->currentData().toString()); #endif #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) @@ -1695,18 +1692,20 @@ void OptionsDialog::initializeStyleCombo() { #ifdef Q_OS_WIN m_ui->labelStyleHint->setText(tr("%1 is recommended for best compatibility with Windows dark mode" - , "Fusion is recommended for best compatibility with Windows dark mode").arg(u"Fusion"_s)); + , "Fusion is recommended for best compatibility with Windows dark mode").arg(u"Fusion"_s)); m_ui->comboStyle->addItem(tr("System", "System default Qt style"), u"system"_s); m_ui->comboStyle->setItemData(0, tr("Let Qt decide the style for this system"), Qt::ToolTipRole); m_ui->comboStyle->insertSeparator(1); QStringList styleNames = QStyleFactory::keys(); std::sort(styleNames.begin(), styleNames.end(), Utils::Compare::NaturalLessThan()); - m_ui->comboStyle->addItems(styleNames); + for (const QString &styleName : asConst(styleNames)) + m_ui->comboStyle->addItem(styleName, styleName); const QString prefStyleName = Preferences::instance()->getStyle(); const QString selectedStyleName = prefStyleName.isEmpty() ? QApplication::style()->name() : prefStyleName; - m_ui->comboStyle->setCurrentIndex(m_ui->comboStyle->findText(selectedStyleName, Qt::MatchFixedString)); + const int styleIndex = m_ui->comboStyle->findData(selectedStyleName, Qt::UserRole, Qt::MatchFixedString); + m_ui->comboStyle->setCurrentIndex(std::max(0, styleIndex)); #else m_ui->labelStyle->hide(); m_ui->comboStyle->hide(); From 375e6800e9c97a5e53be32e07abe37241bab8c49 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Fri, 31 Jan 2025 06:23:04 +0300 Subject: [PATCH 4/7] Remove stopped torrent from "error" tracker filter PR #22219. --- src/gui/transferlistfilters/trackersfilterwidget.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gui/transferlistfilters/trackersfilterwidget.cpp b/src/gui/transferlistfilters/trackersfilterwidget.cpp index 20fc4ac1d..8793868a7 100644 --- a/src/gui/transferlistfilters/trackersfilterwidget.cpp +++ b/src/gui/transferlistfilters/trackersfilterwidget.cpp @@ -444,6 +444,16 @@ void TrackersFilterWidget::handleTrackerStatusesUpdated(const BitTorrent::Torren trackerErrorHashesIt = m_trackerErrors.insert(id, {}); trackerErrorHashesIt->insert(trackerEntryStatus.url); } + else if (trackerEntryStatus.state == BitTorrent::TrackerEndpointState::NotContacted) + { + // remove tracker from "error", "tracker error" and "warning" categories + if (warningHashesIt != m_warnings.end()) + warningHashesIt->remove(trackerEntryStatus.url); + if (errorHashesIt != m_errors.end()) + errorHashesIt->remove(trackerEntryStatus.url); + if (trackerErrorHashesIt != m_trackerErrors.end()) + trackerErrorHashesIt->remove(trackerEntryStatus.url); + } } if ((errorHashesIt != m_errors.end()) && errorHashesIt->isEmpty()) From 069cd029eb88a262614f5d407bfdeda4a9e57898 Mon Sep 17 00:00:00 2001 From: Hugo Carvalho Date: Mon, 23 Dec 2024 14:37:46 +0000 Subject: [PATCH 5/7] NSIS: Update Portuguese translation PR #21632. --- dist/windows/installer-translations/portuguese.nsh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/windows/installer-translations/portuguese.nsh b/dist/windows/installer-translations/portuguese.nsh index b067b00da..c149119f4 100644 --- a/dist/windows/installer-translations/portuguese.nsh +++ b/dist/windows/installer-translations/portuguese.nsh @@ -7,7 +7,7 @@ LangString inst_desktop ${LANG_PORTUGUESE} "Criar atalho no ambiente de trabalho ;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" LangString inst_startmenu ${LANG_PORTUGUESE} "Criar atalho no menu Iniciar" ;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up" -LangString inst_startup ${LANG_PORTUGUESE} "Iniciar o qBittorrent na inicialização do Windows" +LangString inst_startup ${LANG_PORTUGUESE} "Iniciar o qBittorrent no arranque do Windows" ;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" LangString inst_torrent ${LANG_PORTUGUESE} "Abrir ficheiros .torrent com o qBittorrent" ;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" @@ -29,7 +29,7 @@ LangString launch_qbt ${LANG_PORTUGUESE} "Iniciar qBittorrent." ;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." LangString inst_requires_64bit ${LANG_PORTUGUESE} "Este instalador funciona apenas em versões Windows de 64 bits." ;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019." -LangString inst_requires_win10 ${LANG_PORTUGUESE} "This installer requires at least Windows 10 (1809) / Windows Server 2019." +LangString inst_requires_win10 ${LANG_PORTUGUESE} "Este instalador requer, pelo menos, o Windows 10 (1809) / Windows Server 2019." ;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent" LangString inst_uninstall_link_description ${LANG_PORTUGUESE} "Desinstalar qBittorrent" From 730bf957a4d403fd64a6e6ceacf71ea938da157c Mon Sep 17 00:00:00 2001 From: skomerko <168652295+skomerko@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:26:43 +0100 Subject: [PATCH 6/7] WebUI: Don't keep references to context menu targets PR https://github.com/qbittorrent/qBittorrent/pull/22234. --- src/webui/www/private/scripts/contextmenu.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index 388555ffd..a21ee42cf 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -74,7 +74,6 @@ window.qBittorrent.ContextMenu = (function() { // option diffs menu this.menu = $(this.options.menu); - this.targets = $$(this.options.targets); // fx this.fx = new Fx.Tween(this.menu, { @@ -185,11 +184,14 @@ window.qBittorrent.ContextMenu = (function() { }, addTarget: function(t) { + if (t.hasEventListeners) + return; + // prevent long press from selecting this text t.style.setProperty("user-select", "none"); t.style.setProperty("-webkit-user-select", "none"); + t.hasEventListeners = true; - this.targets[this.targets.length] = t; this.setupEventListeners(t); }, @@ -210,8 +212,8 @@ window.qBittorrent.ContextMenu = (function() { // get things started startListener: function() { /* all elements */ - this.targets.each((el) => { - this.setupEventListeners(el); + $$(this.options.targets).each((el) => { + this.addTarget(el); }, this); /* menu items */ From ecde201ec558f2fdfcd9932cda061528688d6538 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Wed, 12 Feb 2025 09:33:41 +0300 Subject: [PATCH 7/7] WebAPI: Don't trim string parameters PR #22266. Closes #19485. Closes #22254. --- src/webui/api/rsscontroller.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/webui/api/rsscontroller.cpp b/src/webui/api/rsscontroller.cpp index f3cd11bba..1b7317112 100644 --- a/src/webui/api/rsscontroller.cpp +++ b/src/webui/api/rsscontroller.cpp @@ -49,7 +49,7 @@ void RSSController::addFolderAction() { requireParams({u"path"_s}); - const QString path = params()[u"path"_s].trimmed(); + const QString path = params()[u"path"_s]; const nonstd::expected result = RSS::Session::instance()->addFolder(path); if (!result) throw APIError(APIErrorType::Conflict, result.error()); @@ -59,8 +59,8 @@ void RSSController::addFeedAction() { requireParams({u"url"_s, u"path"_s}); - const QString url = params()[u"url"_s].trimmed(); - const QString path = params()[u"path"_s].trimmed(); + const QString url = params()[u"url"_s]; + const QString path = params()[u"path"_s]; const nonstd::expected result = RSS::Session::instance()->addFeed(url, (path.isEmpty() ? url : path)); if (!result) throw APIError(APIErrorType::Conflict, result.error()); @@ -70,8 +70,8 @@ void RSSController::setFeedURLAction() { requireParams({u"path"_s, u"url"_s}); - const QString path = params()[u"path"_s].trimmed(); - const QString url = params()[u"url"_s].trimmed(); + const QString path = params()[u"path"_s]; + const QString url = params()[u"url"_s]; const nonstd::expected result = RSS::Session::instance()->setFeedURL(path, url); if (!result) throw APIError(APIErrorType::Conflict, result.error()); @@ -81,7 +81,7 @@ void RSSController::removeItemAction() { requireParams({u"path"_s}); - const QString path = params()[u"path"_s].trimmed(); + const QString path = params()[u"path"_s]; const nonstd::expected result = RSS::Session::instance()->removeItem(path); if (!result) throw APIError(APIErrorType::Conflict, result.error()); @@ -91,8 +91,8 @@ void RSSController::moveItemAction() { requireParams({u"itemPath"_s, u"destPath"_s}); - const QString itemPath = params()[u"itemPath"_s].trimmed(); - const QString destPath = params()[u"destPath"_s].trimmed(); + const QString itemPath = params()[u"itemPath"_s]; + const QString destPath = params()[u"destPath"_s]; const nonstd::expected result = RSS::Session::instance()->moveItem(itemPath, destPath); if (!result) throw APIError(APIErrorType::Conflict, result.error()); @@ -146,8 +146,8 @@ void RSSController::setRuleAction() { requireParams({u"ruleName"_s, u"ruleDef"_s}); - const QString ruleName {params()[u"ruleName"_s].trimmed()}; - const QByteArray ruleDef {params()[u"ruleDef"_s].trimmed().toUtf8()}; + const QString ruleName {params()[u"ruleName"_s]}; + const QByteArray ruleDef {params()[u"ruleDef"_s].toUtf8()}; const auto jsonObj = QJsonDocument::fromJson(ruleDef).object(); RSS::AutoDownloader::instance()->setRule(RSS::AutoDownloadRule::fromJsonObject(jsonObj, ruleName)); @@ -157,8 +157,8 @@ void RSSController::renameRuleAction() { requireParams({u"ruleName"_s, u"newRuleName"_s}); - const QString ruleName {params()[u"ruleName"_s].trimmed()}; - const QString newRuleName {params()[u"newRuleName"_s].trimmed()}; + const QString ruleName {params()[u"ruleName"_s]}; + const QString newRuleName {params()[u"newRuleName"_s]}; RSS::AutoDownloader::instance()->renameRule(ruleName, newRuleName); } @@ -167,7 +167,7 @@ void RSSController::removeRuleAction() { requireParams({u"ruleName"_s}); - const QString ruleName {params()[u"ruleName"_s].trimmed()}; + const QString ruleName {params()[u"ruleName"_s]}; RSS::AutoDownloader::instance()->removeRule(ruleName); }