nextcloud-desktop/debian/patches/0008-qt6.patch
2025-10-21 19:21:18 +02:00

1155 lines
38 KiB
Diff

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 800e561448..2ebc72d236 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,7 +31,7 @@ set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
include(${CMAKE_SOURCE_DIR}/NEXTCLOUD.cmake)
set(QT_VERSION_MAJOR "6")
-set(REQUIRED_QT_VERSION "6.8.0")
+set(REQUIRED_QT_VERSION "6.2.4")
# CfAPI Shell Extensions
set( CFAPI_SHELL_EXTENSIONS_LIB_NAME CfApiShellExtensions )
@@ -84,13 +84,11 @@ endif()
set(APPLE_SUPPRESS_X11_WARNING ON)
-find_package(ECM 6.0.0 REQUIRED NO_MODULE)
+find_package(ECM 5.0.0 REQUIRED NO_MODULE)
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://invent.kde.org/frameworks/extra-cmake-modules")
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
-include(KDEInstallDirs)
-include(KDECMakeSettings)
include(ECMMarkNonGuiExecutable)
include(ECMSetupVersion)
@@ -152,7 +150,7 @@ if(APPLE AND BUILD_OWNCLOUD_OSX_BUNDLE)
add_definitions(-DBUILD_OWNCLOUD_OSX_BUNDLE)
endif()
-find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Core)
+find_package(QT REQUIRED COMPONENTS Core NAMES Qt${QT_MAJOR_VERSION} )
option(QUICK_COMPILER "Use QtQuick compiler to improve performance" OFF)
# this option removes Http authentication, keychain, shibboleth etc and is intended for
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f584246eb7..efa56ae181 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
include(ECMEnableSanitizers)
-set(REQUIRED_QT_VERSION "6.5.0")
+set(REQUIRED_QT_VERSION "6.2.4")
find_package(Qt${QT_MAJOR_VERSION}Core ${REQUIRED_QT_VERSION} CONFIG QUIET)
set_package_properties(Qt${QT_MAJOR_VERSION}Core PROPERTIES
diff --git a/src/common/common.cmake b/src/common/common.cmake
index 5a19933dc9..6f5dabcb7c 100644
--- a/src/common/common.cmake
+++ b/src/common/common.cmake
@@ -39,3 +39,5 @@ elseif(UNIX AND NOT APPLE)
endif()
configure_file(${CMAKE_CURRENT_LIST_DIR}/vfspluginmetadata.json.in ${CMAKE_CURRENT_BINARY_DIR}/vfspluginmetadata.json)
+
+find_package(Qt6 REQUIRED COMPONENTS Widgets)
diff --git a/src/common/qtcompat.cpp b/src/common/qtcompat.cpp
new file mode 100644
index 0000000000..ccded5d62e
--- /dev/null
+++ b/src/common/qtcompat.cpp
@@ -0,0 +1 @@
+#include "qtcompat.h"
diff --git a/src/common/qtcompat.h b/src/common/qtcompat.h
new file mode 100644
index 0000000000..4a4c59b354
--- /dev/null
+++ b/src/common/qtcompat.h
@@ -0,0 +1,290 @@
+
+#pragma once
+
+#include <QtGlobal>
+#include <QLocale>
+#include <QRegularExpression>
+#include <QTimeZone>
+
+#include <type_traits>
+
+//-----------------------------------------------------------------------------
+
+template<unsigned major, unsigned minor, class T = void>
+struct qt_atleast : public std::enable_if<QT_VERSION>=QT_VERSION_CHECK(major, minor, 0), T>
+{
+};
+
+template<unsigned major, unsigned minor, class T = void>
+struct qt_before : public std::enable_if<QT_VERSION<QT_VERSION_CHECK(major, minor, 0), T>
+{
+};
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+inline QString systemLocaleName()
+{
+#if QT_VERSION>=QT_VERSION_CHECK(6, 8, 0)
+ return QLocale::system().uiLanguages(QLocale::TagSeparator::Underscore).first();
+#else
+ return QLocale::system().name();
+#endif
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline QRegularExpressionMatch
+matchRegularExpression(const QRegularExpression& re, const T& s)
+{
+#if QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+ return re.matchView(s);
+#else
+ return re.match(s);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 5, 0)
+template <typename Char, typename... Args>
+inline QDebug& operator<<(QDebug& d, const std::basic_string<Char, Args...>& s)
+{
+ return d << s.c_str();
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 6, 0)
+
+#include <chrono>
+
+template <typename Rep, typename Period>
+inline QDebug& operator<<(QDebug& d, const std::chrono::duration<Rep, Period> dur)
+{
+ return d << dur.count() << " " << Period::num << "/" << Period::den;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+const auto QTimeZoneUTC = QTimeZone::UTC;
+#else
+const auto QTimeZoneUTC = Qt::UTC;
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 4, 0)
+#define QCOMPARE_GT(computed, baseline) QCOMPARE(computed>baseline, true)
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 3, 0)
+#define QLatin1StringOrView QLatin1String
+#else
+#define QLatin1StringOrView QLatin1StringView
+#endif
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 4, 0)
+namespace Qt { namespace StringLiterals {
+
+inline QLatin1StringOrView operator""_L1(const char *str, size_t size)
+{
+ return QLatin1StringOrView(str, size);
+}
+
+} }
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 5, 0)
+#include <QDebug>
+#define qCFatal(category) QDebug(QtFatalMsg)
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 6, 0)
+#define QPromiseEmplaceResult(promise, type, ...) promise->addResult(type(__VA_ARGS__))
+#else
+#define QPromiseEmplaceResult(promise, type, ...) promise->emplaceResult(__VA_ARGS__)
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#ifdef QT_WIDGETS_LIB
+
+//-----------------------------------------------------------------------------
+
+#include <QCheckBox>
+
+//-----------------------------------------------------------------------------
+
+template <typename Functor>
+inline QMetaObject::Connection connectCheckBoxStateChanged(
+ const QCheckBox* sender, const QObject* context, Functor functor)
+{
+ return QObject::connect(sender,
+#if QT_VERSION>=QT_VERSION_CHECK(6, 8, 0)
+ &QCheckBox::checkStateChanged,
+#else
+ &QCheckBox::stateChanged,
+#endif
+ context, functor);
+}
+
+//-----------------------------------------------------------------------------
+
+#endif // QT_WIDGETS_LIB
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#ifdef QT_WEBSOCKETS_LIB
+
+//-----------------------------------------------------------------------------
+
+#include <QWebSocket>
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+#define QWebSocketErrorOccurred &QWebSocket::errorOccurred
+#else
+#define QWebSocketErrorOccurred &QWebSocket::error
+#endif
+
+//-----------------------------------------------------------------------------
+
+#endif // QT_WEBSOCKETS_LIB
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#ifdef QT_XML_LIB
+
+//-----------------------------------------------------------------------------
+
+#include <QDomDocument>
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+
+inline QDomDocument::ParseResult
+QDomDocumentSetContentsUseNamespaceProcessing(QDomDocument& doc, QIODevice* device)
+{
+ return doc.setContent(device, QDomDocument::ParseOption::UseNamespaceProcessing);
+}
+
+#else // QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+
+struct QDomDocumentParseResult {
+ bool retval = false;
+
+ QString errorMessage;
+
+ int errorLine = -1;
+
+ int errorColumn = -1;
+
+ inline operator bool() const {
+ return retval;
+ }
+};
+
+inline QDomDocumentParseResult
+QDomDocumentSetContentsUseNamespaceProcessing(QDomDocument& doc, QIODevice* device)
+{
+ QDomDocumentParseResult result;
+ result.retval = doc.setContent(device, true, &result.errorMessage,
+ &result.errorLine, &result.errorColumn);
+ return result;
+}
+
+#endif // QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+
+//-----------------------------------------------------------------------------
+
+#endif // QT_XML_LIB
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#ifdef QT_GUI_LIB
+
+//-----------------------------------------------------------------------------
+
+#include <QGuiApplication>
+#include <QStyleHints>
+
+//-----------------------------------------------------------------------------
+
+inline double getColorDarkness(const QColor &color)
+{
+ // account for different sensitivity of the human eye to certain colors
+ const double threshold = 1.0 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255.0;
+ return threshold;
+}
+
+//-----------------------------------------------------------------------------
+
+inline bool isDarkColor(const QColor& color)
+{
+ return getColorDarkness(color) > 0.5;
+}
+
+//-----------------------------------------------------------------------------
+
+template <class Target, typename Functor>
+inline void connectQStyleHintsColorSchemeChanged(QGuiApplication* app,
+ const Target* context,
+ Functor functor)
+{
+#if QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+ QObject::connect(app->styleHints(), &QStyleHints::colorSchemeChanged,
+ context, functor, Qt::UniqueConnection);
+#else
+ QObject::connect(app, &QGuiApplication::paletteChanged, context, functor);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+
+inline bool isDarkMode() {
+#if QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+ switch (qGuiApp->styleHints()->colorScheme())
+ {
+ case Qt::ColorScheme::Dark:
+ return true;
+ case Qt::ColorScheme::Light:
+ return false;
+ case Qt::ColorScheme::Unknown:
+ return isDarkColor(QGuiApplication::palette().window().color());
+ }
+
+ return false;
+#else // QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+ return isDarkColor(QGuiApplication::palette().window().color());
+#endif // QT_VERSION>=QT_VERSION_CHECK(6, 5, 0)
+}
+
+//-----------------------------------------------------------------------------
+
+#endif // QT_GUI_LIB
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp
index fa3c97c487..c0505b76f7 100644
--- a/src/csync/csync_exclude.cpp
+++ b/src/csync/csync_exclude.cpp
@@ -21,6 +21,7 @@
#include "common/utility.h"
#include "common/filesystembase.h"
+#include "common/qtcompat.h"
#include "../version.h"
#include <QString>
@@ -297,7 +298,7 @@ void ExcludedFiles::loadExcludeFilePatterns(const QString &basePath, QFile &file
if (line.isEmpty() || line.startsWith('#'))
continue;
const auto patternStr = QString::fromUtf8(line);
- if (QStringView{patternStr}.trimmed() == QLatin1StringView("*")) {
+ if (QStringView{patternStr}.trimmed() == QLatin1StringOrView("*")) {
continue;
}
csync_exclude_expand_escapes(line);
@@ -459,10 +460,10 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
QRegularExpressionMatch m;
if (filetype == ItemTypeDirectory
&& _bnameTraversalRegexDir.contains(basePath)) {
- m = _bnameTraversalRegexDir[basePath].matchView(bnameStr);
+ m = matchRegularExpression(_bnameTraversalRegexDir[basePath], bnameStr);
} else if (filetype == ItemTypeFile
&& _bnameTraversalRegexFile.contains(basePath)) {
- m = _bnameTraversalRegexFile[basePath].matchView(bnameStr);
+ m = matchRegularExpression(_bnameTraversalRegexFile[basePath], bnameStr);
} else {
continue;
}
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 9ce24e95a0..9e8723203d 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
project(gui)
find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2 QuickWidgets Xml Network)
-find_package(KF6Archive REQUIRED)
+find_package(KF6Archive)
find_package(KF6GuiAddons)
if(CMAKE_BUILD_TYPE MATCHES Debug)
@@ -551,9 +551,16 @@ target_link_libraries(nextcloudCore
Qt::Quick
Qt::QuickControls2
Qt::QuickWidgets
- KF6::Archive
)
+if(KF6Archive_FOUND)
+ target_link_libraries(nextcloudCore
+ PUBLIC
+ KF6::Archive
+ )
+ add_definitions(-DHAVE_KARCHIVE)
+endif()
+
if(KF6GuiAddons_FOUND)
target_link_libraries(nextcloudCore
PUBLIC
@@ -762,3 +769,10 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32)
endif()
configure_file(configgui.h.in ${CMAKE_CURRENT_BINARY_DIR}/configgui.h)
+
+if ("${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}" VERSION_GREATER_EQUAL "6.5")
+ set(QML_ACCEPTTHISOBJECT_PRAGMA "pragma NativeMethodBehavior: AcceptThisObject")
+else()
+ set(QML_ACCEPTTHISOBJECT_PRAGMA "")
+endif()
+configure_file(tray/TrayFoldersMenuButton.qml.in ${CMAKE_CURRENT_SOURCE_DIR}/tray/TrayFoldersMenuButton.qml)
diff --git a/src/gui/application.cpp b/src/gui/application.cpp
index f2f6a0503e..cc972dd676 100644
--- a/src/gui/application.cpp
+++ b/src/gui/application.cpp
@@ -36,6 +36,7 @@
#include "version.h"
#include "csync_exclude.h"
#include "common/vfs.h"
+#include "common/qtcompat.h"
#include "config.h"
@@ -1019,7 +1020,7 @@ void Application::setupTranslations()
{
qCInfo(lcApplication) << "System UI languages are:" << QLocale::system().uiLanguages();
const auto enforcedLocale = enforcedLanguage();
- const auto lang = substLang(!enforcedLocale.isEmpty() ? enforcedLocale : QLocale::system().uiLanguages(QLocale::TagSeparator::Underscore).first());
+ const auto lang = substLang(!enforcedLocale.isEmpty() ? enforcedLocale : systemLocaleName());
qCInfo(lcApplication) << "selected application language:" << lang;
auto *translator = new QTranslator(this);
diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp
index 17d693bf71..f7105f131c 100644
--- a/src/gui/folderman.cpp
+++ b/src/gui/folderman.cpp
@@ -16,6 +16,7 @@
#include "filesystem.h"
#include "lockwatcher.h"
#include "common/asserts.h"
+#include "common/qtcompat.h"
#include "gui/systray.h"
#include <pushnotifications.h>
#include <syncengine.h>
diff --git a/src/gui/folderwizard.cpp b/src/gui/folderwizard.cpp
index 3dc10ad198..637b58acf5 100644
--- a/src/gui/folderwizard.cpp
+++ b/src/gui/folderwizard.cpp
@@ -15,6 +15,7 @@
#include "creds/abstractcredentials.h"
#include "wizard/owncloudwizard.h"
#include "common/asserts.h"
+#include "common/qtcompat.h"
#include <QDesktopServices>
#include <QDir>
@@ -571,7 +572,7 @@ FolderWizardSelectiveSync::FolderWizardSelectiveSync(const AccountPtr &account)
if (!Theme::instance()->disableVirtualFilesSyncFolder() && Theme::instance()->showVirtualFilesOption() && bestAvailableVfsMode() != Vfs::Off) {
_virtualFilesCheckBox = new QCheckBox(tr("Use virtual files instead of downloading content immediately %1").arg(bestAvailableVfsMode() == Vfs::WindowsCfApi ? QString() : tr("(experimental)")));
connect(_virtualFilesCheckBox, &QCheckBox::clicked, this, &FolderWizardSelectiveSync::virtualFilesCheckboxClicked);
- connect(_virtualFilesCheckBox, &QCheckBox::checkStateChanged, this, [this](int state) {
+ connectCheckBoxStateChanged(_virtualFilesCheckBox, this, [this](int state) {
_selectiveSync->setEnabled(state == Qt::Unchecked);
});
_virtualFilesCheckBox->setChecked(bestAvailableVfsMode() == Vfs::WindowsCfApi);
diff --git a/src/gui/generalsettings.cpp b/src/gui/generalsettings.cpp
index de5ed4d049..bb8ffb4585 100644
--- a/src/gui/generalsettings.cpp
+++ b/src/gui/generalsettings.cpp
@@ -44,6 +44,7 @@
#include <QScopedValueRollback>
#include <QMessageBox>
+#ifdef HAVE_KARCHIVE
#include <KZip>
#include <chrono>
@@ -178,6 +179,7 @@ bool createDebugArchive(const QString &filename)
}
}
+#endif // HAVE_KARCHIVE
namespace OCC {
@@ -271,7 +273,11 @@ GeneralSettings::GeneralSettings(QWidget *parent)
_ui->monoIconsCheckBox->setVisible(Theme::instance()->monoIconsAvailable());
connect(_ui->ignoredFilesButton, &QAbstractButton::clicked, this, &GeneralSettings::slotIgnoreFilesEditor);
+#ifdef HAVE_KARCHIVE
connect(_ui->debugArchiveButton, &QAbstractButton::clicked, this, &GeneralSettings::slotCreateDebugArchive);
+#else
+ _ui->debugArchiveButton->setEnabled(false);
+#endif
// accountAdded means the wizard was finished and the wizard might change some options.
connect(AccountManager::instance(), &AccountManager::accountAdded, this, &GeneralSettings::loadMiscSettings);
@@ -634,6 +640,7 @@ void GeneralSettings::slotIgnoreFilesEditor()
}
}
+#ifdef HAVE_KARCHIVE
void GeneralSettings::slotCreateDebugArchive()
{
const auto filename = QFileDialog::getSaveFileName(
@@ -655,6 +662,7 @@ void GeneralSettings::slotCreateDebugArchive()
);
}
}
+#endif
void GeneralSettings::slotShowLegalNotice()
{
diff --git a/src/gui/generalsettings.h b/src/gui/generalsettings.h
index b62a7b3c07..85de6f00a1 100644
--- a/src/gui/generalsettings.h
+++ b/src/gui/generalsettings.h
@@ -52,7 +52,9 @@ private slots:
void slotToggleQuotaWarningNotifications(bool);
void slotShowInExplorerNavigationPane(bool);
void slotIgnoreFilesEditor();
+#if defined(HAVE_KARCHIVE)
void slotCreateDebugArchive();
+#endif
void loadMiscSettings();
void slotShowLegalNotice();
void slotRemotePollIntervalChanged(int seconds);
diff --git a/src/gui/sslerrordialog.cpp b/src/gui/sslerrordialog.cpp
index cc0397f295..c4753ab48d 100644
--- a/src/gui/sslerrordialog.cpp
+++ b/src/gui/sslerrordialog.cpp
@@ -7,6 +7,7 @@
#include "configfile.h"
#include "sslerrordialog.h"
#include "theme.h"
+#include "common/qtcompat.h"
#include <QtGui>
#include <QtNetwork>
@@ -215,7 +216,7 @@ QString SslErrorDialog::certDiv(QSslCertificate cert) const
msg += QL("<p>");
- if (cert.effectiveDate() < QDateTime(QDate(2016, 1, 1), QTime(), QTimeZone::UTC)) {
+ if (cert.effectiveDate() < QDateTime(QDate(2016, 1, 1), QTime(), QTimeZoneUTC)) {
QString sha1sum = Utility::formatFingerprint(cert.digest(QCryptographicHash::Sha1).toHex());
msg += tr("Fingerprint (SHA1): <tt>%1</tt>").arg(sha1sum) + QL("<br/>");
}
diff --git a/src/gui/tray/ActivityItemContent.qml b/src/gui/tray/ActivityItemContent.qml
index 2260ed8e6e..e36123fd8a 100644
--- a/src/gui/tray/ActivityItemContent.qml
+++ b/src/gui/tray/ActivityItemContent.qml
@@ -14,7 +14,7 @@ import com.nextcloud.desktopclient
RowLayout {
id: root
- required property color adaptiveTextColor
+ property color adaptiveTextColor
property variant activityData: {{}}
diff --git a/src/gui/tray/TrayFoldersMenuButton.qml b/src/gui/tray/TrayFoldersMenuButton.qml.in
similarity index 99%
rename from src/gui/tray/TrayFoldersMenuButton.qml
rename to src/gui/tray/TrayFoldersMenuButton.qml.in
index 4ae4d28a58..2193c27219 100644
--- a/src/gui/tray/TrayFoldersMenuButton.qml
+++ b/src/gui/tray/TrayFoldersMenuButton.qml.in
@@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-pragma NativeMethodBehavior: AcceptThisObject
+@QML_ACCEPTTHISOBJECT_PRAGMA@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt
index 5820fc0c8a..a70abc9c8d 100644
--- a/src/libsync/CMakeLists.txt
+++ b/src/libsync/CMakeLists.txt
@@ -2,7 +2,7 @@
# SPDX-FileCopyrightText: 2014 ownCloud GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
project(libsync)
-find_package(KF6Archive REQUIRED)
+find_package(KF6Archive)
include(DefinePlatformDefaults)
set(CMAKE_AUTOMOC TRUE)
@@ -162,6 +162,8 @@ set(libsync_SRCS
creds/keychainchunk.cpp
caseclashconflictsolver.h
caseclashconflictsolver.cpp
+ kfcompat.h
+ kfcompat.cpp
)
if (WIN32)
@@ -228,10 +230,15 @@ target_link_libraries(nextcloudsync
Qt::Gui
Qt::Svg
Qt::Widgets
- KF6::Archive
+
Qt::Core5Compat
)
+if (KF6Archive_FOUND)
+ target_link_libraries(nextcloudsync PUBLIC KF6::Archive)
+ add_definitions(-DHAVE_KARCHIVE)
+endif()
+
target_compile_features(nextcloudsync
PRIVATE
cxx_std_17
diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp
index e7bde80a84..b37b5831b3 100644
--- a/src/libsync/account.cpp
+++ b/src/libsync/account.cpp
@@ -22,6 +22,7 @@
#include "common/syncjournaldb.h"
#include "common/asserts.h"
+#include "common/qtcompat.h"
#include "clientsideencryption.h"
#include "ocsuserstatusconnector.h"
@@ -1239,7 +1240,8 @@ void Account::listRemoteFolder(QPromise<OCC::PlaceholderCreateInfo> *promise, co
serverHasMountRootProperty() ? RemotePermissions::MountedPermissionAlgorithm::UseMountRootProperty : RemotePermissions::MountedPermissionAlgorithm::WildGuessMountedSubProperty,
newEntry);
- promise->emplaceResult(itemFileName, itemFileName.toStdWString(), absoluteItemPathName, newEntry);
+ QPromiseEmplaceResult(promise, OCC::PlaceholderCreateInfo,
+ itemFileName, itemFileName.toStdWString(), absoluteItemPathName, newEntry);
});
promise->start();
diff --git a/src/libsync/clientsideencryption.cpp b/src/libsync/clientsideencryption.cpp
index 9ce1b567fa..ef19a95180 100644
--- a/src/libsync/clientsideencryption.cpp
+++ b/src/libsync/clientsideencryption.cpp
@@ -18,7 +18,7 @@
#include <qt6keychain/keychain.h>
-#include <KCompressionDevice>
+#include "kfcompat.h"
#include <QDebug>
#include <QLoggingCategory>
@@ -2750,26 +2750,12 @@ bool EncryptionHelper::dataDecryption(const QByteArray &key, const QByteArray &i
QByteArray EncryptionHelper::gzipThenEncryptData(const QByteArray &key, const QByteArray &inputData, const QByteArray &iv, QByteArray &returnTag)
{
- QBuffer gZipBuffer;
- auto gZipCompressionDevice = KCompressionDevice(&gZipBuffer, false, KCompressionDevice::GZip);
- if (!gZipCompressionDevice.open(QIODevice::WriteOnly)) {
- return {};
- }
- const auto bytesWritten = gZipCompressionDevice.write(inputData);
- gZipCompressionDevice.close();
- if (bytesWritten < 0) {
- return {};
- }
-
- if (!gZipBuffer.open(QIODevice::ReadOnly)) {
- return {};
- }
-
QByteArray outputData;
returnTag.clear();
- const auto gZippedAndNotEncrypted = gZipBuffer.readAll();
+
+ const auto gZippedAndNotEncrypted = gZipData(inputData);
+
EncryptionHelper::dataEncryption(key, iv, gZippedAndNotEncrypted, outputData, returnTag);
- gZipBuffer.close();
return outputData;
}
@@ -2781,23 +2767,7 @@ QByteArray EncryptionHelper::decryptThenUnGzipData(const QByteArray &key, const
return {};
}
- QBuffer gZipBuffer;
- if (!gZipBuffer.open(QIODevice::WriteOnly)) {
- return {};
- }
- const auto bytesWritten = gZipBuffer.write(decryptedAndUnGzipped);
- gZipBuffer.close();
- if (bytesWritten < 0) {
- return {};
- }
-
- auto gZipUnCompressionDevice = KCompressionDevice(&gZipBuffer, false, KCompressionDevice::GZip);
- if (!gZipUnCompressionDevice.open(QIODevice::ReadOnly)) {
- return {};
- }
-
- decryptedAndUnGzipped = gZipUnCompressionDevice.readAll();
- gZipUnCompressionDevice.close();
+ decryptedAndUnGzipped = unGzipData(decryptedAndUnGzipped);
return decryptedAndUnGzipped;
}
diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp
index 08677e49b6..4a4760b0ff 100644
--- a/src/libsync/discovery.cpp
+++ b/src/libsync/discovery.cpp
@@ -23,6 +23,7 @@
#include <QThreadPool>
#include <common/checksums.h>
#include <common/constants.h>
+#include <common/qtcompat.h>
#include "csync_exclude.h"
#include "csync.h"
diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp
index b6a8708498..4e4f991c50 100644
--- a/src/libsync/filesystem.cpp
+++ b/src/libsync/filesystem.cpp
@@ -7,6 +7,7 @@
#include "filesystem.h"
#include "common/utility.h"
+#include "common/qtcompat.h"
#include "csync.h"
#include "vio/csync_vio_local.h"
#include "std/c_time.h"
diff --git a/src/libsync/kfcompat.cpp b/src/libsync/kfcompat.cpp
new file mode 100644
index 0000000000..09a0552883
--- /dev/null
+++ b/src/libsync/kfcompat.cpp
@@ -0,0 +1,176 @@
+
+#include "kfcompat.h"
+
+//-----------------------------------------------------------------------------
+
+#include <QByteArray>
+#include <QBuffer>
+
+//-----------------------------------------------------------------------------
+
+#ifdef HAVE_KARCHIVE
+
+//-----------------------------------------------------------------------------
+
+#include <KCompressionDevice>
+
+//-----------------------------------------------------------------------------
+
+QByteArray gZipData(const QByteArray& inputData)
+{
+ QBuffer gZipBuffer;
+ auto gZipCompressionDevice = KCompressionDevice(&gZipBuffer, false, KCompressionDevice::GZip);
+ if (!gZipCompressionDevice.open(QIODevice::WriteOnly)) {
+ return {};
+ }
+ const auto bytesWritten = gZipCompressionDevice.write(inputData);
+ gZipCompressionDevice.close();
+ if (bytesWritten < 0) {
+ return {};
+ }
+
+ if (!gZipBuffer.open(QIODevice::ReadOnly)) {
+ return {};
+ }
+
+ const auto gZipped = gZipBuffer.readAll();
+ gZipBuffer.close();
+ return gZipped;
+}
+
+//-----------------------------------------------------------------------------
+
+QByteArray unGzipData(const QByteArray& inputData)
+{
+ QBuffer gZipBuffer;
+ if (!gZipBuffer.open(QIODevice::WriteOnly)) {
+ return {};
+ }
+ const auto bytesWritten = gZipBuffer.write(inputData);
+ gZipBuffer.close();
+ if (bytesWritten < 0) {
+ return {};
+ }
+
+ auto gZipUnCompressionDevice = KCompressionDevice(&gZipBuffer, false, KCompressionDevice::GZip);
+ if (!gZipUnCompressionDevice.open(QIODevice::ReadOnly)) {
+ return {};
+ }
+
+ auto unGzipped = gZipUnCompressionDevice.readAll();
+ gZipUnCompressionDevice.close();
+ return unGzipped;
+}
+
+
+//-----------------------------------------------------------------------------
+#else // HAVE_KARCHIVE
+//-----------------------------------------------------------------------------
+
+#include <zlib.h>
+#include <sys/mman.h>
+
+//-----------------------------------------------------------------------------
+
+QByteArray gZipData(const QByteArray& inputData)
+{
+ auto fd = memfd_create("gzipThenEncryptData", 0);
+ if (fd < 0) {
+ return {};
+ }
+
+ auto gzFile = gzdopen(fd, "wb");
+ if (gzFile == nullptr) {
+ close(fd);
+ return {};
+ }
+
+ if (gzwrite(gzFile, inputData.data(), inputData.length())!=inputData.length()) {
+ gzclose(gzFile);
+ close(fd);
+ return {};
+ }
+
+ if (gzflush(gzFile, Z_FINISH)!=Z_OK) {
+ close(fd);
+ return {};
+ }
+
+ auto gzippedSize = lseek(fd, 0, SEEK_CUR);
+ if (gzippedSize < 0) {
+ close(fd);
+ return {};
+ }
+
+ if (lseek(fd, 0, SEEK_SET)!=0) {
+ close(fd);
+ return {};
+ }
+
+ QByteArray gZipped(gzippedSize, Qt::Initialization::Uninitialized);
+
+ if (read(fd, gZipped.data(), gzippedSize)!=gzippedSize) {
+ close(fd);
+ return {};
+ }
+
+ close(fd);
+ return gZipped;
+}
+
+//-----------------------------------------------------------------------------
+
+QByteArray unGzipData(const QByteArray& inputData)
+{
+ auto fd = memfd_create("decryptThenUnGzipData", 0);
+ if (fd < 0) {
+ return {};
+ }
+
+ if (write(fd, inputData.data(), inputData.length())!=inputData.length()) {
+ close(fd);
+ return {};
+ }
+
+ auto gzippedSize = lseek(fd, 0, SEEK_CUR);
+ if (gzippedSize < 0) {
+ close(fd);
+ return {};
+ }
+
+ if (lseek(fd, 0, SEEK_SET)!=0) {
+ close(fd);
+ return {};
+ }
+
+ auto gzFile = gzdopen(fd, "rb");
+ if (gzFile == nullptr) {
+ close(fd);
+ return {};
+ }
+
+ QBuffer gunzipBuffer;
+ if (!gunzipBuffer.open(QIODevice::WriteOnly)) {
+ return {};
+ }
+
+ while(!gzeof(gzFile)) {
+ char buf[4096];
+ auto a = gzread(gzFile, buf, sizeof(buf));
+ if (a<0) {
+ gunzipBuffer.close();
+ gzclose(gzFile);
+ return {};
+ }
+
+ gunzipBuffer.write(buf, a);
+ }
+
+ gzclose(gzFile);
+ gunzipBuffer.close();
+
+ return gunzipBuffer.data();
+}
+
+//-----------------------------------------------------------------------------
+#endif // HAVE_KARCHIVE
diff --git a/src/libsync/kfcompat.h b/src/libsync/kfcompat.h
new file mode 100644
index 0000000000..ba7eb44067
--- /dev/null
+++ b/src/libsync/kfcompat.h
@@ -0,0 +1,7 @@
+#pragma once
+
+class QByteArray;
+
+QByteArray gZipData(const QByteArray& inputData);
+
+QByteArray unGzipData(const QByteArray& inputData);
diff --git a/src/libsync/networkjobs.cpp b/src/libsync/networkjobs.cpp
index 572bd3d3c9..3b177d9762 100644
--- a/src/libsync/networkjobs.cpp
+++ b/src/libsync/networkjobs.cpp
@@ -10,6 +10,7 @@
#include "owncloudpropagator.h"
#include "clientsideencryption.h"
#include "common/checksums.h"
+#include "common/qtcompat.h"
#include "creds/abstractcredentials.h"
#include "creds/httpcredentials.h"
@@ -813,7 +814,7 @@ bool PropfindJob::finished()
// Parse DAV response
auto domDocument = QDomDocument();
- if (const auto res = domDocument.setContent(reply(), QDomDocument::ParseOption::UseNamespaceProcessing); !res) {
+ if (const auto res = QDomDocumentSetContentsUseNamespaceProcessing(domDocument, reply()); !res) {
qCWarning(lcPropfindJob) << "XML parser error: " << res.errorMessage << res.errorLine << res.errorColumn;
emit finishedWithError(reply());
diff --git a/src/libsync/pushnotifications.cpp b/src/libsync/pushnotifications.cpp
index c7c259ab0f..e7ab6d6ad9 100644
--- a/src/libsync/pushnotifications.cpp
+++ b/src/libsync/pushnotifications.cpp
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+#include "common/qtcompat.h"
#include "pushnotifications.h"
#include "creds/abstractcredentials.h"
#include "account.h"
@@ -21,7 +22,7 @@ PushNotifications::PushNotifications(Account *account, QObject *parent)
, _account(account)
, _webSocket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
{
- connect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::errorOccurred), this, &PushNotifications::onWebSocketError);
+ connect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(QWebSocketErrorOccurred), this, &PushNotifications::onWebSocketError);
connect(_webSocket, &QWebSocket::sslErrors, this, &PushNotifications::onWebSocketSslErrors);
connect(_webSocket, &QWebSocket::connected, this, &PushNotifications::onWebSocketConnected);
connect(_webSocket, &QWebSocket::disconnected, this, &PushNotifications::onWebSocketDisconnected);
@@ -67,7 +68,7 @@ void PushNotifications::closeWebSocket()
_reconnectTimer->stop();
}
- disconnect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::errorOccurred), this, &PushNotifications::onWebSocketError);
+ disconnect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(QWebSocketErrorOccurred), this, &PushNotifications::onWebSocketError);
disconnect(_webSocket, &QWebSocket::sslErrors, this, &PushNotifications::onWebSocketSslErrors);
_webSocket->close();
@@ -165,7 +166,7 @@ void PushNotifications::openWebSocket()
const auto webSocketUrl = capabilities.pushNotificationsWebSocketUrl();
qCInfo(lcPushNotifications) << "Open connection to websocket on" << webSocketUrl << "for account" << _account->url();
- connect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::errorOccurred), this, &PushNotifications::onWebSocketError);
+ connect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(QWebSocketErrorOccurred), this, &PushNotifications::onWebSocketError);
connect(_webSocket, &QWebSocket::sslErrors, this, &PushNotifications::onWebSocketSslErrors);
_webSocket->open(webSocketUrl);
}
diff --git a/src/libsync/theme.cpp b/src/libsync/theme.cpp
index 81342a629e..c0507f205c 100644
--- a/src/libsync/theme.cpp
+++ b/src/libsync/theme.cpp
@@ -9,6 +9,7 @@
#include "version.h"
#include "configfile.h"
#include "common/vfs.h"
+#include "common/qtcompat.h"
#include <QtCore>
#ifndef TOKEN_AUTH_ONLY
@@ -913,14 +914,12 @@ QString Theme::versionSwitchOutput() const
double Theme::getColorDarkness(const QColor &color)
{
- // account for different sensitivity of the human eye to certain colors
- const double threshold = 1.0 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255.0;
- return threshold;
+ return ::getColorDarkness(color);
}
bool Theme::isDarkColor(const QColor &color)
{
- return getColorDarkness(color) > 0.5;
+ return ::isDarkColor(color);
}
QColor Theme::getBackgroundAwareLinkColor(const QColor &backgroundColor)
@@ -1028,7 +1027,7 @@ QColor Theme::defaultColor()
void Theme::connectToPaletteSignal() const
{
if (const auto ptr = qobject_cast<QGuiApplication*>(qApp)) {
- connect(ptr->styleHints(), &QStyleHints::colorSchemeChanged, this, &Theme::darkModeChanged, Qt::UniqueConnection);
+ connectQStyleHintsColorSchemeChanged(ptr, this, &Theme::darkModeChanged);
}
}
@@ -1071,19 +1070,6 @@ QVariantMap Theme::systemPalette() const
bool Theme::darkMode() const
{
connectToPaletteSignal();
- const auto isDarkFromStyle = [] {
- switch (qGuiApp->styleHints()->colorScheme())
- {
- case Qt::ColorScheme::Dark:
- return true;
- case Qt::ColorScheme::Light:
- return false;
- case Qt::ColorScheme::Unknown:
- return Theme::isDarkColor(QGuiApplication::palette().window().color());
- }
-
- return false;
- };
#ifdef Q_OS_WIN
static const auto darkModeSubkey = QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
@@ -1094,7 +1080,8 @@ bool Theme::darkMode() const
}
}
#endif
- return isDarkFromStyle();
+
+ return isDarkMode();
}
bool Theme::displayLegacyImportDialog() const
diff --git a/test/syncenginetestutils.cpp b/test/syncenginetestutils.cpp
index f319561550..93aacb2545 100644
--- a/test/syncenginetestutils.cpp
+++ b/test/syncenginetestutils.cpp
@@ -418,7 +418,7 @@ FakePropfindReply::FakePropfindReply(FileInfo &remoteRootFileInfo, QNetworkAcces
xml.writeTextElement(davUri, QStringLiteral("getcontentlength"), QString::number(fileInfo.size));
xml.writeTextElement(davUri, QStringLiteral("getetag"), QStringLiteral("\"%1\"").arg(QString::fromLatin1(fileInfo.etag)));
xml.writeTextElement(ocUri, QStringLiteral("quota-available-bytes"), fileInfo.folderQuota.bytesAvailableString());
- xml.writeTextElement(ocUri, QStringLiteral("quota-used-bytes"), std::to_string(fileInfo.folderQuota.bytesUsed));
+ xml.writeTextElement(ocUri, QStringLiteral("quota-used-bytes"), QString::number(fileInfo.folderQuota.bytesUsed));
xml.writeTextElement(ocUri, QStringLiteral("permissions"), !fileInfo.permissions.isNull() ? QString(fileInfo.permissions.toString()) : fileInfo.isShared ? QStringLiteral("GSRDNVCKW") : QStringLiteral("GRDNVCKW"));
if (fileInfo.isShared) {
if (fileInfo.downloadForbidden) {
diff --git a/test/testdatefieldbackend.cpp b/test/testdatefieldbackend.cpp
index 850e9c919c..fc0371170e 100644
--- a/test/testdatefieldbackend.cpp
+++ b/test/testdatefieldbackend.cpp
@@ -10,6 +10,7 @@
#include <QTest>
#include <QSignalSpy>
#include <QStandardPaths>
+#include <QTimeZone>
using namespace OCC;
diff --git a/test/testfolder.cpp b/test/testfolder.cpp
index b45cf49114..060f9aca0b 100644
--- a/test/testfolder.cpp
+++ b/test/testfolder.cpp
@@ -12,6 +12,7 @@
#include "accountstate.h"
#include "common/vfs.h"
+#include "common/qtcompat.h"
#include "folder.h"
#include "account.h"
diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp
index 503454e4d7..5f073a2a9e 100644
--- a/test/testsyncengine.cpp
+++ b/test/testsyncengine.cpp
@@ -17,6 +17,7 @@
#include "configfile.h"
#include "propagatorjobs.h"
#include "syncengine.h"
+#include "common/qtcompat.h"
#include <QFile>
#include <QtTest>
diff --git a/test/testsyncjournaldb.cpp b/test/testsyncjournaldb.cpp
index 1e71e25ff7..7bb62edcd7 100644
--- a/test/testsyncjournaldb.cpp
+++ b/test/testsyncjournaldb.cpp
@@ -14,6 +14,7 @@
#include "common/syncjournaldb.h"
#include "common/syncjournalfilerecord.h"
+#include "common/qtcompat.h"
#include "logger.h"
using namespace OCC;
diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp
index c4840c0308..c531e0424e 100644
--- a/test/testsyncvirtualfiles.cpp
+++ b/test/testsyncvirtualfiles.cpp
@@ -11,6 +11,7 @@
#include <QtTest>
#include "syncenginetestutils.h"
#include "common/vfs.h"
+#include "common/qtcompat.h"
#include "config.h"
#include <syncengine.h>