diff --git a/cmake/Modules/CheckPackages.cmake b/cmake/Modules/CheckPackages.cmake
index 6c85b8d11..6b082ea11 100644
--- a/cmake/Modules/CheckPackages.cmake
+++ b/cmake/Modules/CheckPackages.cmake
@@ -47,6 +47,9 @@ find_package(Boost ${minBoostVersion} REQUIRED)
find_package(OpenSSL ${minOpenSSLVersion} REQUIRED)
find_package(ZLIB ${minZlibVersion} REQUIRED)
find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools)
+if (Qt6_FOUND AND (Qt6_VERSION VERSION_GREATER_EQUAL 6.10))
+ find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS CorePrivate)
+endif()
if (DBUS)
find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS DBus)
set_package_properties(Qt6DBus PROPERTIES
diff --git a/src/base/search/searchpluginmanager.cpp b/src/base/search/searchpluginmanager.cpp
index 09b7a67cc..ab53c5d5e 100644
--- a/src/base/search/searchpluginmanager.cpp
+++ b/src/base/search/searchpluginmanager.cpp
@@ -487,14 +487,14 @@ void SearchPluginManager::updateNova()
const Path enginePath = engineLocation();
QFile packageFile {(enginePath / Path(u"__init__.py"_s)).data()};
- packageFile.open(QIODevice::WriteOnly);
- packageFile.close();
+ if (packageFile.open(QIODevice::WriteOnly))
+ packageFile.close();
Utils::Fs::mkdir(enginePath / Path(u"engines"_s));
QFile packageFile2 {(enginePath / Path(u"engines/__init__.py"_s)).data()};
- packageFile2.open(QIODevice::WriteOnly);
- packageFile2.close();
+ if (packageFile2.open(QIODevice::WriteOnly))
+ packageFile2.close();
// Copy search plugin files (if necessary)
const auto updateFile = [&enginePath](const Path &filename, const bool compareVersion)
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 1dc459fdb..dd07ea2ef 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -1161,7 +1161,7 @@ void MainWindow::closeEvent(QCloseEvent *e)
if (!m_forceExit)
{
hide();
- e->accept();
+ e->ignore();
return;
}
#else
@@ -1660,11 +1660,11 @@ void MainWindow::handleUpdateCheckFinished(ProgramUpdater *updater, const bool i
updater->deleteLater();
};
- const QString newVersion = updater->getNewVersion();
- if (!newVersion.isEmpty())
+ const auto newVersion = updater->getNewVersion();
+ if (newVersion.isValid())
{
const QString msg {tr("A new version is available.") + u"
"
- + tr("Do you want to download %1?").arg(newVersion) + u"
"
+ + tr("Do you want to download %1?").arg(newVersion.toString()) + u"
"
+ u"%1"_s.arg(tr("Open changelog..."))};
auto *msgBox = new QMessageBox {QMessageBox::Question, tr("qBittorrent Update Available"), msg
, (QMessageBox::Yes | QMessageBox::No), this};
diff --git a/src/gui/programupdater.cpp b/src/gui/programupdater.cpp
index 063bc5473..dc6965f29 100644
--- a/src/gui/programupdater.cpp
+++ b/src/gui/programupdater.cpp
@@ -35,10 +35,13 @@
#include
#include
#include
+#include
+#include
#include
#include
#include "base/global.h"
+#include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/preferences.h"
#include "base/utils/version.h"
@@ -46,23 +49,20 @@
namespace
{
- bool isVersionMoreRecent(const QString &remoteVersion)
+ bool isVersionMoreRecent(const ProgramUpdater::Version &remoteVersion)
{
- using Version = Utils::Version<4, 3>;
-
- const auto newVersion = Version::fromString(remoteVersion);
- if (!newVersion.isValid())
+ if (!remoteVersion.isValid())
return false;
- const Version currentVersion {QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD};
- if (newVersion == currentVersion)
+ const ProgramUpdater::Version currentVersion {QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD};
+ if (remoteVersion == currentVersion)
{
const bool isDevVersion = QStringLiteral(QBT_VERSION_STATUS).contains(
QRegularExpression(u"(alpha|beta|rc)"_s));
if (isDevVersion)
return true;
}
- return (newVersion > currentVersion);
+ return (remoteVersion > currentVersion);
}
QString buildVariant()
@@ -82,30 +82,34 @@ namespace
void ProgramUpdater::checkForUpdates() const
{
+ const auto USER_AGENT = QStringLiteral("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)");
const auto RSS_URL = u"https://www.fosshub.com/feed/5b8793a7f9ee5a5c3e97a3b2.xml"_s;
+ const auto FALLBACK_URL = u"https://www.qbittorrent.org/versions.json"_s;
+
// Don't change this User-Agent. In case our updater goes haywire,
// the filehost can identify it and contact us.
- Net::DownloadManager::instance()->download(
- Net::DownloadRequest(RSS_URL).userAgent(QStringLiteral("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)"))
+ Net::DownloadManager::instance()->download(Net::DownloadRequest(RSS_URL).userAgent(USER_AGENT)
, Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::rssDownloadFinished);
+ Net::DownloadManager::instance()->download(Net::DownloadRequest(FALLBACK_URL).userAgent(USER_AGENT)
+ , Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::fallbackDownloadFinished);
+
+ m_hasCompletedOneReq = false;
}
-QString ProgramUpdater::getNewVersion() const
+ProgramUpdater::Version ProgramUpdater::getNewVersion() const
{
- return m_newVersion;
+ return shouldUseFallback() ? m_fallbackRemoteVersion : m_remoteVersion;
}
void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
{
if (result.status != Net::DownloadStatus::Success)
{
- qDebug() << "Downloading the new qBittorrent updates RSS failed:" << result.errorString;
- emit updateCheckFinished();
+ LogMsg(tr("Failed to download the update info. URL: %1. Error: %2").arg(result.url, result.errorString) , Log::WARNING);
+ handleFinishedRequest();
return;
}
- qDebug("Finished downloading the new qBittorrent updates RSS");
-
const auto getStringValue = [](QXmlStreamReader &xml) -> QString
{
xml.readNext();
@@ -146,9 +150,10 @@ void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
if (!version.isEmpty())
{
qDebug("Detected version is %s", qUtf8Printable(version));
- if (isVersionMoreRecent(version))
+ const ProgramUpdater::Version tmpVer {version};
+ if (isVersionMoreRecent(tmpVer))
{
- m_newVersion = version;
+ m_remoteVersion = tmpVer;
m_updateURL = updateLink;
}
}
@@ -163,10 +168,50 @@ void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
}
}
- emit updateCheckFinished();
+ handleFinishedRequest();
+}
+
+void ProgramUpdater::fallbackDownloadFinished(const Net::DownloadResult &result)
+{
+ if (result.status != Net::DownloadStatus::Success)
+ {
+ LogMsg(tr("Failed to download the update info. URL: %1. Error: %2").arg(result.url, result.errorString) , Log::WARNING);
+ handleFinishedRequest();
+ return;
+ }
+
+ const auto json = QJsonDocument::fromJson(result.data);
+
+#if defined(Q_OS_MACOS)
+ const QString platformKey = u"macos"_s;
+#elif defined(Q_OS_WIN)
+ const QString platformKey = u"win"_s;
+#endif
+
+ if (const QJsonValue verJSON = json[platformKey][u"version"_s]; verJSON.isString())
+ {
+ const ProgramUpdater::Version tmpVer {verJSON.toString()};
+ if (isVersionMoreRecent(tmpVer))
+ m_fallbackRemoteVersion = tmpVer;
+ }
+
+ handleFinishedRequest();
}
bool ProgramUpdater::updateProgram() const
{
- return QDesktopServices::openUrl(m_updateURL);
+ return QDesktopServices::openUrl(shouldUseFallback() ? u"https://www.qbittorrent.org/download"_s : m_updateURL);
+}
+
+void ProgramUpdater::handleFinishedRequest()
+{
+ if (m_hasCompletedOneReq)
+ emit updateCheckFinished();
+ else
+ m_hasCompletedOneReq = true;
+}
+
+bool ProgramUpdater::shouldUseFallback() const
+{
+ return m_fallbackRemoteVersion > m_remoteVersion;
}
diff --git a/src/gui/programupdater.h b/src/gui/programupdater.h
index 88d41985f..531d12118 100644
--- a/src/gui/programupdater.h
+++ b/src/gui/programupdater.h
@@ -30,9 +30,10 @@
#pragma once
#include
-#include
#include
+#include "base/utils/version.h"
+
namespace Net
{
struct DownloadResult;
@@ -45,9 +46,10 @@ class ProgramUpdater final : public QObject
public:
using QObject::QObject;
+ using Version = Utils::Version<4, 3>;
void checkForUpdates() const;
- QString getNewVersion() const;
+ Version getNewVersion() const;
bool updateProgram() const;
signals:
@@ -55,8 +57,14 @@ signals:
private slots:
void rssDownloadFinished(const Net::DownloadResult &result);
+ void fallbackDownloadFinished(const Net::DownloadResult &result);
private:
- QString m_newVersion;
+ void handleFinishedRequest();
+ bool shouldUseFallback() const;
+
+ mutable bool m_hasCompletedOneReq = false;
+ Version m_remoteVersion;
+ Version m_fallbackRemoteVersion;
QUrl m_updateURL;
};
diff --git a/src/gui/uithemecommon.h b/src/gui/uithemecommon.h
index 9f1545fe6..ba7a5c2c5 100644
--- a/src/gui/uithemecommon.h
+++ b/src/gui/uithemecommon.h
@@ -80,8 +80,14 @@ inline QHash defaultUIThemeColors()
{u"TransferList.StoppedUploading"_s, {Color::Primer::Light::doneFg, Color::Primer::Dark::doneFg}},
{u"TransferList.Moving"_s, {Color::Primer::Light::successFg, Color::Primer::Dark::successFg}},
{u"TransferList.MissingFiles"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}},
- {u"TransferList.Error"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}},
+ {u"TransferList.Error"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}}
+ };
+}
+// Palette isn't customizable in default theme
+inline QHash defaultPaletteColors()
+{
+ return {
{u"Palette.Window"_s, {{}, {}}},
{u"Palette.WindowText"_s, {{}, {}}},
{u"Palette.Base"_s, {{}, {}}},
diff --git a/src/gui/uithemedialog.cpp b/src/gui/uithemedialog.cpp
index 24ee381da..2d06ceeba 100644
--- a/src/gui/uithemedialog.cpp
+++ b/src/gui/uithemedialog.cpp
@@ -273,8 +273,6 @@ void UIThemeDialog::loadColors()
int row = 2;
for (const QString &id : colorIDs)
{
- if (id == u"Log.Normal")
- qDebug() << "!!!!!!!";
m_ui->colorsLayout->addWidget(new QLabel(id), row, 0);
const UIThemeColor &defaultColor = defaultColors.value(id);
diff --git a/src/gui/uithemesource.cpp b/src/gui/uithemesource.cpp
index be0138ee0..b854986ea 100644
--- a/src/gui/uithemesource.cpp
+++ b/src/gui/uithemesource.cpp
@@ -105,6 +105,8 @@ DefaultThemeSource::DefaultThemeSource()
, m_colors {defaultUIThemeColors()}
{
loadColors();
+ // Palette isn't customizable in default theme
+ m_colors.insert(defaultPaletteColors());
}
QByteArray DefaultThemeSource::readStyleSheet()
diff --git a/src/webui/api/appcontroller.cpp b/src/webui/api/appcontroller.cpp
index 95bb6e0d0..a1fc0e1da 100644
--- a/src/webui/api/appcontroller.cpp
+++ b/src/webui/api/appcontroller.cpp
@@ -673,12 +673,12 @@ void AppController::setPreferencesAction()
if (hasKey(u"autorun_on_torrent_added_enabled"_s))
pref->setAutoRunOnTorrentAddedEnabled(it.value().toBool());
if (hasKey(u"autorun_on_torrent_added_program"_s))
- pref->setAutoRunOnTorrentAddedProgram(it.value().toString());
+ pref->setAutoRunOnTorrentAddedProgram(it.value().toString().trimmed());
// Run an external program on torrent finished
if (hasKey(u"autorun_enabled"_s))
pref->setAutoRunOnTorrentFinishedEnabled(it.value().toBool());
if (hasKey(u"autorun_program"_s))
- pref->setAutoRunOnTorrentFinishedProgram(it.value().toString());
+ pref->setAutoRunOnTorrentFinishedProgram(it.value().toString().trimmed());
// Connection
// Listening Port