--- /dev/null
+/*
+ * Copyright (C) 2024 by Claudio Cambra <claudio.cambra@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import "../"
+import "../filedetails/"
+
+import Style
+import com.nextcloud.desktopclient
+
+Button {
+ id: root
+
+ readonly property alias userLineInstantiator: userLineInstantiator
+ readonly property alias accountMenu: accountMenu
+
+ display: AbstractButton.IconOnly
+ flat: true
+
+ Accessible.role: Accessible.ButtonMenu
+ Accessible.name: qsTr("Current account")
+ Accessible.onPressAction: root.clicked()
+
+ // We call open() instead of popup() because we want to position it
+ // exactly below the dropdown button, not the mouse
+ onClicked: {
+ syncPauseButton.text = Systray.syncIsPaused ? qsTr("Resume sync for all") : qsTr("Pause sync for all")
+ if (accountMenu.visible) {
+ accountMenu.close()
+ } else {
+ accountMenu.open()
+ }
+ }
+
+ Menu {
+ id: accountMenu
+
+ // x coordinate grows towards the right
+ // y coordinate grows towards the bottom
+ x: (root.x + 2)
+ y: (root.y + Style.trayWindowHeaderHeight + 2)
+
+ width: (Style.rootWidth - 2)
+ height: Math.min(implicitHeight, maxMenuHeight)
+ closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
+
+ onClosed: {
+ // HACK: reload account Instantiator immediately by restting it - could be done better I guess
+ // see also onVisibleChanged above
+ userLineInstantiator.active = false;
+ userLineInstantiator.active = true;
+ }
+
+ Instantiator {
+ id: userLineInstantiator
+ model: UserModel
+ delegate: MenuItem {
+ implicitHeight: instantiatedUserLine.height
+ UserLine {
+ id: instantiatedUserLine
+ width: parent.width
+ onShowUserStatusSelector: {
+ userStatusDrawer.openUserStatusDrawer(model.index);
+ accountMenu.close();
+ }
+ onClicked: UserModel.currentUserId = model.index;
+ }
+ }
+ onObjectAdded: accountMenu.insertItem(index, object)
+ onObjectRemoved: accountMenu.removeItem(object)
+ }
+
+ MenuItem {
+ id: addAccountButton
+ hoverEnabled: true
+ visible: Systray.enableAddAccount
+
+ icon.source: "image://svgimage-custom-color/add.svg/" + palette.windowText
+ icon.width: Style.accountAvatarSize
+ text: qsTr("Add account")
+ onClicked: UserModel.addAccount()
+
+ Accessible.role: Accessible.MenuItem
+ Accessible.name: qsTr("Add new account")
+ Accessible.onPressAction: addAccountButton.clicked()
+ }
+
+ Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ implicitHeight: 1
+ color: palette.dark
+ }
+
+ MenuItem {
+ id: syncPauseButton
+ font.pixelSize: Style.topLinePixelSize
+ hoverEnabled: true
+ onClicked: Systray.syncIsPaused = !Systray.syncIsPaused
+ Accessible.role: Accessible.MenuItem
+ Accessible.name: Systray.syncIsPaused ? qsTr("Resume sync for all") : qsTr("Pause sync for all")
+ Accessible.onPressAction: syncPauseButton.clicked()
+ }
+
+ MenuItem {
+ id: settingsButton
+ text: qsTr("Settings")
+ font.pixelSize: Style.topLinePixelSize
+ hoverEnabled: true
+ onClicked: Systray.openSettings()
+ Accessible.role: Accessible.MenuItem
+ Accessible.name: text
+ Accessible.onPressAction: settingsButton.clicked()
+ }
+
+ MenuItem {
+ id: exitButton
+ text: qsTr("Exit");
+ font.pixelSize: Style.topLinePixelSize
+ hoverEnabled: true
+ onClicked: Systray.shutdown()
+ Accessible.role: Accessible.MenuItem
+ Accessible.name: text
+ Accessible.onPressAction: exitButton.clicked()
+ }
+ }
+
+ RowLayout {
+ id: accountControlRowLayout
+
+ height: Style.trayWindowHeaderHeight
+ width: Style.rootWidth
+ spacing: 0
+
+ Image {
+ id: currentAccountAvatar
+
+ Layout.leftMargin: Style.trayHorizontalMargin
+ verticalAlignment: Qt.AlignCenter
+ cache: false
+ source: (UserModel.currentUser && UserModel.currentUser.avatar !== "") ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite"
+ Layout.preferredHeight: Style.accountAvatarSize
+ Layout.preferredWidth: Style.accountAvatarSize
+
+ Accessible.role: Accessible.Graphic
+ Accessible.name: qsTr("Current account avatar")
+
+ Rectangle {
+ id: currentAccountStatusIndicatorBackground
+ visible: UserModel.currentUser && UserModel.currentUser.isConnected
+ && UserModel.currentUser.serverHasUserStatus
+ width: Style.accountAvatarStateIndicatorSize + + Style.trayFolderStatusIndicatorSizeOffset
+ height: width
+ color: trayWindowHeaderBackground.color
+ anchors.bottom: currentAccountAvatar.bottom
+ anchors.right: currentAccountAvatar.right
+ radius: width * Style.trayFolderStatusIndicatorRadiusFactor
+ }
+
+ Image {
+ id: currentAccountStatusIndicator
+ visible: UserModel.currentUser && UserModel.currentUser.isConnected
+ && UserModel.currentUser.serverHasUserStatus
+ source: UserModel.currentUser ? UserModel.currentUser.statusIcon : ""
+ cache: false
+ x: currentAccountStatusIndicatorBackground.x + 1
+ y: currentAccountStatusIndicatorBackground.y + 1
+ sourceSize.width: Style.accountAvatarStateIndicatorSize
+ sourceSize.height: Style.accountAvatarStateIndicatorSize
+
+ Accessible.role: Accessible.Indicator
+ Accessible.name: UserModel.desktopNotificationsAllowed ? qsTr("Current account status is online") : qsTr("Current account status is do not disturb")
+ }
+ }
+
+ Column {
+ id: accountLabels
+ spacing: 0
+ Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
+ Layout.leftMargin: Style.userStatusSpacing
+ Layout.fillWidth: true
+ Layout.maximumWidth: parent.width
+
+ EnforcedPlainTextLabel {
+ id: currentAccountUser
+ Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
+ width: Style.currentAccountLabelWidth
+ text: UserModel.currentUser ? UserModel.currentUser.name : ""
+ elide: Text.ElideRight
+
+ font.pixelSize: Style.topLinePixelSize
+ font.bold: true
+ }
+
+ EnforcedPlainTextLabel {
+ id: currentAccountServer
+ Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
+ width: Style.currentAccountLabelWidth
+ text: UserModel.currentUser ? UserModel.currentUser.server : ""
+ elide: Text.ElideRight
+ visible: UserModel.numUsers() > 1
+ }
+
+ RowLayout {
+ id: currentUserStatus
+ visible: UserModel.currentUser && UserModel.currentUser.isConnected &&
+ UserModel.currentUser.serverHasUserStatus
+ spacing: Style.accountLabelsSpacing
+ width: parent.width
+
+ EnforcedPlainTextLabel {
+ id: emoji
+ visible: UserModel.currentUser && UserModel.currentUser.statusEmoji !== ""
+ width: Style.userStatusEmojiSize
+ text: UserModel.currentUser ? UserModel.currentUser.statusEmoji : ""
+ }
+ EnforcedPlainTextLabel {
+ id: message
+ Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
+ Layout.fillWidth: true
+ visible: UserModel.currentUser && UserModel.currentUser.statusMessage !== ""
+ width: Style.currentAccountLabelWidth
+ text: UserModel.currentUser && UserModel.currentUser.statusMessage !== ""
+ ? UserModel.currentUser.statusMessage
+ : UserModel.currentUser ? UserModel.currentUser.server : ""
+ elide: Text.ElideRight
+ font.pixelSize: Style.subLinePixelSize
+ }
+ }
+ }
+
+ Loader {
+ active: root.indicator === null
+ sourceComponent: Image {
+ Layout.alignment: Qt.AlignRight
+ verticalAlignment: Qt.AlignCenter
+ horizontalAlignment: Qt.AlignRight
+ Layout.leftMargin: Style.accountDropDownCaretMargin
+ source: "image://svgimage-custom-color/caret-down.svg/" + palette.windowText
+ sourceSize.width: Style.accountDropDownCaretSize
+ sourceSize.height: Style.accountDropDownCaretSize
+ Accessible.role: Accessible.PopupMenu
+ Accessible.name: qsTr("Account switcher and settings menu")
+ }
+ }
+ }
+}
\r
onVisibleChanged: {\r
// HACK: reload account Instantiator immediately by restting it - could be done better I guess\r
- // see also id:accountMenu below\r
- userLineInstantiator.active = false;\r
- userLineInstantiator.active = true;\r
+ // see also id:currentAccountHeaderButton.accountMenu below\r
+ currentAccountHeaderButton.userLineInstantiator.active = false;\r
+ currentAccountHeaderButton.userLineInstantiator.active = true;\r
syncStatus.model.load();\r
}\r
\r
Connections {\r
target: UserModel\r
function onCurrentUserChanged() {\r
- accountMenu.close();\r
+ currentAccountHeaderButton.accountMenu.close();\r
syncStatus.model.load();\r
}\r
}\r
fileDetailsDrawer.close();\r
\r
if(Systray.isOpen) {\r
- accountMenu.close();\r
+ currentAccountHeaderButton.accountMenu.close();\r
appsMenu.close();\r
openLocalFolderButton.closeMenu()\r
}\r
spacing: 0\r
anchors.fill: parent\r
\r
- Button {\r
- id: currentAccountButton\r
-\r
+ CurrentAccountHeaderButton {\r
+ id: currentAccountHeaderButton\r
Layout.preferredWidth: Style.currentAccountButtonWidth\r
Layout.preferredHeight: Style.trayWindowHeaderHeight\r
- display: AbstractButton.IconOnly\r
- flat: true\r
-\r
- Accessible.role: Accessible.ButtonMenu\r
- Accessible.name: qsTr("Current account")\r
- Accessible.onPressAction: currentAccountButton.clicked()\r
-\r
- // We call open() instead of popup() because we want to position it\r
- // exactly below the dropdown button, not the mouse\r
- onClicked: {\r
- syncPauseButton.text = Systray.syncIsPaused ? qsTr("Resume sync for all") : qsTr("Pause sync for all")\r
- if (accountMenu.visible) {\r
- accountMenu.close()\r
- } else {\r
- accountMenu.open()\r
- }\r
- }\r
-\r
- Menu {\r
- id: accountMenu\r
-\r
- // x coordinate grows towards the right\r
- // y coordinate grows towards the bottom\r
- x: (currentAccountButton.x + 2)\r
- y: (currentAccountButton.y + Style.trayWindowHeaderHeight + 2)\r
-\r
- width: (Style.currentAccountButtonWidth - 2)\r
- height: Math.min(implicitHeight, maxMenuHeight)\r
- closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape\r
-\r
- onClosed: {\r
- // HACK: reload account Instantiator immediately by restting it - could be done better I guess\r
- // see also onVisibleChanged above\r
- userLineInstantiator.active = false;\r
- userLineInstantiator.active = true;\r
- }\r
-\r
- Instantiator {\r
- id: userLineInstantiator\r
- model: UserModel\r
- delegate: MenuItem {\r
- implicitHeight: instantiatedUserLine.height\r
- UserLine {\r
- id: instantiatedUserLine\r
- width: parent.width\r
- onShowUserStatusSelector: {\r
- userStatusDrawer.openUserStatusDrawer(model.index);\r
- accountMenu.close();\r
- }\r
- onClicked: UserModel.currentUserId = model.index;\r
- }\r
- }\r
- onObjectAdded: accountMenu.insertItem(index, object)\r
- onObjectRemoved: accountMenu.removeItem(object)\r
- }\r
-\r
- MenuItem {\r
- id: addAccountButton\r
- hoverEnabled: true\r
- visible: Systray.enableAddAccount\r
-\r
- icon.source: "image://svgimage-custom-color/add.svg/" + palette.windowText\r
- icon.width: Style.accountAvatarSize\r
- text: qsTr("Add account") \r
- onClicked: UserModel.addAccount()\r
-\r
- Accessible.role: Accessible.MenuItem\r
- Accessible.name: qsTr("Add new account")\r
- Accessible.onPressAction: addAccountButton.clicked()\r
- }\r
-\r
- Rectangle {\r
- anchors.left: parent.left\r
- anchors.right: parent.right\r
- implicitHeight: 1\r
- color: palette.dark\r
- }\r
-\r
- MenuItem {\r
- id: syncPauseButton\r
- font.pixelSize: Style.topLinePixelSize\r
- hoverEnabled: true\r
- onClicked: Systray.syncIsPaused = !Systray.syncIsPaused\r
- Accessible.role: Accessible.MenuItem\r
- Accessible.name: Systray.syncIsPaused ? qsTr("Resume sync for all") : qsTr("Pause sync for all")\r
- Accessible.onPressAction: syncPauseButton.clicked()\r
- }\r
-\r
- MenuItem {\r
- id: settingsButton\r
- text: qsTr("Settings")\r
- font.pixelSize: Style.topLinePixelSize\r
- hoverEnabled: true\r
- onClicked: Systray.openSettings()\r
- Accessible.role: Accessible.MenuItem\r
- Accessible.name: text\r
- Accessible.onPressAction: settingsButton.clicked()\r
- }\r
-\r
- MenuItem {\r
- id: exitButton\r
- text: qsTr("Exit");\r
- font.pixelSize: Style.topLinePixelSize\r
- hoverEnabled: true\r
- onClicked: Systray.shutdown()\r
- Accessible.role: Accessible.MenuItem\r
- Accessible.name: text\r
- Accessible.onPressAction: exitButton.clicked() \r
- }\r
- }\r
-\r
- RowLayout {\r
- id: accountControlRowLayout\r
-\r
- height: Style.trayWindowHeaderHeight\r
- width: Style.currentAccountButtonWidth\r
- spacing: 0\r
-\r
- Image {\r
- id: currentAccountAvatar\r
-\r
- Layout.leftMargin: Style.trayHorizontalMargin\r
- verticalAlignment: Qt.AlignCenter\r
- cache: false\r
- source: (UserModel.currentUser && UserModel.currentUser.avatar !== "") ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite"\r
- Layout.preferredHeight: Style.accountAvatarSize\r
- Layout.preferredWidth: Style.accountAvatarSize\r
-\r
- Accessible.role: Accessible.Graphic\r
- Accessible.name: qsTr("Current account avatar")\r
-\r
- Rectangle {\r
- id: currentAccountStatusIndicatorBackground\r
- visible: UserModel.currentUser && UserModel.currentUser.isConnected\r
- && UserModel.currentUser.serverHasUserStatus\r
- width: Style.accountAvatarStateIndicatorSize + + Style.trayFolderStatusIndicatorSizeOffset\r
- height: width\r
- color: trayWindowHeaderBackground.color\r
- anchors.bottom: currentAccountAvatar.bottom\r
- anchors.right: currentAccountAvatar.right\r
- radius: width * Style.trayFolderStatusIndicatorRadiusFactor\r
- }\r
-\r
- Image {\r
- id: currentAccountStatusIndicator\r
- visible: UserModel.currentUser && UserModel.currentUser.isConnected\r
- && UserModel.currentUser.serverHasUserStatus\r
- source: UserModel.currentUser ? UserModel.currentUser.statusIcon : ""\r
- cache: false\r
- x: currentAccountStatusIndicatorBackground.x + 1\r
- y: currentAccountStatusIndicatorBackground.y + 1\r
- sourceSize.width: Style.accountAvatarStateIndicatorSize\r
- sourceSize.height: Style.accountAvatarStateIndicatorSize\r
-\r
- Accessible.role: Accessible.Indicator\r
- Accessible.name: UserModel.desktopNotificationsAllowed ? qsTr("Current account status is online") : qsTr("Current account status is do not disturb")\r
- }\r
- }\r
-\r
- Column {\r
- id: accountLabels\r
- spacing: 0\r
- Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter\r
- Layout.leftMargin: Style.userStatusSpacing\r
- Layout.fillWidth: true\r
- Layout.maximumWidth: parent.width\r
-\r
- EnforcedPlainTextLabel {\r
- id: currentAccountUser\r
- Layout.alignment: Qt.AlignLeft | Qt.AlignBottom\r
- width: Style.currentAccountLabelWidth\r
- text: UserModel.currentUser ? UserModel.currentUser.name : ""\r
- elide: Text.ElideRight\r
-\r
- font.pixelSize: Style.topLinePixelSize\r
- font.bold: true\r
- }\r
-\r
- EnforcedPlainTextLabel {\r
- id: currentAccountServer\r
- Layout.alignment: Qt.AlignLeft | Qt.AlignBottom\r
- width: Style.currentAccountLabelWidth\r
- text: UserModel.currentUser ? UserModel.currentUser.server : ""\r
- elide: Text.ElideRight\r
- visible: UserModel.numUsers() > 1\r
- }\r
-\r
- RowLayout {\r
- id: currentUserStatus\r
- visible: UserModel.currentUser && UserModel.currentUser.isConnected &&\r
- UserModel.currentUser.serverHasUserStatus\r
- spacing: Style.accountLabelsSpacing\r
- width: parent.width\r
-\r
- EnforcedPlainTextLabel {\r
- id: emoji\r
- visible: UserModel.currentUser && UserModel.currentUser.statusEmoji !== ""\r
- width: Style.userStatusEmojiSize\r
- text: UserModel.currentUser ? UserModel.currentUser.statusEmoji : ""\r
- }\r
- EnforcedPlainTextLabel {\r
- id: message\r
- Layout.alignment: Qt.AlignLeft | Qt.AlignBottom\r
- Layout.fillWidth: true\r
- visible: UserModel.currentUser && UserModel.currentUser.statusMessage !== ""\r
- width: Style.currentAccountLabelWidth\r
- text: UserModel.currentUser && UserModel.currentUser.statusMessage !== ""\r
- ? UserModel.currentUser.statusMessage\r
- : UserModel.currentUser ? UserModel.currentUser.server : ""\r
- elide: Text.ElideRight\r
- font.pixelSize: Style.subLinePixelSize\r
- }\r
- }\r
- }\r
-\r
- Loader {\r
- active: currentAccountButton.indicator === null\r
- sourceComponent: Image {\r
- Layout.alignment: Qt.AlignRight\r
- verticalAlignment: Qt.AlignCenter\r
- horizontalAlignment: Qt.AlignRight\r
- Layout.leftMargin: Style.accountDropDownCaretMargin\r
- source: "image://svgimage-custom-color/caret-down.svg/" + palette.windowText\r
- sourceSize.width: Style.accountDropDownCaretSize\r
- sourceSize.height: Style.accountDropDownCaretSize\r
- Accessible.role: Accessible.PopupMenu\r
- Accessible.name: qsTr("Account switcher and settings menu")\r
- }\r
- }\r
- }\r
}\r
\r
// Add space between items\r