Quellcode durchsuchen

Merge pull request #4251 from nextcloud/feature/darkmode

Add a dark mode
Matthieu Gallien vor 3 Jahren
Ursprung
Commit
db129a09f2
46 geänderte Dateien mit 441 neuen und 124 gelöschten Zeilen
  1. 25 0
      src/gui/systray.cpp
  2. 8 0
      src/gui/systray.h
  3. 6 0
      src/gui/systray.mm
  4. 2 2
      src/gui/tray/ActivityActionButton.qml
  5. 15 4
      src/gui/tray/ActivityItem.qml
  6. 18 6
      src/gui/tray/ActivityItemActions.qml
  7. 28 8
      src/gui/tray/ActivityItemContent.qml
  8. 2 0
      src/gui/tray/ActivityItemContextMenu.qml
  9. 6 0
      src/gui/tray/AutoSizingMenu.qml
  10. 16 6
      src/gui/tray/CustomButton.qml
  11. 11 2
      src/gui/tray/CustomTextButton.qml
  12. 8 0
      src/gui/tray/FileActivityDialog.qml
  13. 1 1
      src/gui/tray/HeaderButton.qml
  14. 2 1
      src/gui/tray/SyncStatus.qml
  15. 3 0
      src/gui/tray/UnifiedSearchInputContainer.qml
  16. 1 1
      src/gui/tray/UnifiedSearchResultFetchMoreTrigger.qml
  17. 3 3
      src/gui/tray/UnifiedSearchResultItem.qml
  18. 2 2
      src/gui/tray/UnifiedSearchResultItemSkeleton.qml
  19. 3 3
      src/gui/tray/UnifiedSearchResultItemSkeletonContainer.qml
  20. 11 2
      src/gui/tray/UnifiedSearchResultListItem.qml
  21. 1 1
      src/gui/tray/UnifiedSearchResultNothingFound.qml
  22. 10 6
      src/gui/tray/UserLine.qml
  23. 33 11
      src/gui/tray/Window.qml
  24. 35 13
      src/gui/tray/activitylistmodel.cpp
  25. 1 0
      src/gui/tray/activitylistmodel.h
  26. 46 42
      src/gui/tray/unifiedsearchresultslistmodel.cpp
  27. 12 0
      src/libsync/theme.cpp
  28. 8 1
      src/libsync/theme.h
  29. 15 0
      theme.qrc.in
  30. 10 9
      theme/Style/Style.qml
  31. 1 0
      theme/black/change.svg
  32. 1 0
      theme/black/close.svg
  33. 1 0
      theme/black/confirm.svg
  34. 0 0
      theme/black/settings.svg
  35. 2 0
      theme/white/activity.svg
  36. 39 0
      theme/white/bell.svg
  37. 0 0
      theme/white/calendar.svg
  38. 0 0
      theme/white/change.svg
  39. 1 0
      theme/white/close.svg
  40. 1 0
      theme/white/comment.svg
  41. 1 0
      theme/white/confirm.svg
  42. 8 0
      theme/white/deck.svg
  43. 43 0
      theme/white/edit.svg
  44. 1 0
      theme/white/email.svg
  45. 0 0
      theme/white/settings.svg
  46. 0 0
      theme/white/state-info.svg

+ 25 - 0
src/gui/systray.cpp

@@ -31,6 +31,7 @@
 #include <QQuickWindow>
 #include <QScreen>
 #include <QMenu>
+#include <QGuiApplication>
 
 #ifdef USE_FDO_NOTIFICATIONS
 #include <QDBusConnection>
@@ -129,6 +130,12 @@ Systray::Systray()
     });
 #endif
 
+    const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance());
+    if(ptr) {
+        _guiAppInstance.reset(ptr);
+        connect(ptr, &QGuiApplication::paletteChanged, this, &Systray::darkModeChanged);
+    }
+
     connect(UserModel::instance(), &UserModel::newUserSelected,
         this, &Systray::slotNewUserSelected);
     connect(UserModel::instance(), &UserModel::addAccount,
@@ -224,6 +231,24 @@ bool Systray::useNormalWindow() const
     return cfg.showMainDialogAsNormalWindow();
 }
 
+bool Systray::darkMode()
+{
+#if defined(Q_OS_MACOS)
+    return osXInDarkMode();
+// Windows: Check registry for dark mode
+#elif defined(Q_OS_WIN)
+    const auto darkModeSubkey = QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
+    if (!Utility::registryKeyExists(HKEY_CURRENT_USER, darkModeSubkey)) {
+        return false;
+    }
+    const auto darkMode = Utility::registryGetKeyValue(HKEY_CURRENT_USER, darkModeSubkey, QStringLiteral("AppsUseLightTheme")).toBool();
+    return darkMode;
+// Probably Linux
+#else
+    return Theme::isDarkColor(QGuiApplication::palette().window().color());
+#endif
+}
+
 Q_INVOKABLE void Systray::setOpened()
 {
     _isOpen = true;

+ 8 - 0
src/gui/systray.h

@@ -27,6 +27,7 @@ class QQmlApplicationEngine;
 class QQuickWindow;
 class QWindow;
 class QQuickWindow;
+class QGuiApplication;
 
 namespace OCC {
 
@@ -39,6 +40,7 @@ public:
 };
 
 #ifdef Q_OS_OSX
+bool osXInDarkMode();
 bool canOsXSendUserNotification();
 void sendOsXUserNotification(const QString &title, const QString &message);
 void setTrayWindowLevelAndVisibleOnAllSpaces(QWindow *window);
@@ -56,6 +58,7 @@ class Systray
 
     Q_PROPERTY(QString windowTitle READ windowTitle CONSTANT)
     Q_PROPERTY(bool useNormalWindow READ useNormalWindow CONSTANT)
+    Q_PROPERTY(bool darkMode READ darkMode NOTIFY darkModeChanged)
 
 public:
     static Systray *instance();
@@ -71,6 +74,7 @@ public:
     bool isOpen();
     QString windowTitle() const;
     bool useNormalWindow() const;
+    bool darkMode();
 
     Q_INVOKABLE void pauseResumeSync();
     Q_INVOKABLE bool syncIsPaused();
@@ -93,6 +97,8 @@ signals:
     void showFileActivityDialog(const QString &objectName, const int objectId);
     void sendChatMessage(const QString &token, const QString &message, const QString &replyTo);
 
+    void darkModeChanged();
+
 public slots:
     void slotNewUserSelected();
 
@@ -119,6 +125,8 @@ private:
     QPointer<QQmlApplicationEngine> _trayEngine;
 
     AccessManagerFactory _accessManagerFactory;
+
+    QScopedPointer<QGuiApplication> _guiAppInstance;
 };
 
 } // namespace OCC

+ 6 - 0
src/gui/systray.mm

@@ -56,4 +56,10 @@ void setTrayWindowLevelAndVisibleOnAllSpaces(QWindow *window)
     [nativeWindow setLevel:NSMainMenuWindowLevel];
 }
 
+bool osXInDarkMode()
+{
+    NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
+    return [osxMode containsString:@"Dark"];
+}
+
 }

+ 2 - 2
src/gui/tray/ActivityActionButton.qml

@@ -15,8 +15,8 @@ Item {
     property string imageSource: ""
     property string imageSourceHover: ""
 
-    property color textColor: Style.unifiedSearchResulTitleColor
-    property color textColorHovered: Style.unifiedSearchResulSublineColor
+    property color textColor: Style.ncTextColor
+    property color textColorHovered: Style.ncSecondaryTextColor
 
     signal clicked()
 

+ 15 - 4
src/gui/tray/ActivityItem.qml

@@ -22,10 +22,6 @@ MouseArea {
 
     height: childrenRect.height
 
-    ToolTip.visible: containsMouse && !activityContent.childHovered && model.displayLocation !== ""
-    ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
-    ToolTip.text: qsTr("In %1").arg(model.displayLocation)
-
     Accessible.role: Accessible.ListItem
     Accessible.name: (model.path !== "" && model.displayPath !== "") ? qsTr("Open %1 locally").arg(model.displayPath) : model.message
     Accessible.onPressAction: root.clicked()
@@ -36,6 +32,21 @@ MouseArea {
         color: (parent.containsMouse ? Style.lightHover : "transparent")
     }
 
+    ToolTip {
+        id: activityMouseAreaTooltip
+        visible: containsMouse && !activityContent.childHovered && model.displayLocation !== ""
+        delay: Qt.styleHints.mousePressAndHoldInterval
+        text: qsTr("In %1").arg(model.displayLocation)
+        contentItem: Label {
+            text: activityMouseAreaTooltip.text
+            color: Style.ncTextColor
+        }
+        background: Rectangle {
+            border.color: Style.menuBorder
+            color: Style.backgroundColor
+        }
+    }
+
     ColumnLayout {
         anchors.left: root.left
         anchors.right: root.right

+ 18 - 6
src/gui/tray/ActivityItemActions.qml

@@ -43,8 +43,8 @@ RowLayout {
             imageSource: model.modelData.imageSource
             imageSourceHover: model.modelData.imageSourceHovered
 
-            textColor: imageSource !== "" ? UserModel.currentUser.headerColor : Style.unifiedSearchResulSublineColor
-            textColorHovered: imageSource !== "" ? Style.lightHover : Style.unifiedSearchResulTitleColor
+            textColor: imageSource !== "" ? UserModel.currentUser.headerColor : Style.ncTextColor
+            textColorHovered: imageSource !== "" ? Style.lightHover : Style.ncTextColor
 
             bold: primary
 
@@ -67,15 +67,27 @@ RowLayout {
             id: moreActionsButton
 
             icon.source: "qrc:///client/theme/more.svg"
+            icon.color: Style.ncTextColor
 
             background: Rectangle {
-                color: parent.hovered ? "white" : root.moreActionsButtonColor
+                color: parent.hovered ? Style.lightHover : root.moreActionsButtonColor
                 radius: width / 2
             }
 
-            ToolTip.visible: hovered
-            ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
-            ToolTip.text: qsTr("Show more actions")
+            ToolTip {
+                id: moreActionsButtonTooltip
+                visible: parent.hovered
+                delay: Qt.styleHints.mousePressAndHoldInterval
+                text: qsTr("Show more actions")
+                contentItem: Label {
+                    text: moreActionsButtonTooltip.text
+                    color: Style.ncTextColor
+                }
+                background: Rectangle {
+                    border.color: Style.menuBorder
+                    color: Style.backgroundColor
+                }
+            }
 
             Accessible.name: qsTr("Show more actions")
 

+ 28 - 8
src/gui/tray/ActivityItemContent.qml

@@ -76,7 +76,12 @@ RowLayout {
             anchors.right: if(model.thumbnail !== undefined) parent.right
             anchors.bottom: if(model.thumbnail !== undefined) parent.bottom
             cache: true
-            source: icon
+
+            property string sourceUrl: Systray.darkMode ?
+                model.icon.replace("__COLOR__", "white").replace("__WHITE_GOES_HERE__", "-white") :
+                model.icon.replace("__COLOR__", "black").replace("__WHITE_GOES_HERE__", "")
+
+            source: sourceUrl
             sourceSize.height: 64
             sourceSize.width: 64
         }
@@ -99,7 +104,8 @@ RowLayout {
             wrapMode: Text.Wrap
             maximumLineCount: 2
             font.pixelSize: Style.topLinePixelSize
-            color: root.activityData.activityTextTitleColor
+            color: Style.ncTextColor
+            //color: root.activityData.activityTextTitleColor
         }
 
         Label {
@@ -114,6 +120,7 @@ RowLayout {
             wrapMode: Text.Wrap
             maximumLineCount: 2
             font.pixelSize: Style.subLinePixelSize
+            color: Style.ncTextColor
         }
 
         Label {
@@ -125,8 +132,8 @@ RowLayout {
             wrapMode: Text.Wrap
             maximumLineCount: 2
             font.pixelSize: Style.subLinePixelSize
-            color: "#808080"
-        }  
+            color: Style.ncSecondaryTextColor
+        }
 
         Loader {
             id: talkReplyTextFieldLoader
@@ -152,9 +159,20 @@ RowLayout {
 
         Layout.margins: Style.roundButtonBackgroundVerticalMargins
 
-        ToolTip.visible: hovered
-        ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
-        ToolTip.text: qsTr("Dismiss")
+        ToolTip {
+            id: dismissActionButtonTooltip
+            visible: parent.hovered
+            delay: Qt.styleHints.mousePressAndHoldInterval
+            text: qsTr("Dismiss")
+            contentItem: Label {
+                text: dismissActionButtonTooltip.text
+                color: Style.ncTextColor
+            }
+            background: Rectangle {
+                border.color: Style.menuBorder
+                color: Style.backgroundColor
+            }
+        }
 
         Accessible.name: qsTr("Dismiss")
 
@@ -166,7 +184,9 @@ RowLayout {
 
         contentItem: Image {
             anchors.fill: parent
-            source: parent.hovered ? "image://svgimage-custom-color/clear.svg/black" : "image://svgimage-custom-color/clear.svg/grey"
+            source: parent.hovered ? Systray.darkMode ?
+                "image://svgimage-custom-color/clear.svg/white" : "image://svgimage-custom-color/clear.svg/black" :
+                "image://svgimage-custom-color/clear.svg/grey"
             sourceSize.width: 24
             sourceSize.height: 24
         }

+ 2 - 0
src/gui/tray/ActivityItemContextMenu.qml

@@ -1,6 +1,7 @@
 import QtQml 2.15
 import QtQuick 2.15
 import QtQuick.Controls 2.3
+import Style 1.0
 
 AutoSizingMenu {
     id: moreActionsButtonContextMenu
@@ -19,6 +20,7 @@ AutoSizingMenu {
         delegate: MenuItem {
             id: moreActionsButtonContextMenuEntry
             text: model.modelData.label
+            palette.windowText: Style.ncTextColor
             onTriggered: menuEntryTriggered(model.modelData.actionIndex)
         }
     }

+ 6 - 0
src/gui/tray/AutoSizingMenu.qml

@@ -1,7 +1,13 @@
 import QtQuick 2.15
 import QtQuick.Controls 2.3
+import Style 1.0
 
 Menu {
+    background: Rectangle {
+        border.color: Style.menuBorder
+        color: Style.backgroundColor
+    }
+
     width: {
         var result = 0;
         var padding = 0;

+ 16 - 6
src/gui/tray/CustomButton.qml

@@ -1,6 +1,7 @@
 import QtQuick 2.15
 import QtQuick.Controls 2.3
 import QtQuick.Layouts 1.2
+import Style 1.0
 
 Button {
     id: root
@@ -26,6 +27,21 @@ Button {
     leftPadding: root.text === "" ? 5 : 10
     rightPadding: root.text === "" ? 5 : 10
 
+    ToolTip {
+        id: customButtonTooltip
+        text: root.toolTipText
+        delay: Qt.styleHints.mousePressAndHoldInterval
+        visible: root.toolTipText !== "" && root.hovered
+        contentItem: Label {
+            text: customButtonTooltip.text
+            color: Style.ncTextColor
+        }
+        background: Rectangle {
+            border.color: Style.menuBorder
+            color: Style.backgroundColor
+        }
+    }
+
     contentItem: RowLayout {
         Image {
             id: icon
@@ -52,10 +68,4 @@ Button {
             elide: Text.ElideRight
         }
     }
-
-    ToolTip {
-        text: root.toolTipText
-        delay: Qt.styleHints.mousePressAndHoldInterval
-        visible: root.toolTipText !== "" && root.hovered
-    }
 }

+ 11 - 2
src/gui/tray/CustomTextButton.qml

@@ -12,8 +12,8 @@ Label {
 
     height: implicitHeight
 
-    property color textColor: Style.unifiedSearchResulTitleColor
-    property color textColorHovered: Style.unifiedSearchResulSublineColor
+    property color textColor: Style.ncTextColor
+    property color textColorHovered: Style.ncSecondaryTextColor
 
     Accessible.role: Accessible.Button
     Accessible.name: text
@@ -33,9 +33,18 @@ Label {
     signal clicked(QtObject mouse)
 
     ToolTip {
+        id: customTextButtonTooltip
         text: root.toolTipText
         delay: Qt.styleHints.mousePressAndHoldInterval
         visible: root.toolTipText !== "" && root.hovered
+        contentItem: Label {
+            text: customTextButtonTooltip.text
+            color: Style.ncTextColor
+        }
+        background: Rectangle {
+            border.color: Style.menuBorder
+            color: Style.backgroundColor
+        }
     }
 
     MouseArea {

+ 8 - 0
src/gui/tray/FileActivityDialog.qml

@@ -1,6 +1,8 @@
+import QtQml 2.15
 import QtQuick 2.15
 import QtQuick.Window 2.15
 
+import Style 1.0
 import com.nextcloud.desktopclient 1.0 as NC
 
 Window {
@@ -15,6 +17,12 @@ Window {
     width: 500
     height: 500
 
+    Rectangle {
+        id: background
+        anchors.fill: parent
+        color: Style.backgroundColor
+    }
+
     ActivityList {
         isFileActivityList: true
         anchors.fill: parent

+ 1 - 1
src/gui/tray/HeaderButton.qml

@@ -18,7 +18,7 @@ Button {
 
     icon.width: Style.headerButtonIconSize
     icon.height: Style.headerButtonIconSize
-    icon.color: Style.ncTextColor
+    icon.color: Style.ncHeaderTextColor
 
     Layout.alignment: Qt.AlignRight
     Layout.preferredWidth:  Style.trayWindowHeaderHeight

+ 2 - 1
src/gui/tray/SyncStatus.qml

@@ -62,6 +62,7 @@ RowLayout {
             verticalAlignment: Text.AlignVCenter
             font.pixelSize: Style.topLinePixelSize
             font.bold: true
+            color: Style.ncTextColor
         }
 
         Loader {
@@ -84,7 +85,7 @@ RowLayout {
 
             text: syncStatus.syncStatusDetailString
             visible: syncStatus.syncStatusDetailString !== ""
-            color: "#808080"
+            color: Style.ncSecondaryTextColor
             font.pixelSize: Style.subLinePixelSize
         }
     }

+ 3 - 0
src/gui/tray/UnifiedSearchInputContainer.qml

@@ -28,10 +28,13 @@ TextField {
 
     selectByMouse: true
 
+    palette.text: Style.ncSecondaryTextColor
+
     background: Rectangle {
         radius: 5
         border.color: parent.activeFocus ? UserModel.currentUser.accentColor : Style.menuBorder
         border.width: 1
+        color: Style.backgroundColor
     }
 
     Image {

+ 1 - 1
src/gui/tray/UnifiedSearchResultFetchMoreTrigger.qml

@@ -13,7 +13,7 @@ ColumnLayout {
 
     property int fontSize: Style.topLinePixelSize
 
-    property string textColor: "grey"
+    property string textColor: Style.ncSecondaryTextColor
 
     Accessible.role: Accessible.ListItem
     Accessible.name: unifiedSearchResultItemFetchMoreText.text

+ 3 - 3
src/gui/tray/UnifiedSearchResultItem.qml

@@ -23,8 +23,8 @@ RowLayout {
     property int titleFontSize: Style.topLinePixelSize
     property int sublineFontSize: Style.subLinePixelSize
 
-    property string titleColor: "black"
-    property string sublineColor: "grey"
+    property color titleColor: Style.ncTextColor
+    property color sublineColor: Style.ncSecondaryTextColor
 
     Accessible.role: Accessible.ListItem
     Accessible.name: resultTitle
@@ -65,12 +65,12 @@ RowLayout {
         }
         Image {
             id: unifiedSearchResultThumbnailPlaceholder
-            visible: icons && iconPlaceholder && unifiedSearchResultThumbnail.status !== Image.Ready
             Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
             Layout.leftMargin: iconLeftMargin
             verticalAlignment: Qt.AlignCenter
             cache: true
             source: iconPlaceholder
+            visible: false
             sourceSize.height: unifiedSearchResultItemDetails.iconWidth
             sourceSize.width: unifiedSearchResultItemDetails.iconWidth
             Layout.preferredWidth: unifiedSearchResultItemDetails.iconWidth

+ 2 - 2
src/gui/tray/UnifiedSearchResultItemSkeleton.qml

@@ -14,8 +14,8 @@ RowLayout {
     property int titleFontSize: Style.topLinePixelSize
     property int sublineFontSize: Style.subLinePixelSize
 
-    property string titleColor: "black"
-    property string sublineColor: "grey"
+    property color titleColor: Style.ncTextColor
+    property color sublineColor: Style.ncSecondaryTextColor
 
     property string iconColor: "#afafaf"
 

+ 3 - 3
src/gui/tray/UnifiedSearchResultItemSkeletonContainer.qml

@@ -13,9 +13,9 @@ Column {
     property int itemHeight: Style.trayWindowHeaderHeight
     property int titleFontSize: Style.topLinePixelSize
     property int sublineFontSize: Style.subLinePixelSize
-    property string titleColor: "black"
-    property string sublineColor: "grey"
-    property string iconColor: "#afafaf"
+    property color titleColor: Style.ncTextColor
+    property color sublineColor: Style.ncSecondaryTextColor
+    property color iconColor: "#afafaf"
 
     Repeater {
         model: 10

+ 11 - 2
src/gui/tray/UnifiedSearchResultListItem.qml

@@ -14,8 +14,8 @@ MouseArea {
     property int titleFontSize: Style.topLinePixelSize
     property int sublineFontSize: Style.subLinePixelSize
 
-    property string titleColor: "black"
-    property string sublineColor: "grey"
+    property color titleColor: Style.ncTextColor
+    property color sublineColor: Style.ncSecondaryTextColor
 
     property string currentFetchMoreInProgressProviderId: ""
 
@@ -33,9 +33,18 @@ MouseArea {
     hoverEnabled: enabled
 
     ToolTip {
+        id: unifiedSearchResultMouseAreaTooltip
         visible: unifiedSearchResultMouseArea.containsMouse
         text: isFetchMoreTrigger ? qsTr("Load more results") : model.resultTitle + "\n\n" + model.subline
         delay: Qt.styleHints.mousePressAndHoldInterval
+        contentItem: Label {
+            text: unifiedSearchResultMouseAreaTooltip.text
+            color: Style.ncTextColor
+        }
+        background: Rectangle {
+            border.color: Style.menuBorder
+            color: Style.backgroundColor
+        }
     }
 
     Rectangle {

+ 1 - 1
src/gui/tray/UnifiedSearchResultNothingFound.qml

@@ -35,7 +35,7 @@ ColumnLayout {
     Label {
         id: unifiedSearchResultsNoResultsLabelDetails
         text: unifiedSearchResultNothingFoundContainer.text
-        color: "black"
+        color: Style.ncTextColor
         font.pixelSize: Style.topLinePixelSize * 1.25
         wrapMode: Text.Wrap
         maximumLineCount: 2

+ 10 - 6
src/gui/tray/UserLine.qml

@@ -48,7 +48,7 @@ MenuItem {
                 Rectangle {
                     anchors.fill: parent
                     anchors.margins: 1
-                    color: parent.parent.hovered || parent.parent.visualFocus ? Style.lightHover : "transparent"
+                    color: parent.parent.hovered || parent.parent.visualFocus ? Style.lightHover : Style.backgroundColor
                 }
             }
 
@@ -61,7 +61,7 @@ MenuItem {
                     Layout.leftMargin: 7
                     verticalAlignment: Qt.AlignCenter
                     cache: false
-                    source: model.avatar != "" ? model.avatar : "image://avatars/fallbackBlack"
+                    source: model.avatar != "" ? model.avatar : Systray.darkMode ? "image://avatars/fallbackWhite" : "image://avatars/fallbackBlack"
                     Layout.preferredHeight: Style.accountAvatarSize
                     Layout.preferredWidth: Style.accountAvatarSize
                     Rectangle {
@@ -100,7 +100,7 @@ MenuItem {
                         id: accountUser
                         text: name
                         elide: Text.ElideRight
-                        color: "black"
+                        color: Style.ncTextColor
                         font.pixelSize: Style.topLinePixelSize
                         font.bold: true
                         width: parent.width
@@ -121,7 +121,7 @@ MenuItem {
                             visible: model.statusMessage !== ""
                             text: statusMessage
                             elide: Text.ElideRight
-                            color: "black"
+                            color: Style.ncTextColor
                             font.pixelSize: Style.subLinePixelSize
                             leftPadding: Style.accountLabelsSpacing
                         }
@@ -132,7 +132,7 @@ MenuItem {
                         height: Style.topLinePixelSize
                         text: server
                         elide: Text.ElideRight
-                        color: "black"
+                        color: Style.ncTextColor
                         font.pixelSize: Style.subLinePixelSize
                     }
                 }
@@ -146,7 +146,7 @@ MenuItem {
             flat: true
 
             icon.source: "qrc:///client/theme/more.svg"
-            icon.color: "transparent"
+            icon.color: Style.ncTextColor
 
             Accessible.role: Accessible.ButtonMenu
             Accessible.name: qsTr("Account actions")
@@ -173,6 +173,7 @@ MenuItem {
 
                 background: Rectangle {
                     border.color: Style.menuBorder
+                    color: Style.backgroundColor
                     radius: 2
                 }
 
@@ -181,6 +182,7 @@ MenuItem {
                     height: visible ? implicitHeight : 0
                     text: qsTr("Set status")
                     font.pixelSize: Style.topLinePixelSize
+                    palette.windowText: Style.ncTextColor
                     hoverEnabled: true
                     onClicked: {
                         showUserStatusSelectorDialog(index)
@@ -201,6 +203,7 @@ MenuItem {
                 MenuItem {
                     text: model.isConnected ? qsTr("Log out") : qsTr("Log in")
                     font.pixelSize: Style.topLinePixelSize
+                    palette.windowText: Style.ncTextColor
                     hoverEnabled: true
                     onClicked: {
                         model.isConnected ? UserModel.logout(index) : UserModel.login(index)
@@ -234,6 +237,7 @@ MenuItem {
                     id: removeAccountButton
                     text: qsTr("Remove account")
                     font.pixelSize: Style.topLinePixelSize
+                    palette.windowText: Style.ncTextColor
                     hoverEnabled: true
                     onClicked: {
                         UserModel.removeAccount(index)

+ 33 - 11
src/gui/tray/Window.qml

@@ -111,6 +111,7 @@ Window {
         radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius
         border.width:   Style.trayWindowBorderWidth
         border.color:   Style.menuBorder
+        color: Style.backgroundColor
 
         Accessible.role: Accessible.Grouping
         Accessible.name: qsTr("Nextcloud desktop main dialog")
@@ -137,6 +138,7 @@ Window {
                     Layout.preferredHeight: Style.trayWindowHeaderHeight
                     display:                AbstractButton.IconOnly
                     flat:                   true
+                    palette: Style.systemPalette
 
                     Accessible.role: Accessible.ButtonMenu
                     Accessible.name: qsTr("Current account")
@@ -168,9 +170,11 @@ Window {
                         width: (Style.currentAccountButtonWidth - 2)
                         height: Math.min(implicitHeight, maxMenuHeight)
                         closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
+                        palette: Style.palette
 
                         background: Rectangle {
                             border.color: Style.menuBorder
+                            color: Style.backgroundColor
                             radius: Style.currentAccountButtonRadius
                         }
 
@@ -216,6 +220,7 @@ Window {
                             id: addAccountButton
                             height: Style.addAccountButtonHeight
                             hoverEnabled: true
+                            palette: Theme.systemPalette
 
                             background: Item {
                                 height: parent.height
@@ -234,14 +239,14 @@ Window {
                                 Image {
                                     Layout.leftMargin: 12
                                     verticalAlignment: Qt.AlignCenter
-                                    source: "qrc:///client/theme/black/add.svg"
+                                    source: Systray.darkMode ? "qrc:///client/theme/white/add.svg" : "qrc:///client/theme/black/add.svg"
                                     sourceSize.width: Style.headerButtonIconSize
                                     sourceSize.height: Style.headerButtonIconSize
                                 }
                                 Label {
                                     Layout.leftMargin: 14
                                     text: qsTr("Add account")
-                                    color: "black"
+                                    color: Style.ncTextColor
                                     font.pixelSize: Style.topLinePixelSize
                                 }
                                 // Filler on the right
@@ -267,6 +272,7 @@ Window {
                         MenuItem {
                             id: syncPauseButton
                             font.pixelSize: Style.topLinePixelSize
+                            palette.windowText: Style.ncTextColor
                             hoverEnabled: true
                             onClicked: Systray.pauseResumeSync()
 
@@ -289,6 +295,7 @@ Window {
                             id: settingsButton
                             text: qsTr("Settings")
                             font.pixelSize: Style.topLinePixelSize
+                            palette.windowText: Style.ncTextColor
                             hoverEnabled: true
                             onClicked: Systray.openSettings()
 
@@ -311,6 +318,7 @@ Window {
                             id: exitButton
                             text: qsTr("Exit");
                             font.pixelSize: Style.topLinePixelSize
+                            palette.windowText: Style.ncTextColor
                             hoverEnabled: true
                             onClicked: Systray.shutdown()
 
@@ -411,6 +419,7 @@ Window {
                                 text: UserModel.currentUser.name
                                 elide: Text.ElideRight
                                 color: UserModel.currentUser.headerTextColor
+
                                 font.pixelSize: Style.topLinePixelSize
                                 font.bold: true
                             }
@@ -566,6 +575,7 @@ Window {
 
                         background: Rectangle {
                             border.color: Style.menuBorder
+                            color: Style.backgroundColor
                             radius: 2
                         }
 
@@ -578,10 +588,22 @@ Window {
                                 id: appEntry
                                 text: appName
                                 font.pixelSize: Style.topLinePixelSize
+                                palette.windowText: Style.ncTextColor
                                 icon.source: appIconUrl
+                                icon.color: Style.ncTextColor
                                 onTriggered: UserAppsModel.openAppUrl(appUrl)
                                 hoverEnabled: true
 
+                                background: Item {
+                                    height: parent.height
+                                    width: parent.width
+                                    Rectangle {
+                                        anchors.fill: parent
+                                        anchors.margins: 1
+                                        color: parent.parent.hovered || parent.parent.visualFocus ? Style.lightHover : "transparent"
+                                    }
+                                }
+
                                 Accessible.role: Accessible.MenuItem
                                 Accessible.name: qsTr("Open %1 in browser").arg(appName)
                                 Accessible.onPressAction: appEntry.triggered()
@@ -713,16 +735,16 @@ Window {
 
                 delegate: UnifiedSearchResultListItem {
                     width: unifiedSearchResultsListView.width
-                    height: trayWindowBackground.Style.unifiedSearchItemHeight
+                    height: Style.unifiedSearchItemHeight
                     isSearchInProgress:  unifiedSearchResultsListView.model.isSearchInProgress
-                    textLeftMargin: trayWindowBackground.Style.unifiedSearchResultTextLeftMargin
-                    textRightMargin: trayWindowBackground.Style.unifiedSearchResultTextRightMargin
-                    iconWidth: trayWindowBackground.Style.unifiedSearchResulIconWidth
-                    iconLeftMargin: trayWindowBackground.Style.unifiedSearchResulIconLeftMargin
-                    titleFontSize: trayWindowBackground.Style.unifiedSearchResulTitleFontSize
-                    sublineFontSize: trayWindowBackground.Style.unifiedSearchResulSublineFontSize
-                    titleColor: trayWindowBackground.Style.unifiedSearchResulTitleColor
-                    sublineColor: trayWindowBackground.Style.unifiedSearchResulSublineColor
+                    textLeftMargin: Style.unifiedSearchResultTextLeftMargin
+                    textRightMargin: Style.unifiedSearchResultTextRightMargin
+                    iconWidth: Style.unifiedSearchResulIconWidth
+                    iconLeftMargin: Style.unifiedSearchResulIconLeftMargin
+                    titleFontSize: Style.unifiedSearchResulTitleFontSize
+                    sublineFontSize: Style.unifiedSearchResulSublineFontSize
+                    titleColor: Style.ncTextColor
+                    sublineColor: Style.ncSecondaryTextColor
                     currentFetchMoreInProgressProviderId: unifiedSearchResultsListView.model.currentFetchMoreInProgressProviderId
                     fetchMoreTriggerClicked: unifiedSearchResultsListView.model.fetchMoreTriggerClicked
                     resultClicked: unifiedSearchResultsListView.model.resultClicked

+ 35 - 13
src/gui/tray/activitylistmodel.cpp

@@ -33,6 +33,7 @@
 
 #include "activitydata.h"
 #include "activitylistmodel.h"
+#include "systray.h"
 
 #include "theme.h"
 
@@ -215,41 +216,48 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
     }
 
     case ActionIconRole: {
+        auto colorIconPath = QStringLiteral("qrc:///client/theme/__COLOR__/"); // We will replace __COLOR__ in QML
         if (a._type == Activity::NotificationType) {
-            return "qrc:///client/theme/black/bell.svg";
+            colorIconPath.append("bell.svg");
+            return colorIconPath;
         } else if (a._type == Activity::SyncResultType) {
-            return "qrc:///client/theme/black/state-error.svg";
+            colorIconPath.append("state-error.svg");
+            return colorIconPath;
         } else if (a._type == Activity::SyncFileItemType) {
             if (a._status == SyncFileItem::NormalError
                 || a._status == SyncFileItem::FatalError
                 || a._status == SyncFileItem::DetailError
                 || a._status == SyncFileItem::BlacklistedError) {
-                return "qrc:///client/theme/black/state-error.svg";
+                colorIconPath.append("state-error.svg");
+                return colorIconPath;
             } else if (a._status == SyncFileItem::SoftError
                 || a._status == SyncFileItem::Conflict
                 || a._status == SyncFileItem::Restoration
                 || a._status == SyncFileItem::FileLocked
                 || a._status == SyncFileItem::FileNameInvalid) {
-                return "qrc:///client/theme/black/state-warning.svg";
+                colorIconPath.append("state-warning.svg");
+                return colorIconPath;
             } else if (a._status == SyncFileItem::FileIgnored) {
-                return "qrc:///client/theme/black/state-info.svg";
+                colorIconPath.append("state-info.svg");
+                return colorIconPath;
             } else {
                 // File sync successful
                 if (a._fileAction == "file_created") {
-                    return a._previews.empty() ? "qrc:///client/theme/colored/add.svg"
-                                               : "qrc:///client/theme/colored/add-bordered.svg";
+                    return a._previews.empty() ? QStringLiteral("qrc:///client/theme/colored/add.svg")
+                                               : QStringLiteral("qrc:///client/theme/colored/add-bordered.svg");
                 } else if (a._fileAction == "file_deleted") {
-                    return a._previews.empty() ? "qrc:///client/theme/colored/delete.svg"
-                                               : "qrc:///client/theme/colored/delete-bordered.svg";
+                    return a._previews.empty() ? QStringLiteral("qrc:///client/theme/colored/delete.svg")
+                                               : QStringLiteral("qrc:///client/theme/colored/delete-bordered.svg");
                 } else {
-                    return a._previews.empty() ? "qrc:///client/theme/change.svg"
-                                               : "qrc:///client/theme/colored/change-bordered.svg";
+                    return a._previews.empty() ? colorIconPath % QStringLiteral("change.svg")
+                                               : QStringLiteral("qrc:///client/theme/colored/change-bordered.svg");
                 }
             }
         } else {
             // We have an activity
             if (a._icon.isEmpty()) {
-                return "qrc:///client/theme/black/activity.svg";
+                colorIconPath.append("activity.svg");
+                return colorIconPath;
             }
 
             return a._icon;
@@ -390,7 +398,21 @@ void ActivityListModel::ingestActivities(const QJsonArray &activities)
     for (const auto &activ : activities) {
         const auto json = activ.toObject();
 
-        const auto a = Activity::fromActivityJson(json, _accountState->account());
+        auto a = Activity::fromActivityJson(json, _accountState->account());
+
+        auto colorIconPath = QStringLiteral("qrc:///client/theme/__COLOR__/");
+        if(a._icon.contains("change.svg")) {
+            colorIconPath.append("change.svg");
+            a._icon = colorIconPath;
+        } else if(a._icon.contains("calendar.svg")) {
+            colorIconPath.append("calendar.svg");
+            a._icon = colorIconPath;
+        } else if(a._icon.contains("personal.svg")) {
+            colorIconPath.append("user.svg");
+            a._icon = colorIconPath;
+        }  else if(a._icon.contains("core/img/actions")) {
+            a._icon.insert(a._icon.indexOf(".svg"), "__WHITE_GOES_HERE__");
+        }
 
         list.append(a);
         _currentItem = list.last()._id;

+ 1 - 0
src/gui/tray/activitylistmodel.h

@@ -115,6 +115,7 @@ signals:
     void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
 
 protected:
+    void setup();
     void activitiesReceived(const QJsonDocument &json, int statusCode);
     QHash<int, QByteArray> roleNames() const override;
 

+ 46 - 42
src/gui/tray/unifiedsearchresultslistmodel.cpp

@@ -19,6 +19,7 @@
 #include "guiutility.h"
 #include "folderman.h"
 #include "networkjobs.h"
+#include "systray.h"
 
 #include <algorithm>
 
@@ -30,17 +31,17 @@ QString imagePlaceholderUrlForProviderId(const QString &providerId)
 {
     if (providerId.contains(QStringLiteral("message"), Qt::CaseInsensitive)
         || providerId.contains(QStringLiteral("talk"), Qt::CaseInsensitive)) {
-        return QStringLiteral("qrc:///client/theme/black/wizard-talk.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral("qrc:///client/theme/white/wizard-talk.svg") : QStringLiteral("qrc:///client/theme/black/wizard-talk.svg");
     } else if (providerId.contains(QStringLiteral("file"), Qt::CaseInsensitive)) {
-        return QStringLiteral("qrc:///client/theme/black/edit.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral("qrc:///client/theme/white/edit.svg") : QStringLiteral("qrc:///client/theme/black/edit.svg");
     } else if (providerId.contains(QStringLiteral("deck"), Qt::CaseInsensitive)) {
-        return QStringLiteral("qrc:///client/theme/black/deck.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral("qrc:///client/theme/white/deck.svg") : QStringLiteral("qrc:///client/theme/black/deck.svg");
     } else if (providerId.contains(QStringLiteral("calendar"), Qt::CaseInsensitive)) {
-        return QStringLiteral("qrc:///client/theme/black/calendar.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral("qrc:///client/theme/white/calendar.svg") : QStringLiteral("qrc:///client/theme/black/calendar.svg");
     } else if (providerId.contains(QStringLiteral("mail"), Qt::CaseInsensitive)) {
-        return QStringLiteral("qrc:///client/theme/black/email.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral("qrc:///client/theme/white/email.svg") : QStringLiteral("qrc:///client/theme/black/email.svg");
     } else if (providerId.contains(QStringLiteral("comment"), Qt::CaseInsensitive)) {
-        return QStringLiteral("qrc:///client/theme/black/comment.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral("qrc:///client/theme/white/comment.svg") : QStringLiteral("qrc:///client/theme/black/comment.svg");
     }
 
     return QStringLiteral("qrc:///client/theme/change.svg");
@@ -50,20 +51,20 @@ QString localIconPathFromIconPrefix(const QString &iconNameWithPrefix)
 {
     if (iconNameWithPrefix.contains(QStringLiteral("message"), Qt::CaseInsensitive)
         || iconNameWithPrefix.contains(QStringLiteral("talk"), Qt::CaseInsensitive)) {
-        return QStringLiteral(":/client/theme/black/wizard-talk.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/wizard-talk.svg") : QStringLiteral(":/client/theme/black/wizard-talk.svg");
     } else if (iconNameWithPrefix.contains(QStringLiteral("folder"), Qt::CaseInsensitive)) {
-        return QStringLiteral(":/client/theme/black/folder.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/folder.svg") : QStringLiteral(":/client/theme/black/folder.svg");
     } else if (iconNameWithPrefix.contains(QStringLiteral("deck"), Qt::CaseInsensitive)) {
-        return QStringLiteral(":/client/theme/black/deck.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/deck.svg") : QStringLiteral(":/client/theme/black/deck.svg");
     } else if (iconNameWithPrefix.contains(QStringLiteral("contacts"), Qt::CaseInsensitive)) {
-        return QStringLiteral(":/client/theme/black/wizard-groupware.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/wizard-groupware.svg") : QStringLiteral(":/client/theme/black/wizard-groupware.svg");
     } else if (iconNameWithPrefix.contains(QStringLiteral("calendar"), Qt::CaseInsensitive)) {
-        return QStringLiteral(":/client/theme/black/calendar.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/calendar.svg") : QStringLiteral(":/client/theme/black/calendar.svg");
     } else if (iconNameWithPrefix.contains(QStringLiteral("mail"), Qt::CaseInsensitive)) {
-        return QStringLiteral(":/client/theme/black/email.svg");
+        return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/email.svg") : QStringLiteral(":/client/theme/black/email.svg");
     }
 
-    return QStringLiteral(":/client/theme/change.svg");
+    return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/change.svg") : QStringLiteral(":/client/theme/change.svg");
 }
 
 QString iconUrlForDefaultIconName(const QString &defaultIconName)
@@ -78,16 +79,17 @@ QString iconUrlForDefaultIconName(const QString &defaultIconName)
         const auto parts = defaultIconName.split(QLatin1Char('-'));
 
         if (parts.size() > 1) {
-            const QString iconFilePath = QStringLiteral(":/client/theme/") + parts[1] + QStringLiteral(".svg");
+            const QString blackOrWhite = OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/") : QStringLiteral(":/client/theme/black/");
+            const QString blackIconFilePath = blackOrWhite + parts[1] + QStringLiteral(".svg");
 
-            if (QFile::exists(iconFilePath)) {
-                return iconFilePath;
+            if (QFile::exists(blackIconFilePath)) {
+                return blackIconFilePath;
             }
 
-            const QString blackIconFilePath = QStringLiteral(":/client/theme/black/") + parts[1] + QStringLiteral(".svg");
+            const QString iconFilePath = QStringLiteral(":/client/theme/") + parts[1] + QStringLiteral(".svg");
 
-            if (QFile::exists(blackIconFilePath)) {
-                return blackIconFilePath;
+            if (QFile::exists(iconFilePath)) {
+                return iconFilePath;
             }
         }
 
@@ -98,7 +100,7 @@ QString iconUrlForDefaultIconName(const QString &defaultIconName)
         }
     }
 
-    return QStringLiteral(":/client/theme/change.svg");
+    return OCC::Systray::instance()->darkMode() ? QStringLiteral(":/client/theme/white/change.svg") : QStringLiteral(":/client/theme/change.svg");
 }
 
 QString generateUrlForThumbnail(const QString &thumbnailUrl, const QUrl &serverUrl)
@@ -123,57 +125,59 @@ QString generateUrlForThumbnail(const QString &thumbnailUrl, const QUrl &serverU
     return thumbnailUrlCopy;
 }
 
-QString generateUrlForIcon(const QString &fallackIcon, const QUrl &serverUrl)
+QString generateUrlForIcon(const QString &fallbackIcon, const QUrl &serverUrl)
 {
     auto serverUrlCopy = serverUrl;
 
-    auto fallackIconCopy = fallackIcon;
+    auto fallbackIconCopy = fallbackIcon;
 
-    if (fallackIconCopy.startsWith(QLatin1Char('/')) || fallackIconCopy.startsWith(QLatin1Char('\\'))) {
+    if (fallbackIconCopy.startsWith(QLatin1Char('/')) || fallbackIconCopy.startsWith(QLatin1Char('\\'))) {
         // relative image resource URL, just needs some concatenation with current server URL
         // some icons may contain parameters after (?)
-        const QStringList fallackIconPathSplitted =
-            fallackIconCopy.contains(QLatin1Char('?')) ? fallackIconCopy.split(QLatin1Char('?')) : QStringList{fallackIconCopy};
-        Q_ASSERT(!fallackIconPathSplitted.isEmpty());
-        serverUrlCopy.setPath(fallackIconPathSplitted[0]);
-        fallackIconCopy = serverUrlCopy.toString();
-        if (fallackIconPathSplitted.size() > 1) {
-            fallackIconCopy += QLatin1Char('?') + fallackIconPathSplitted[1];
+        const QStringList fallbackIconPathSplitted =
+            fallbackIconCopy.contains(QLatin1Char('?')) ? fallbackIconCopy.split(QLatin1Char('?')) : QStringList{fallbackIconCopy};
+        Q_ASSERT(!fallbackIconPathSplitted.isEmpty());
+        serverUrlCopy.setPath(fallbackIconPathSplitted[0]);
+        fallbackIconCopy = serverUrlCopy.toString();
+        if (fallbackIconPathSplitted.size() > 1) {
+            fallbackIconCopy += QLatin1Char('?') + fallbackIconPathSplitted[1];
         }
-    } else if (!fallackIconCopy.isEmpty()) {
+    } else if (!fallbackIconCopy.isEmpty()) {
         // could be one of names for standard icons (e.g. icon-mail)
-        const auto defaultIconUrl = iconUrlForDefaultIconName(fallackIconCopy);
+        const auto defaultIconUrl = iconUrlForDefaultIconName(fallbackIconCopy);
         if (!defaultIconUrl.isEmpty()) {
-            fallackIconCopy = defaultIconUrl;
+            fallbackIconCopy = defaultIconUrl;
         }
     }
 
-    return fallackIconCopy;
+    return fallbackIconCopy;
 }
 
-QString iconsFromThumbnailAndFallbackIcon(const QString &thumbnailUrl, const QString &fallackIcon, const QUrl &serverUrl)
+QString iconsFromThumbnailAndFallbackIcon(const QString &thumbnailUrl, const QString &fallbackIcon, const QUrl &serverUrl)
 {
-    if (thumbnailUrl.isEmpty() && fallackIcon.isEmpty()) {
+    if (thumbnailUrl.isEmpty() && fallbackIcon.isEmpty()) {
         return {};
     }
 
     if (serverUrl.isEmpty()) {
-        const QStringList listImages = {thumbnailUrl, fallackIcon};
+        const QStringList listImages = {thumbnailUrl, fallbackIcon};
         return listImages.join(QLatin1Char(';'));
     }
 
     const auto urlForThumbnail = generateUrlForThumbnail(thumbnailUrl, serverUrl);
-    const auto urlForFallackIcon = generateUrlForIcon(fallackIcon, serverUrl);
+    const auto urlForFallbackIcon = generateUrlForIcon(fallbackIcon, serverUrl);
+
+    qDebug() << "SEARCH" << urlForThumbnail << urlForFallbackIcon;
 
-    if (urlForThumbnail.isEmpty() && !urlForFallackIcon.isEmpty()) {
-        return urlForFallackIcon;
+    if (urlForThumbnail.isEmpty() && !urlForFallbackIcon.isEmpty()) {
+        return urlForFallbackIcon;
     }
 
-    if (!urlForThumbnail.isEmpty() && urlForFallackIcon.isEmpty()) {
+    if (!urlForThumbnail.isEmpty() && urlForFallbackIcon.isEmpty()) {
         return urlForThumbnail;
     }
 
-    const QStringList listImages{urlForThumbnail, urlForFallackIcon};
+    const QStringList listImages{urlForThumbnail, urlForFallbackIcon};
     return listImages.join(QLatin1Char(';'));
 }
 

+ 12 - 0
src/libsync/theme.cpp

@@ -899,4 +899,16 @@ QColor Theme::errorBoxBorderColor() const
     return QColor{"black"};
 }
 
+QPalette Theme::systemPalette()
+{
+    if(!_guiAppInstance) {
+        const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance());
+        if(ptr) {
+            _guiAppInstance.reset(ptr);
+            connect(ptr, &QGuiApplication::paletteChanged, this, &Theme::systemPaletteChanged);
+        }
+    }
+    return QGuiApplication::palette();
+}
+
 } // end namespace client

+ 8 - 1
src/libsync/theme.h

@@ -17,6 +17,8 @@
 
 #include <QIcon>
 #include <QObject>
+#include <QPalette>
+#include <QGuiApplication>
 #include "syncresult.h"
 
 class QString;
@@ -24,7 +26,6 @@ class QObject;
 class QPixmap;
 class QColor;
 class QPaintDevice;
-class QPalette;
 
 namespace OCC {
 
@@ -66,6 +67,8 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject
     Q_PROPERTY(QColor errorBoxTextColor READ errorBoxTextColor CONSTANT)
     Q_PROPERTY(QColor errorBoxBackgroundColor READ errorBoxBackgroundColor CONSTANT)
     Q_PROPERTY(QColor errorBoxBorderColor READ errorBoxBorderColor CONSTANT)
+
+    Q_PROPERTY(QPalette systemPalette READ systemPalette NOTIFY systemPaletteChanged)
 public:
     enum CustomMediaType {
         oCSetupTop, // ownCloud connect page
@@ -590,6 +593,8 @@ public:
 
     static constexpr const char *themePrefix = ":/client/theme/";
 
+    QPalette systemPalette();
+
 protected:
 #ifndef TOKEN_AUTH_ONLY
     QIcon themeIcon(const QString &name, bool sysTray = false) const;
@@ -606,6 +611,7 @@ protected:
 
 signals:
     void systrayUseMonoIconsChanged(bool);
+    void systemPaletteChanged(const QPalette &palette);
 
 private:
     Theme(Theme const &);
@@ -613,6 +619,7 @@ private:
 
     static Theme *_instance;
     bool _mono = false;
+    QScopedPointer<QGuiApplication> _guiAppInstance;
 #ifndef TOKEN_AUTH_ONLY
     mutable QHash<QString, QIcon> _iconCache;
 #endif

+ 15 - 0
theme.qrc.in

@@ -92,6 +92,7 @@
         <file>theme/colored/folder@2x.png</file>
         <file>theme/black/control-next.svg</file>
         <file>theme/black/control-prev.svg</file>
+        <file>theme/black/settings.svg</file>
         <file>theme/black/state-error.svg</file>
         <file>theme/black/state-error-16.png</file>
         <file>theme/black/state-offline.svg</file>
@@ -112,10 +113,21 @@
         <file>theme/black/state-warning-64.png</file>
         <file>theme/black/state-warning-128.png</file>
         <file>theme/black/state-warning-256.png</file>
+        <file>theme/white/bell.svg</file>
+        <file>theme/white/calendar.svg</file>
+        <file>theme/white/change.svg</file>
+        <file>theme/white/close.svg</file>
+        <file>theme/white/confirm.svg</file>
         <file>theme/white/control-next.svg</file>
         <file>theme/white/control-prev.svg</file>
+        <file>theme/white/comment.svg</file>
+        <file>theme/white/deck.svg</file>
+        <file>theme/white/edit.svg</file>
+        <file>theme/white/email.svg</file>
+        <file>theme/white/settings.svg</file>
         <file>theme/white/state-error.svg</file>
         <file>theme/white/state-error-16.png</file>
+        <file>theme/white/state-info.svg</file>
         <file>theme/white/state-offline.svg</file>
         <file>theme/white/state-offline-16.png</file>
         <file>theme/white/state-offline-32.png</file>
@@ -136,6 +148,7 @@
         <file>theme/white/state-warning-256.png</file>
         <file>theme/white/wizard-files.png</file>
         <file>theme/white/wizard-files@2x.png</file>
+        <file>theme/white/wizard-groupware.svg</file>
         <file>theme/white/wizard-groupware.png</file>
         <file>theme/white/wizard-groupware@2x.png</file>
         <file>theme/white/wizard-nextcloud.png</file>
@@ -183,6 +196,8 @@
         <file>theme/black/deck.svg</file>
         <file>theme/black/state-info.svg</file>
         <file>theme/close.svg</file>
+        <file>theme/black/close.svg</file>
+        <file>theme/white/close.svg</file>
         <file>theme/files.svg</file>
         <file>theme/public.svg</file>
         <file>theme/settings.svg</file>

+ 10 - 9
theme/Style/Style.qml

@@ -8,15 +8,18 @@ QtObject {
     readonly property int pixelSize: fontMetrics.font.pixelSize
 
     // Colors
-    property color ncBlue:      Theme.wizardHeaderBackgroundColor
-    property color ncTextColor: Theme.wizardHeaderTitleColor
-    property color lightHover:  "#f7f7f7"
-    property color menuBorder:  "#bdbdbd"
+    readonly property color ncBlue:      Theme.wizardHeaderBackgroundColor
+    readonly property color ncTextColor: Theme.systemPalette.windowText
+    readonly property color ncSecondaryTextColor: "#808080"
+    readonly property color ncHeaderTextColor: "white"
+    readonly property color lightHover:  Theme.systemPalette.highlight
+    readonly property color menuBorder:  Systray.darkMode ? Qt.lighter(backgroundColor, 3) : Qt.darker(backgroundColor, 1.5)
+    readonly property color backgroundColor: Theme.systemPalette.base
 
     // ErrorBox colors
-    property color errorBoxTextColor:       Theme.errorBoxTextColor
-    property color errorBoxBackgroundColor: Theme.errorBoxBackgroundColor
-    property color errorBoxBorderColor:     Theme.errorBoxBorderColor
+    readonly property color errorBoxTextColor:       Theme.errorBoxTextColor
+    readonly property color errorBoxBackgroundColor: Theme.errorBoxBackgroundColor
+    readonly property color errorBoxBorderColor:     Theme.errorBoxBorderColor
 
     // Fonts
     // We are using pixel size because this is cross platform comparable, point size isn't
@@ -79,8 +82,6 @@ QtObject {
     readonly property int unifiedSearchResulIconLeftMargin: 12
     readonly property int unifiedSearchResulTitleFontSize: topLinePixelSize
     readonly property int unifiedSearchResulSublineFontSize: subLinePixelSize
-    readonly property string unifiedSearchResulTitleColor: "black"
-    readonly property string unifiedSearchResulSublineColor: "grey"
 
     readonly property var fontMetrics: FontMetrics {}
 

+ 1 - 0
theme/black/change.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" version="1.1" height="16"><path d="m8 2c-2.142 0-4.125 1.145-5.196 3l1.948 1.125c0.671-1.162 1.906-1.875 3.2476-1.875 1.1906 0 2.297 0.56157 3 1.5l-1.5 1.5h4.5v-4.5l-1.406 1.406c-1.129-1.348-2.802-2.1563-4.594-2.1563z"/><path d="m2 8.75v4.5l1.408-1.41c1.116 1.334 2.817 2.145 4.592 2.16 2.16 0.01827 4.116-1.132 5.196-3.002l-1.948-1.125c-0.677 1.171-1.9005 1.886-3.248 1.875-1.18-0.01-2.3047-0.572-3-1.5l1.5-1.5z"/></svg>

+ 1 - 0
theme/black/close.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1"><path d="m12.95 11.536l-1.414 1.414-3.536-3.536-3.535 3.536-1.415-1.414 3.536-3.536-3.536-3.536 1.415-1.414 3.535 3.536 3.516-3.555 1.434 1.434-3.536 3.535z"/></svg>

+ 1 - 0
theme/black/confirm.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 16 16" width="16" version="1.1" height="16"><path d="m8.5 0.5c-0.8974 0-1.3404 1.0909-0.6973 1.7168l4.7837 4.7832h-11.573c-1.3523-0.019125-1.3523 2.0191 0 2h11.572l-4.7832 4.7832c-0.98163 0.94251 0.47155 2.3957 1.4141 1.4141l6.4911-6.49c0.387-0.3878 0.391-1.0228 0-1.414l-6.4906-6.4903c-0.1883-0.1935-0.4468-0.30268-0.7168-0.3027z"/></svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
theme/black/settings.svg


+ 2 - 0
theme/white/activity.svg

@@ -0,0 +1,2 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.1"><path fill="#fff" d="m32 2-20 36h22l-2 24 20-36h-22z"/>
+</svg>

+ 39 - 0
theme/white/bell.svg

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   height="16"
+   width="16"
+   version="1.1"
+   viewBox="0 0 16 16"
+   id="svg4"
+   sodipodi:docname="bell.svg"
+   inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     id="namedview6"
+     pagecolor="#ffffff"
+     bordercolor="#ffffff"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="39.375"
+     inkscape:cx="8"
+     inkscape:cy="8"
+     inkscape:window-width="1471"
+     inkscape:window-height="826"
+     inkscape:window-x="170"
+     inkscape:window-y="133"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg4" />
+  <path
+     d="m8 2c-0.5523 0-1 0.4477-1 1 0 0.0472 0.021 0.0873 0.0273 0.1328-1.7366 0.4362-3.0273 1.9953-3.0273 3.8672v2l-1 1v1h10v-1l-1-1v-2c0-1.8719-1.291-3.431-3.0273-3.8672 0.0063-0.0455 0.0273-0.0856 0.0273-0.1328 0-0.5523-0.4477-1-1-1zm-2 10c0 1.1046 0.8954 2 2 2s2-0.8954 2-2z"
+     fill="#ffffff"
+     id="path2"
+     style="fill:#ffffff;fill-opacity:1" />
+</svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
theme/white/calendar.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
theme/white/change.svg


+ 1 - 0
theme/white/close.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1"><path fill="#fff" d="m12.95 11.536l-1.414 1.414-3.536-3.536-3.535 3.536-1.415-1.414 3.536-3.536-3.536-3.536 1.415-1.414 3.535 3.536 3.516-3.555 1.434 1.434-3.536 3.535z"/></svg>

+ 1 - 0
theme/white/comment.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#fff"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18zM20 4v13.17L18.83 16H4V4h16zM6 12h12v2H6zm0-3h12v2H6zm0-3h12v2H6z"/></svg>

+ 1 - 0
theme/white/confirm.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 16 16" width="16" version="1.1" height="16"><path fill="#fff" d="m8.5 0.5c-0.8974 0-1.3404 1.0909-0.6973 1.7168l4.7837 4.7832h-11.573c-1.3523-0.019125-1.3523 2.0191 0 2h11.572l-4.7832 4.7832c-0.98163 0.94251 0.47155 2.3957 1.4141 1.4141l6.4911-6.49c0.387-0.3878 0.391-1.0228 0-1.414l-6.4906-6.4903c-0.1883-0.1935-0.4468-0.30268-0.7168-0.3027z"/></svg>

+ 8 - 0
theme/white/deck.svg

@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16">
+    <g fill="#fff">
+        <rect ry="1" height="8" width="14" y="7" x="1"/>
+        <rect ry=".5" height="1" width="12" y="5" x="2"/>
+        <rect ry=".5" height="1" width="10" y="3" x="3"/>
+        <rect ry=".5" height="1" width="8" y="1" x="4"/>
+    </g>
+</svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 43 - 0
theme/white/edit.svg


+ 1 - 0
theme/white/email.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 24 24" width="16px" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
theme/white/settings.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
theme/white/state-info.svg


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.