diff --git a/CMakeLists.txt b/CMakeLists.txt
index d46ed4d312..1ed56c1a05 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 c19ede88ce..ee3db931ba 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 564b6c69b5..d0b7f235c9 100644
--- a/src/common/common.cmake
+++ b/src/common/common.cmake
@@ -45,3 +45,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..9b633f0027
--- /dev/null
+++ b/src/common/qtcompat.h
@@ -0,0 +1,357 @@
+
+#pragma once
+
+#include <QtGlobal>
+#include <QLocale>
+#include <QRegularExpression>
+#include <QTimeZone>
+#include <QString>
+
+#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 QStringList QLocale_uiLanguages()
+{
+#if QT_VERSION>=QT_VERSION_CHECK(6, 8, 0)
+    return QLocale::system().uiLanguages(QLocale::TagSeparator::Underscore);
+#else
+    auto languages = QLocale::system().uiLanguages();
+    for (auto& language: languages) {
+        language.replace(QLatin1Char('-'), QLatin1Char('_'));
+    }
+    return languages;
+#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_EQ(computed, baseline) QCOMPARE(computed==baseline, true)
+#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);
+}
+
+inline QLatin1Char operator""_L1(char c)
+{
+    return QLatin1Char(c);
+}
+
+inline QString operator""_s(const char16_t *str, size_t size)
+{
+    return QString(QStringPrivate(nullptr, const_cast<char16_t *>(str),
+                                  qsizetype(size)));
+}
+
+inline QByteArray operator""_ba(const char *str, size_t size)
+{
+    return QByteArray(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
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#ifdef QT_NETWORK_LIB
+
+//-----------------------------------------------------------------------------
+
+#include <QNetworkRequest>
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 8, 0)
+inline void removeAuthorizationHeaders(QNetworkRequest& request)
+{
+    request.setRawHeader("Authorization", QByteArray());
+}
+#else
+inline void removeAuthorizationHeaders(QNetworkRequest& request)
+{
+    auto headers = request.headers();
+    headers.removeAll(QHttpHeaders::WellKnownHeader::Authorization);
+    request.setHeaders(headers);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if QT_VERSION<QT_VERSION_CHECK(6, 7, 0)
+#include <QNetworkReply>
+inline bool QNetworkReplyHasRawHeader(QNetworkReply *reply, const char *header)
+{
+    return reply->hasRawHeader(QByteArray(header));
+}
+#else
+#include <QNetworkReply>
+inline bool QNetworkReplyHasRawHeader(QNetworkReply *reply, const char *header)
+{
+    return reply->hasRawHeader(header);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#endif // QT_NETWORK_LIB
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
diff --git a/src/common/syncjournaldb.cpp b/src/common/syncjournaldb.cpp
index ab99460a0f..6d911b7217 100644
--- a/src/common/syncjournaldb.cpp
+++ b/src/common/syncjournaldb.cpp
@@ -24,6 +24,7 @@
 #include "common/preparedsqlquerymanager.h"
 
 #include "common/c_jhash.h"
+#include "common/qtcompat.h"
 
 // SQL expression to check whether path.startswith(prefix + '/')
 // Note: '/' + 1 == '0'
diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp
index 72e585aea7..9bf2a8c344 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>
@@ -309,7 +310,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);
@@ -471,10 +472,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 0a16af2219..8db5c8e773 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)
@@ -504,10 +504,17 @@ target_link_libraries(nextcloudCore
   Qt::Quick
   Qt::QuickControls2
   Qt::QuickWidgets
-  KF6::Archive
   KDAB::kdsingleapplication
   )
 
+if(KF6Archive_FOUND)
+  target_link_libraries(nextcloudCore
+    PUBLIC
+    KF6::Archive
+  )
+  add_definitions(-DHAVE_KARCHIVE)
+endif()
+
 if(KF6GuiAddons_FOUND)
   target_link_libraries(nextcloudCore
     PUBLIC
@@ -736,3 +743,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/EmojiPicker.qml b/src/gui/EmojiPicker.qml
index f49410d6ea..db71b8e12d 100644
--- a/src/gui/EmojiPicker.qml
+++ b/src/gui/EmojiPicker.qml
@@ -116,10 +116,18 @@ ColumnLayout {
                 }
 
                 ToolTip {
-                    popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                    id: emojiDelegateToolTip
+
                     text: modelData === undefined ? "" : modelData.shortname
                     visible: emojiDelegate.hovered
                     delay: Qt.styleHints.mousePressAndHoldInterval
+
+                    Binding {
+                        target: emojiDelegateToolTip
+                        property: "popupType"
+                        value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                        when: emojiDelegateToolTip.hasOwnProperty("popupType")
+                    }
                 }
 
                 onClicked: {
diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp
index d88cb2a4d1..8a1637ba91 100644
--- a/src/gui/accountsettings.cpp
+++ b/src/gui/accountsettings.cpp
@@ -10,6 +10,7 @@
 #include "common/syncjournalfilerecord.h"
 #include "qmessagebox.h"
 #include "ui_accountsettings.h"
+#include "common/qtcompat.h"
 
 #include "theme.h"
 #include "foldercreationdialog.h"
diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp
index d139565a56..41e2924fce 100644
--- a/src/gui/accountstate.cpp
+++ b/src/gui/accountstate.cpp
@@ -17,6 +17,7 @@
 #include "ocsuserstatusconnector.h"
 #include "pushnotifications.h"
 #include "networkjobs.h"
+#include "common/qtcompat.h"
 
 #include <QSettings>
 #include <QTimer>
diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp
index 7f478534af..62f583617b 100644
--- a/src/gui/advancedsettings.cpp
+++ b/src/gui/advancedsettings.cpp
@@ -28,7 +28,9 @@
 #include "common/utility_mac_sandbox.h"
 #endif
 
+#ifdef HAVE_KARCHIVE
 #include <KZip>
+#endif
 
 #include <QDir>
 #include <QDirIterator>
@@ -122,6 +124,7 @@ QVector<ZipEntry> createDebugArchiveFileList()
     return list;
 }
 
+#ifdef HAVE_KARCHIVE
 bool createDebugArchive(const QString &filename)
 {
     const auto entries = createDebugArchiveFileList();
@@ -222,6 +225,8 @@ bool createDebugArchive(const QString &filename)
     return true;
 }
 
+#endif // HAVE_KARCHIVE
+
 } // namespace
 
 namespace OCC {
@@ -373,6 +378,7 @@ void AdvancedSettings::slotCreateDebugArchive()
         return;
     }
 
+#ifdef HAVE_KARCHIVE
 #ifdef Q_OS_MACOS
     auto scopedAccess = Utility::MacSandboxSecurityScopedAccess::create(destination);
 
@@ -393,6 +399,13 @@ void AdvancedSettings::slotCreateDebugArchive()
             tr("Redact information deemed sensitive before sharing! Debug archive created at %1").arg(destination.toLocalFile())
         );
     }
+#else
+    QMessageBox::information(
+        this,
+        tr("Debug Archive Not Available"),
+        tr("Debug archive creation is not available on this platform.")
+    );
+#endif
 }
 
 void AdvancedSettings::slotRemotePollIntervalChanged(int seconds)
diff --git a/src/gui/application.cpp b/src/gui/application.cpp
index f68fb3db2f..ac0b5cdc3e 100644
--- a/src/gui/application.cpp
+++ b/src/gui/application.cpp
@@ -31,6 +31,7 @@
 #include "version.h"
 #include "csync_exclude.h"
 #include "common/vfs.h"
+#include "common/qtcompat.h"
 
 #include "config.h"
 
@@ -1118,7 +1119,7 @@ void Application::setupTranslations()
     qCInfo(lcApplication) << "System UI languages are:" << QLocale::system().uiLanguages();
     auto choosenLanguage = enforcedLanguage();
     if (choosenLanguage.isEmpty()) {
-        for(const auto &localeToTest : QLocale::system().uiLanguages(QLocale::TagSeparator::Underscore)){
+        for(const auto &localeToTest : QLocale_uiLanguages()){
             const auto trFile = QString{QLatin1String{"client_"} + localeToTest};
             qCDebug(lcApplication()) << "trying to load" << localeToTest << "in" << trFile << "from" << trPath;
             if (translator->load(trFile, trPath)) {
diff --git a/src/gui/filedetails/FileDetailsPage.qml b/src/gui/filedetails/FileDetailsPage.qml
index c061eff726..2a0751b07c 100644
--- a/src/gui/filedetails/FileDetailsPage.qml
+++ b/src/gui/filedetails/FileDetailsPage.qml
@@ -196,9 +196,17 @@ Page {
                     }
 
                     ToolTip {
-                        popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                        id: overflowTagToolTip
+
                         visible: hoverHandler.hovered
                         text: tagRepeater.fileTagModel.overflowTagsString
+
+                        Binding {
+                            target: overflowTagToolTip
+                            property: "popupType"
+                            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                            when: overflowTagToolTip.hasOwnProperty("popupType")
+                        }
                     }
                 }
             }
diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp
index 7fe6760ed2..a39f60c2aa 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 "logger.h"
 #include <pushnotifications.h>
diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp
index 5c3504674f..b58163fa23 100644
--- a/src/gui/folderstatusmodel.cpp
+++ b/src/gui/folderstatusmodel.cpp
@@ -8,6 +8,7 @@
 #include "accountstate.h"
 #include "common/asserts.h"
 #include "common/utility.h"
+#include "common/qtcompat.h"
 #include "folderman.h"
 #include "folderstatusdelegate.h"
 #include <account.h>
diff --git a/src/gui/folderwizard.cpp b/src/gui/folderwizard.cpp
index 9208814e36..074c6fd519 100644
--- a/src/gui/folderwizard.cpp
+++ b/src/gui/folderwizard.cpp
@@ -15,6 +15,7 @@
 #include "creds/abstractcredentials.h"
 #include "guiutility.h"
 #include "common/asserts.h"
+#include "common/qtcompat.h"
 
 #ifdef Q_OS_MACOS
 #include "common/utility_mac_sandbox.h"
@@ -587,7 +588,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/owncloudsetupwizard.cpp b/src/gui/owncloudsetupwizard.cpp
index 01d95502d1..27dd0bfdc9 100644
--- a/src/gui/owncloudsetupwizard.cpp
+++ b/src/gui/owncloudsetupwizard.cpp
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
+#include "common/qtcompat.h"
 #include "owncloudsetupwizard.h"
 
 #include "folderman.h"
diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp
index 58f50275fa..49a87bdafd 100644
--- a/src/gui/settingsdialog.cpp
+++ b/src/gui/settingsdialog.cpp
@@ -17,6 +17,7 @@
 #include "progressdispatcher.h"
 #include "owncloudgui.h"
 #include "accountmanager.h"
+#include "common/qtcompat.h"
 
 #include <QLabel>
 #include <QStandardItemModel>
diff --git a/src/gui/sharemanager.cpp b/src/gui/sharemanager.cpp
index 42b61a5d84..ac29fbf181 100644
--- a/src/gui/sharemanager.cpp
+++ b/src/gui/sharemanager.cpp
@@ -11,6 +11,7 @@
 #include "accountstate.h"
 #include "clientsideencryption.h"
 #include "updatee2eefolderusersmetadatajob.h"
+#include "common/qtcompat.h"
 
 #include <QUrl>
 #include <QJsonDocument>
diff --git a/src/gui/socketapi/socketapi.cpp b/src/gui/socketapi/socketapi.cpp
index 496a2a4d10..02b74a7c3f 100644
--- a/src/gui/socketapi/socketapi.cpp
+++ b/src/gui/socketapi/socketapi.cpp
@@ -18,6 +18,7 @@
 #include "encryptfolderjob.h"
 #include "theme.h"
 #include "common/syncjournalfilerecord.h"
+#include "common/qtcompat.h"
 #include "syncengine.h"
 #include "syncfileitem.h"
 #include "filesystem.h"
diff --git a/src/gui/sslerrordialog.cpp b/src/gui/sslerrordialog.cpp
index b6ec909176..50716a585e 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/ActivityItem.qml b/src/gui/tray/ActivityItem.qml
index 6af9ec3c16..4195dd305b 100644
--- a/src/gui/tray/ActivityItem.qml
+++ b/src/gui/tray/ActivityItem.qml
@@ -30,9 +30,17 @@ ItemDelegate {
     Accessible.onPressAction: root.clicked()
 
     ToolTip {
-        popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+        id: rootToolTip
+
         visible: root.hovered && !activityContent.childHovered && model.displayLocation !== ""
         text: qsTr("In %1").arg(model.displayLocation)
+
+        Binding {
+            target: rootToolTip
+            property: "popupType"
+            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+            when: rootToolTip.hasOwnProperty("popupType")
+        }
     }
 
     // TODO: the current style does not support customization of this control
diff --git a/src/gui/tray/ActivityItemContent.qml b/src/gui/tray/ActivityItemContent.qml
index fbea235484..b416ff1bda 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: {{}}
 
@@ -179,9 +179,17 @@ RowLayout {
                     icon.height: Style.activityListButtonIconSize
 
                     ToolTip {
-                        popupType: Qt.platform.os === "windows" ? Popup.Item : Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                        id: fieldDetailsButtonToolTip
+
                         text: qsTr("Open file details")
                         visible: parent.hovered
+
+                        Binding {
+                            target: fieldDetailsButtonToolTip
+                            property: "popupType"
+                            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                            when: fieldDetailsButtonToolTip.hasOwnProperty("popupType")
+                        }
                     }
 
                     display: Button.IconOnly
@@ -225,9 +233,17 @@ RowLayout {
                     display: Button.IconOnly
 
                     ToolTip {
-                        popupType: Qt.platform.os === "windows" ? Popup.Item : Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                        id: dismissActionButtonToolTip
+
                         text: qsTr("Dismiss")
                         visible: parent.hovered
+
+                        Binding {
+                            target: dismissActionButtonToolTip
+                            property: "popupType"
+                            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                            when: dismissActionButtonToolTip.hasOwnProperty("popupType")
+                        }
                     }
 
                     visible: root.showDismissButton
diff --git a/src/gui/tray/TalkReplyTextField.qml b/src/gui/tray/TalkReplyTextField.qml
index 28e3883633..6ed9550d9b 100644
--- a/src/gui/tray/TalkReplyTextField.qml
+++ b/src/gui/tray/TalkReplyTextField.qml
@@ -52,9 +52,17 @@ TextField {
         }
 
         ToolTip {
-            popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+            id: sendReplyMessageButtonToolTip
+
             visible: sendReplyMessageButton.hovered
             text:  qsTr("Send reply to chat message")
+
+            Binding {
+                target: sendReplyMessageButtonToolTip
+                property: "popupType"
+                value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+                when: sendReplyMessageButtonToolTip.hasOwnProperty("popupType")
+            }
         }
     }
 }
diff --git a/src/gui/tray/TrayFolderListItem.qml b/src/gui/tray/TrayFolderListItem.qml
index feb8303830..b2e29a7df9 100644
--- a/src/gui/tray/TrayFolderListItem.qml
+++ b/src/gui/tray/TrayFolderListItem.qml
@@ -17,9 +17,17 @@ MenuItem {
     property string toolTipText: root.text
 
     ToolTip {
-        popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+        id: rootToolTip
+
         visible: root.hovered && root.toolTipText !== ""
         text: root.toolTipText
+
+        Binding {
+            target: rootToolTip
+            property: "popupType"
+            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+            when: rootToolTip.hasOwnProperty("popupType")
+        }
     }
 
     contentItem: RowLayout {
diff --git a/src/gui/tray/TrayFoldersMenuButton.qml b/src/gui/tray/TrayFoldersMenuButton.qml.in
similarity index 95%
rename from src/gui/tray/TrayFoldersMenuButton.qml
rename to src/gui/tray/TrayFoldersMenuButton.qml.in
index 82b2640d61..141e608dcd 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
@@ -57,9 +57,16 @@ HeaderButton {
 
     ToolTip {
         id: tooltip
-        popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+
         visible: root.hovered && !foldersMenuLoader.isMenuVisible
-        text: root.userHasGroupFolders ? qsTr("Open local or team folders") : qsTr("Open local folder")
+        text: root.userHasGroupFolders ? qsTr("Open local or group folders") : qsTr("Open local folder")
+
+        Binding {
+            target: tooltip
+            property: "popupType"
+            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+            when: tooltip.hasOwnProperty("popupType")
+        }
     }
 
 
diff --git a/src/gui/tray/UnifiedSearchResultListItem.qml b/src/gui/tray/UnifiedSearchResultListItem.qml
index 6c998598fb..5866e1615a 100644
--- a/src/gui/tray/UnifiedSearchResultListItem.qml
+++ b/src/gui/tray/UnifiedSearchResultListItem.qml
@@ -30,9 +30,17 @@ MouseArea {
     height: Style.unifiedSearchItemHeight
 
     ToolTip {
-        popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+        id: unifiedSearchResultMouseAreaToolTop
+
         visible: unifiedSearchResultMouseArea.containsMouse
         text: isFetchMoreTrigger ? qsTr("Load more results") : model.resultTitle + "\n\n" + model.subline
+
+        Binding {
+            target: unifiedSearchResultMouseAreaToolTop
+            property: "popupType"
+            value: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
+            when: unifiedSearchResultMouseAreaToolTop.hasOwnProperty("popupType")
+        }
     }
 
     Rectangle {
diff --git a/src/gui/tray/activitydata.cpp b/src/gui/tray/activitydata.cpp
index aeaad62a3a..f85170046e 100644
--- a/src/gui/tray/activitydata.cpp
+++ b/src/gui/tray/activitydata.cpp
@@ -8,6 +8,7 @@
 
 #include "activitydata.h"
 #include "folderman.h"
+#include "common/qtcompat.h"
 
 using namespace Qt::StringLiterals;
 
diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp
index 9034750791..c7a6e8b7b2 100644
--- a/src/gui/tray/activitylistmodel.cpp
+++ b/src/gui/tray/activitylistmodel.cpp
@@ -18,6 +18,7 @@
 #include "activitydata.h"
 #include "systray.h"
 #include "common/utility.h"
+#include "common/qtcompat.h"
 
 #include <QtCore>
 #include <QAbstractListModel>
diff --git a/src/gui/tray/asyncimageresponse.cpp b/src/gui/tray/asyncimageresponse.cpp
index 875a2d16eb..58969f7546 100644
--- a/src/gui/tray/asyncimageresponse.cpp
+++ b/src/gui/tray/asyncimageresponse.cpp
@@ -10,6 +10,8 @@
 #include <QPainter>
 #include <QSvgRenderer>
 
+#include "common/qtcompat.h"
+
 #include "accountmanager.h"
 
 using namespace Qt::StringLiterals;
diff --git a/src/gui/tray/notificationhandler.cpp b/src/gui/tray/notificationhandler.cpp
index cf0624367a..cde9cec563 100644
--- a/src/gui/tray/notificationhandler.cpp
+++ b/src/gui/tray/notificationhandler.cpp
@@ -8,6 +8,7 @@
 #include "accountstate.h"
 #include "capabilities.h"
 #include "networkjobs.h"
+#include "common/qtcompat.h"
 
 #include "iconjob.h"
 
diff --git a/src/gui/tray/talkreply.cpp b/src/gui/tray/talkreply.cpp
index 8e8a1a8d61..f917c6d7ac 100644
--- a/src/gui/tray/talkreply.cpp
+++ b/src/gui/tray/talkreply.cpp
@@ -7,6 +7,7 @@
 
 #include "accountstate.h"
 #include "networkjobs.h"
+#include "common/qtcompat.h"
 
 #include <QJsonDocument>
 #include <QJsonObject>
diff --git a/src/gui/tray/unifiedsearchresultslistmodel.cpp b/src/gui/tray/unifiedsearchresultslistmodel.cpp
index 424bc4c191..c478caa092 100644
--- a/src/gui/tray/unifiedsearchresultslistmodel.cpp
+++ b/src/gui/tray/unifiedsearchresultslistmodel.cpp
@@ -10,6 +10,7 @@
 #include "guiutility.h"
 #include "folderman.h"
 #include "networkjobs.h"
+#include "common/qtcompat.h"
 
 #include <algorithm>
 
diff --git a/src/gui/tray/usermodel.cpp b/src/gui/tray/usermodel.cpp
index 84fb7fe599..139762fcdf 100644
--- a/src/gui/tray/usermodel.cpp
+++ b/src/gui/tray/usermodel.cpp
@@ -27,6 +27,7 @@
 #include "userstatusconnector.h"
 #include "common/utility.h"
 #include "ocsassistantconnector.h"
+#include "common/qtcompat.h"
 
 #ifdef BUILD_FILE_PROVIDER_MODULE
 #include "gui/macOS/fileprovider.h"
diff --git a/src/gui/userinfo.cpp b/src/gui/userinfo.cpp
index b65a604b72..b15ac6c1e2 100644
--- a/src/gui/userinfo.cpp
+++ b/src/gui/userinfo.cpp
@@ -10,6 +10,7 @@
 #include "folderman.h"
 #include "creds/abstractcredentials.h"
 #include <theme.h>
+#include "common/qtcompat.h"
 
 #include <QTimer>
 #include <QJsonDocument>
diff --git a/src/gui/wizard/accountwizardcontroller.cpp b/src/gui/wizard/accountwizardcontroller.cpp
index 95f6b89ee4..9001c95bda 100644
--- a/src/gui/wizard/accountwizardcontroller.cpp
+++ b/src/gui/wizard/accountwizardcontroller.cpp
@@ -5,6 +5,8 @@
 
 #include "wizard/accountwizardcontroller.h"
 
+#include "common/qtcompat.h"
+
 #include "account.h"
 #include "accountmanager.h"
 #include "clientproxy.h"
@@ -1993,7 +1995,7 @@ bool AccountWizardController::checkDowngradeAdvised(QNetworkReply *reply) const
         break;
     }
 
-    return !reply->hasRawHeader("Strict-Transport-Security"_L1);
+    return !QNetworkReplyHasRawHeader(reply, "Strict-Transport-Security");
 }
 
 } // namespace OCC
diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt
index be060e8ce2..4a41f4fedc 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)
@@ -166,6 +166,8 @@ set(libsync_SRCS
     creds/keychainchunk.cpp
     caseclashconflictsolver.h
     caseclashconflictsolver.cpp
+    kfcompat.h
+    kfcompat.cpp
 )
 
 if (WIN32)
@@ -239,10 +241,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/abstractnetworkjob.cpp b/src/libsync/abstractnetworkjob.cpp
index 199f7c0546..588dc8ad3b 100644
--- a/src/libsync/abstractnetworkjob.cpp
+++ b/src/libsync/abstractnetworkjob.cpp
@@ -5,6 +5,7 @@
  */
 
 #include "common/asserts.h"
+#include "common/qtcompat.h"
 #include "networkjobs.h"
 #include "account.h"
 #include "owncloudpropagator.h"
@@ -281,9 +282,7 @@ void AbstractNetworkJob::slotFinished()
                         << " origin=" << requestedUrl.host() << ":" << requestedUrl.port()
                         << " target=" << redirectUrl.host() << ":" << redirectUrl.port();
 
-                    auto headers = request.headers();
-                    headers.removeAll(QHttpHeaders::WellKnownHeader::Authorization);
-                    request.setHeaders(headers);
+                    removeAuthorizationHeaders(request);
                     request.setAttribute(AbstractCredentials::DontAddCredentialsAttribute, true);
                 }
 
diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp
index d55b7951ea..4a5f91ee95 100644
--- a/src/libsync/account.cpp
+++ b/src/libsync/account.cpp
@@ -25,6 +25,7 @@
 
 #include "common/syncjournaldb.h"
 #include "common/asserts.h"
+#include "common/qtcompat.h"
 #include "clientsideencryption.h"
 #include "ocsuserstatusconnector.h"
 
@@ -1295,7 +1296,8 @@ void Account::listRemoteFolder(QPromise<OCC::PlaceholderCreateInfo> *promise, co
             return;
         }
 
-        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 c5426ef2df..3268280a73 100644
--- a/src/libsync/clientsideencryption.cpp
+++ b/src/libsync/clientsideencryption.cpp
@@ -14,11 +14,12 @@
 #include "common/utility.h"
 #include "common/constants.h"
 #include <common/checksums.h>
+#include <common/qtcompat.h>
 #include "wordlist.h"
 
 #include <qt6keychain/keychain.h>
 
-#include <KCompressionDevice>
+#include "kfcompat.h"
 
 #include <QDebug>
 #include <QLoggingCategory>
@@ -2747,26 +2748,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;
 }
 
@@ -2778,23 +2765,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 394a7b22fd..d70e078c89 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/discoveryphase.cpp b/src/libsync/discoveryphase.cpp
index 602ded6293..fd805dbe93 100644
--- a/src/libsync/discoveryphase.cpp
+++ b/src/libsync/discoveryphase.cpp
@@ -17,6 +17,7 @@
 
 #include "common/asserts.h"
 #include "common/checksums.h"
+#include "common/qtcompat.h"
 
 #include <csync_exclude.h>
 #include "vio/csync_vio_local.h"
diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp
index e27301c035..762d93a25c 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 8cd4709d96..2baaf83268 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"
@@ -814,7 +815,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/ocsassistantconnector.cpp b/src/libsync/ocsassistantconnector.cpp
index d15483e4a5..98661733c6 100644
--- a/src/libsync/ocsassistantconnector.cpp
+++ b/src/libsync/ocsassistantconnector.cpp
@@ -7,6 +7,7 @@
 
 #include "account.h"
 #include "networkjobs.h"
+#include "common/qtcompat.h"
 
 #include <QJsonDocument>
 #include <QLoggingCategory>
diff --git a/src/libsync/ocsuserstatusconnector.cpp b/src/libsync/ocsuserstatusconnector.cpp
index a70088034e..4943ccd79c 100644
--- a/src/libsync/ocsuserstatusconnector.cpp
+++ b/src/libsync/ocsuserstatusconnector.cpp
@@ -6,6 +6,7 @@
 #include "ocsuserstatusconnector.h"
 #include "account.h"
 #include "userstatusconnector.h"
+#include "common/qtcompat.h"
 
 #include <networkjobs.h>
 
diff --git a/src/libsync/propagateuploadng.cpp b/src/libsync/propagateuploadng.cpp
index 0582611616..617a0b5381 100644
--- a/src/libsync/propagateuploadng.cpp
+++ b/src/libsync/propagateuploadng.cpp
@@ -18,6 +18,7 @@
 #include "propagateremotemove.h"
 #include "deletejob.h"
 #include "common/asserts.h"
+#include "common/qtcompat.h"
 
 #include <QNetworkAccessManager>
 #include <QFileInfo>
diff --git a/src/libsync/pushnotifications.cpp b/src/libsync/pushnotifications.cpp
index 74729921fe..fbf9fb6bc5 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"
@@ -25,7 +26,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);
@@ -71,7 +72,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();
@@ -171,7 +172,7 @@ void PushNotifications::openWebSocket()
     const auto webSocketUrl = capabilities.pushNotificationsWebSocketUrl();
 
     qCInfo(lcPushNotifications) << "Open connection to websocket on" << webSocketUrl << "for account" << _account->displayName() << _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);
 }
@@ -216,7 +217,7 @@ void PushNotifications::handleNotifyFileId(const QString &message)
 
     QList<qint64> fileIds{};
     QJsonParseError parseError;
-    const auto fileIdsJson = message.mid(NOTIFY_FILE_ID_PREFIX.length());
+    const auto fileIdsJson = message.mid(NOTIFY_FILE_ID_PREFIX.size());
     const auto jsonDoc = QJsonDocument::fromJson(fileIdsJson.toUtf8(), &parseError);
 
     if (parseError.error != QJsonParseError::NoError) {
diff --git a/src/libsync/syncfileitem.cpp b/src/libsync/syncfileitem.cpp
index d5aa8776a1..baf79a8e2e 100644
--- a/src/libsync/syncfileitem.cpp
+++ b/src/libsync/syncfileitem.cpp
@@ -8,6 +8,7 @@
 #include "common/checksums.h"
 #include "common/syncjournalfilerecord.h"
 #include "common/utility.h"
+#include "common/qtcompat.h"
 #include "helpers.h"
 #include "filesystem.h"
 
diff --git a/src/libsync/theme.cpp b/src/libsync/theme.cpp
index 830554b98e..7576d5452c 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
@@ -916,14 +917,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)
@@ -1038,7 +1037,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);
     }
 }
 
@@ -1081,19 +1080,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");
@@ -1104,7 +1090,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 bd6a7d441c..01ed6685bc 100644
--- a/test/syncenginetestutils.cpp
+++ b/test/syncenginetestutils.cpp
@@ -438,7 +438,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/testaccount.cpp b/test/testaccount.cpp
index 9f032c6ebe..5fefa5d295 100644
--- a/test/testaccount.cpp
+++ b/test/testaccount.cpp
@@ -12,6 +12,7 @@
 #include <QTemporaryDir>
 #include <QtTest>
 
+#include "common/qtcompat.h"
 #include "account.h"
 #include "accountstate.h"
 #include "logger.h"
diff --git a/test/testaccountsettings.cpp b/test/testaccountsettings.cpp
index b43723f630..93568774f0 100644
--- a/test/testaccountsettings.cpp
+++ b/test/testaccountsettings.cpp
@@ -16,6 +16,8 @@
 
 #include "accountsettings.h"
 
+#include "common/qtcompat.h"
+
 using namespace OCC;
 
 class TestAccountSettings : public QObject
diff --git a/test/testactivitydata.cpp b/test/testactivitydata.cpp
index 3a3f8ad923..0cb3f0cd01 100644
--- a/test/testactivitydata.cpp
+++ b/test/testactivitydata.cpp
@@ -8,6 +8,7 @@
 #include "accountstate.h"
 #include "syncenginetestutils.h"
 #include "testhelper.h"
+#include "common/qtcompat.h"
 
 #include <QTest>
 #include <QHash>
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/testfilesystem.cpp b/test/testfilesystem.cpp
index 37abf3784f..57ae135aee 100644
--- a/test/testfilesystem.cpp
+++ b/test/testfilesystem.cpp
@@ -12,6 +12,7 @@
 #include <QTemporaryFile>
 
 #include "common/filesystembase.h"
+#include "common/qtcompat.h"
 #include "logger.h"
 
 #include "libsync/filesystem.h"
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/testfolderman.cpp b/test/testfolderman.cpp
index 127a9b4f31..f377bcb8bf 100644
--- a/test/testfolderman.cpp
+++ b/test/testfolderman.cpp
@@ -14,6 +14,7 @@
 
 #include "QtTest/qtestcase.h"
 #include "common/utility.h"
+#include "common/qtcompat.h"
 #include "folderman.h"
 #include "account.h"
 #include "accountstate.h"
diff --git a/test/testlocaldiscovery.cpp b/test/testlocaldiscovery.cpp
index e5e2a943dc..6b02d0e8b7 100644
--- a/test/testlocaldiscovery.cpp
+++ b/test/testlocaldiscovery.cpp
@@ -13,6 +13,8 @@
 #include <syncengine.h>
 #include <localdiscoverytracker.h>
 
+#include "common/qtcompat.h"
+
 using namespace OCC;
 using namespace Qt::StringLiterals;
 
diff --git a/test/testnextcloudpropagator.cpp b/test/testnextcloudpropagator.cpp
index 1568313f4a..9deea92c6d 100644
--- a/test/testnextcloudpropagator.cpp
+++ b/test/testnextcloudpropagator.cpp
@@ -17,6 +17,8 @@
 #include "owncloudpropagator_p.h"
 #include "syncenginetestutils.h"
 
+#include "common/qtcompat.h"
+
 using namespace Qt::StringLiterals;
 
 #ifdef HAVE_QHTTPSERVER
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 38fb455f5b..cec9154e21 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>
 
