diff options
author | Felix Weilbach <felix.weilbach@nextcloud.com> | 2021-03-22 17:08:42 +0300 |
---|---|---|
committer | Felix Weilbach <felix.weilbach@nextcloud.com> | 2021-03-22 17:08:42 +0300 |
commit | 910cd65ff1b1150f38a91e8043916c4a38d1eba7 (patch) | |
tree | 144b7bb1c7995946cc3795a5482812f16113b990 | |
parent | 4d921c8025f74e606b19597642547064f0a594bb (diff) |
Use unix encoding instead of dos in qml filesbugfix/main-dialog-respect-system-theme
Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
-rw-r--r-- | src/gui/tray/UserLine.qml | 470 | ||||
-rw-r--r-- | src/gui/tray/Window.qml | 1636 |
2 files changed, 1053 insertions, 1053 deletions
diff --git a/src/gui/tray/UserLine.qml b/src/gui/tray/UserLine.qml index 654aa079c..3f219d82e 100644 --- a/src/gui/tray/UserLine.qml +++ b/src/gui/tray/UserLine.qml @@ -1,235 +1,235 @@ -import QtQuick 2.9
-import QtQuick.Window 2.3
-import QtQuick.Controls 2.2
-import QtQuick.Layouts 1.2
-
-// Custom qml modules are in /theme (and included by resources.qrc)
-import Style 1.0
-import com.nextcloud.desktopclient 1.0
-
-MenuItem {
- id: userLine
- height: Style.trayWindowHeaderHeight
-
- Accessible.role: Accessible.MenuItem
- Accessible.name: qsTr("Account entry")
-
- RowLayout {
- id: userLineLayout
- spacing: 0
- width: Style.currentAccountButtonWidth
- height: parent.height
-
- Button {
- id: accountButton
- Layout.preferredWidth: (userLineLayout.width * (5/6))
- Layout.preferredHeight: (userLineLayout.height)
- display: AbstractButton.IconOnly
- hoverEnabled: true
- flat: true
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Switch to account") + " " + name
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- onContainsMouseChanged: {
- accountStateIndicatorBackground.color = (containsMouse ? "#f6f6f6" : "white")
- }
- onClicked: {
- if (!isCurrentUser) {
- UserModel.switchCurrentUser(id)
- } else {
- accountMenu.close()
- }
- }
- }
-
-
- background: Item {
- height: parent.height
- width: userLine.menu ? userLine.menu.width : 0
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- RowLayout {
- id: accountControlRowLayout
- height: accountButton.height
- width: accountButton.width
- spacing: 0
- Image {
- id: accountAvatar
- Layout.leftMargin: 4
- verticalAlignment: Qt.AlignCenter
- cache: false
- source: model.avatar != "" ? model.avatar : "image://avatars/fallbackBlack"
- Layout.preferredHeight: (userLineLayout.height -16)
- Layout.preferredWidth: (userLineLayout.height -16)
- Rectangle {
- id: accountStateIndicatorBackground
- width: accountStateIndicator.sourceSize.width + 2
- height: width
- anchors.bottom: accountAvatar.bottom
- anchors.right: accountAvatar.right
- color: "white"
- radius: width*0.5
- }
- Image {
- id: accountStateIndicator
- source: model.isConnected
- ? Style.stateOnlineImageSource
- : Style.stateOfflineImageSource
- cache: false
- x: accountStateIndicatorBackground.x + 1
- y: accountStateIndicatorBackground.y + 1
- sourceSize.width: Style.accountAvatarStateIndicatorSize
- sourceSize.height: Style.accountAvatarStateIndicatorSize
-
- Accessible.role: Accessible.Indicator
- Accessible.name: model.isConnected ? qsTr("Account connected") : qsTr("Account not connected")
- }
- }
-
- Column {
- id: accountLabels
- spacing: 4
- Layout.alignment: Qt.AlignLeft
- Layout.leftMargin: 6
- Label {
- id: accountUser
- width: 128
- text: name
- elide: Text.ElideRight
- color: "black"
- font.pixelSize: 12
- font.bold: true
- }
- Label {
- id: accountServer
- width: 128
- text: server
- elide: Text.ElideRight
- color: "black"
- font.pixelSize: 10
- }
- }
- }
- } // accountButton
-
- Button {
- id: userMoreButton
- Layout.preferredWidth: (userLineLayout.width * (1/6))
- Layout.preferredHeight: userLineLayout.height
- flat: true
-
- icon.source: "qrc:///client/theme/more.svg"
- icon.color: "transparent"
-
- Accessible.role: Accessible.ButtonMenu
- Accessible.name: qsTr("Account actions")
- Accessible.onPressAction: userMoreButtonMouseArea.clicked()
-
- MouseArea {
- id: userMoreButtonMouseArea
- anchors.fill: parent
- hoverEnabled: true
- onClicked: {
- if (userMoreButtonMenu.visible) {
- userMoreButtonMenu.close()
- } else {
- userMoreButtonMenu.popup()
- }
- }
- }
- background:
- Rectangle {
- color: userMoreButtonMouseArea.containsMouse ? "grey" : "transparent"
- opacity: 0.2
- height: userMoreButton.height - 2
- y: userMoreButton.y + 1
- }
-
- Menu {
- id: userMoreButtonMenu
- width: 120
- closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
-
- background: Rectangle {
- border.color: Style.menuBorder
- radius: 2
- }
-
- MenuItem {
- text: model.isConnected ? qsTr("Log out") : qsTr("Log in")
- font.pixelSize: Style.topLinePixelSize
- hoverEnabled: true
- onClicked: {
- model.isConnected ? UserModel.logout(index) : UserModel.login(index)
- accountMenu.close()
- }
-
- background: Item {
- height: parent.height
- width: parent.menu.width
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- Accessible.role: Accessible.Button
- Accessible.name: model.isConnected ? qsTr("Log out") : qsTr("Log in")
-
- onPressed: {
- if (model.isConnected) {
- UserModel.logout(index)
- } else {
- UserModel.login(index)
- }
- accountMenu.close()
- }
- }
-
- MenuItem {
- id: removeAccountButton
- text: qsTr("Remove account")
- font.pixelSize: Style.topLinePixelSize
- hoverEnabled: true
- onClicked: {
- UserModel.removeAccount(index)
- accountMenu.close()
- }
-
- background: Item {
- height: parent.height
- width: parent.menu.width
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- Accessible.role: Accessible.Button
- Accessible.name: text
- Accessible.onPressAction: removeAccountButton.clicked()
- }
- }
- }
- }
-
- Connections {
- target: UserModel
- onRefreshCurrentUserGui: {
- accountStateIndicator.source = model.isConnected
- ? Style.stateOnlineImageSource
- : Style.stateOfflineImageSource
- }
- }
-} // MenuItem userLine
+import QtQuick 2.9 +import QtQuick.Window 2.3 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.2 + +// Custom qml modules are in /theme (and included by resources.qrc) +import Style 1.0 +import com.nextcloud.desktopclient 1.0 + +MenuItem { + id: userLine + height: Style.trayWindowHeaderHeight + + Accessible.role: Accessible.MenuItem + Accessible.name: qsTr("Account entry") + + RowLayout { + id: userLineLayout + spacing: 0 + width: Style.currentAccountButtonWidth + height: parent.height + + Button { + id: accountButton + Layout.preferredWidth: (userLineLayout.width * (5/6)) + Layout.preferredHeight: (userLineLayout.height) + display: AbstractButton.IconOnly + hoverEnabled: true + flat: true + + Accessible.role: Accessible.Button + Accessible.name: qsTr("Switch to account") + " " + name + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: { + accountStateIndicatorBackground.color = (containsMouse ? "#f6f6f6" : "white") + } + onClicked: { + if (!isCurrentUser) { + UserModel.switchCurrentUser(id) + } else { + accountMenu.close() + } + } + } + + + background: Item { + height: parent.height + width: userLine.menu ? userLine.menu.width : 0 + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + RowLayout { + id: accountControlRowLayout + height: accountButton.height + width: accountButton.width + spacing: 0 + Image { + id: accountAvatar + Layout.leftMargin: 4 + verticalAlignment: Qt.AlignCenter + cache: false + source: model.avatar != "" ? model.avatar : "image://avatars/fallbackBlack" + Layout.preferredHeight: (userLineLayout.height -16) + Layout.preferredWidth: (userLineLayout.height -16) + Rectangle { + id: accountStateIndicatorBackground + width: accountStateIndicator.sourceSize.width + 2 + height: width + anchors.bottom: accountAvatar.bottom + anchors.right: accountAvatar.right + color: "white" + radius: width*0.5 + } + Image { + id: accountStateIndicator + source: model.isConnected + ? Style.stateOnlineImageSource + : Style.stateOfflineImageSource + cache: false + x: accountStateIndicatorBackground.x + 1 + y: accountStateIndicatorBackground.y + 1 + sourceSize.width: Style.accountAvatarStateIndicatorSize + sourceSize.height: Style.accountAvatarStateIndicatorSize + + Accessible.role: Accessible.Indicator + Accessible.name: model.isConnected ? qsTr("Account connected") : qsTr("Account not connected") + } + } + + Column { + id: accountLabels + spacing: 4 + Layout.alignment: Qt.AlignLeft + Layout.leftMargin: 6 + Label { + id: accountUser + width: 128 + text: name + elide: Text.ElideRight + color: "black" + font.pixelSize: 12 + font.bold: true + } + Label { + id: accountServer + width: 128 + text: server + elide: Text.ElideRight + color: "black" + font.pixelSize: 10 + } + } + } + } // accountButton + + Button { + id: userMoreButton + Layout.preferredWidth: (userLineLayout.width * (1/6)) + Layout.preferredHeight: userLineLayout.height + flat: true + + icon.source: "qrc:///client/theme/more.svg" + icon.color: "transparent" + + Accessible.role: Accessible.ButtonMenu + Accessible.name: qsTr("Account actions") + Accessible.onPressAction: userMoreButtonMouseArea.clicked() + + MouseArea { + id: userMoreButtonMouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: { + if (userMoreButtonMenu.visible) { + userMoreButtonMenu.close() + } else { + userMoreButtonMenu.popup() + } + } + } + background: + Rectangle { + color: userMoreButtonMouseArea.containsMouse ? "grey" : "transparent" + opacity: 0.2 + height: userMoreButton.height - 2 + y: userMoreButton.y + 1 + } + + Menu { + id: userMoreButtonMenu + width: 120 + closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape + + background: Rectangle { + border.color: Style.menuBorder + radius: 2 + } + + MenuItem { + text: model.isConnected ? qsTr("Log out") : qsTr("Log in") + font.pixelSize: Style.topLinePixelSize + hoverEnabled: true + onClicked: { + model.isConnected ? UserModel.logout(index) : UserModel.login(index) + accountMenu.close() + } + + background: Item { + height: parent.height + width: parent.menu.width + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + Accessible.role: Accessible.Button + Accessible.name: model.isConnected ? qsTr("Log out") : qsTr("Log in") + + onPressed: { + if (model.isConnected) { + UserModel.logout(index) + } else { + UserModel.login(index) + } + accountMenu.close() + } + } + + MenuItem { + id: removeAccountButton + text: qsTr("Remove account") + font.pixelSize: Style.topLinePixelSize + hoverEnabled: true + onClicked: { + UserModel.removeAccount(index) + accountMenu.close() + } + + background: Item { + height: parent.height + width: parent.menu.width + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + Accessible.role: Accessible.Button + Accessible.name: text + Accessible.onPressAction: removeAccountButton.clicked() + } + } + } + } + + Connections { + target: UserModel + onRefreshCurrentUserGui: { + accountStateIndicator.source = model.isConnected + ? Style.stateOnlineImageSource + : Style.stateOfflineImageSource + } + } +} // MenuItem userLine diff --git a/src/gui/tray/Window.qml b/src/gui/tray/Window.qml index f46bc6100..f90570fae 100644 --- a/src/gui/tray/Window.qml +++ b/src/gui/tray/Window.qml @@ -1,818 +1,818 @@ -import QtQml 2.1
-import QtQml.Models 2.1
-import QtQuick 2.9
-import QtQuick.Window 2.3
-import QtQuick.Controls 2.3
-import QtQuick.Layouts 1.2
-import QtGraphicalEffects 1.0
-
-// Custom qml modules are in /theme (and included by resources.qrc)
-import Style 1.0
-
-import com.nextcloud.desktopclient 1.0
-
-Window {
- id: trayWindow
-
- width: Style.trayWindowWidth
- height: Style.trayWindowHeight
- color: "transparent"
- flags: Qt.Dialog | Qt.FramelessWindowHint
-
- readonly property int maxMenuHeight: Style.trayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth
-
- Accessible.role: Accessible.Application
- Accessible.name: qsTr("Nextcloud desktop main dialog")
-
- Component.onCompleted: Systray.forceWindowInit(trayWindow)
-
- // Close tray window when focus is lost (e.g. click somewhere else on the screen)
- onActiveChanged: {
- if(!active) {
- trayWindow.hide();
- Systray.setClosed();
- }
- }
-
- onVisibleChanged: {
- currentAccountStateIndicator.source = ""
- currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
- ? Style.stateOnlineImageSource
- : Style.stateOfflineImageSource
-
- // HACK: reload account Instantiator immediately by restting it - could be done better I guess
- // see also id:accountMenu below
- userLineInstantiator.active = false;
- userLineInstantiator.active = true;
- }
-
- Connections {
- target: UserModel
- onRefreshCurrentUserGui: {
- currentAccountStateIndicator.source = ""
- currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
- ? Style.stateOnlineImageSource
- : Style.stateOfflineImageSource
- }
- onNewUserSelected: {
- accountMenu.close();
- }
- }
-
- Connections {
- target: Systray
- onShowWindow: {
- accountMenu.close();
- appsMenu.close();
-
- Systray.positionWindow(trayWindow);
-
- trayWindow.show();
- trayWindow.raise();
- trayWindow.requestActivate();
-
- Systray.setOpened();
- UserModel.fetchCurrentActivityModel();
- }
- onHideWindow: {
- trayWindow.hide();
- Systray.setClosed();
- }
- }
-
- OpacityMask {
- anchors.fill: parent
- source: ShaderEffectSource {
- sourceItem: trayWindowBackground
- hideSource: true
- }
- maskSource: Rectangle {
- width: trayWindowBackground.width
- height: trayWindowBackground.height
- radius: trayWindowBackground.radius
- }
- }
-
- Rectangle {
- id: trayWindowBackground
-
- anchors.fill: parent
- radius: Style.trayWindowRadius
- border.width: Style.trayWindowBorderWidth
- border.color: Style.menuBorder
-
- Accessible.role: Accessible.Grouping
- Accessible.name: qsTr("Nextcloud desktop main dialog")
-
- Rectangle {
- id: trayWindowHeaderBackground
-
- anchors.left: trayWindowBackground.left
- anchors.right: trayWindowBackground.right
- anchors.top: trayWindowBackground.top
- height: Style.trayWindowHeaderHeight
- color: Style.ncBlue
-
- RowLayout {
- id: trayWindowHeaderLayout
-
- spacing: 0
- anchors.fill: parent
-
- Button {
- id: currentAccountButton
-
- Layout.preferredWidth: Style.currentAccountButtonWidth
- Layout.preferredHeight: Style.trayWindowHeaderHeight
- display: AbstractButton.IconOnly
- flat: true
-
- Accessible.role: Accessible.ButtonMenu
- Accessible.name: qsTr("Current account")
- Accessible.onPressAction: currentAccountButton.clicked()
-
- MouseArea {
- id: accountBtnMouseArea
-
- anchors.fill: parent
- hoverEnabled: Style.hoverEffectsEnabled
-
- // 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: (currentAccountButton.x + 2)
- y: (currentAccountButton.y + Style.trayWindowHeaderHeight + 2)
-
- width: (Style.currentAccountButtonWidth - 2)
- height: Math.min(implicitHeight, maxMenuHeight)
- closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
-
- background: Rectangle {
- border.color: Style.menuBorder
- radius: Style.currentAccountButtonRadius
- }
-
- Accessible.role: PopupMenu
- Accessible.name: qsTr("Account switcher and settings menu")
-
- 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: UserLine {}
- onObjectAdded: accountMenu.insertItem(index, object)
- onObjectRemoved: accountMenu.removeItem(object)
- }
-
- MenuItem {
- id: addAccountButton
- height: Style.addAccountButtonHeight
- hoverEnabled: true
-
- background: Item {
- height: parent.height
- width: parent.menu.width
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- RowLayout {
- anchors.fill: parent
- spacing: 0
-
- Image {
- Layout.leftMargin: 12
- verticalAlignment: Qt.AlignCenter
- source: "qrc:///client/theme/black/add.svg"
- sourceSize.width: Style.headerButtonIconSize
- sourceSize.height: Style.headerButtonIconSize
- }
- Label {
- Layout.leftMargin: 14
- text: qsTr("Add account")
- color: "black"
- font.pixelSize: Style.topLinePixelSize
- }
- // Filler on the right
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
- }
- }
- onClicked: UserModel.addAccount()
-
- Accessible.role: Accessible.MenuItem
- Accessible.name: qsTr("Add new account")
- Accessible.onPressAction: addAccountButton.clicked()
- }
-
- MenuSeparator {
- contentItem: Rectangle {
- implicitHeight: 1
- color: Style.menuBorder
- }
- }
-
- MenuItem {
- id: syncPauseButton
- font.pixelSize: Style.topLinePixelSize
- hoverEnabled: true
- onClicked: Systray.pauseResumeSync()
-
- background: Item {
- height: parent.height
- width: parent.menu.width
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- 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()
-
- background: Item {
- height: parent.height
- width: parent.menu.width
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- 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()
-
- background: Item {
- height: parent.height
- width: parent.menu.width
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: parent.parent.hovered ? Style.lightHover : "transparent"
- }
- }
-
- Accessible.role: Accessible.MenuItem
- Accessible.name: text
- Accessible.onPressAction: exitButton.clicked()
- }
- }
- }
-
- background: Rectangle {
- color: accountBtnMouseArea.containsMouse ? "white" : "transparent"
- opacity: 0.2
- }
-
- RowLayout {
- id: accountControlRowLayout
-
- height: Style.trayWindowHeaderHeight
- width: Style.currentAccountButtonWidth
- spacing: 0
-
- Image {
- id: currentAccountAvatar
-
- Layout.leftMargin: 8
- verticalAlignment: Qt.AlignCenter
- cache: false
- source: 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 user avatar")
-
- Rectangle {
- id: currentAccountStateIndicatorBackground
- width: Style.accountAvatarStateIndicatorSize + 2
- height: width
- anchors.bottom: currentAccountAvatar.bottom
- anchors.right: currentAccountAvatar.right
- color: Style.ncBlue
- radius: width*0.5
- }
-
- Rectangle {
- width: Style.accountAvatarStateIndicatorSize + 2
- height: width
- anchors.bottom: currentAccountAvatar.bottom
- anchors.right: currentAccountAvatar.right
- color: accountBtnMouseArea.containsMouse ? "white" : "transparent"
- opacity: 0.2
- radius: width*0.5
- }
-
- Image {
- id: currentAccountStateIndicator
- source: UserModel.isUserConnected(UserModel.currentUserId)
- ? Style.stateOnlineImageSource
- : Style.stateOfflineImageSource
- cache: false
- x: currentAccountStateIndicatorBackground.x + 1
- y: currentAccountStateIndicatorBackground.y + 1
- sourceSize.width: Style.accountAvatarStateIndicatorSize
- sourceSize.height: Style.accountAvatarStateIndicatorSize
-
- Accessible.role: Accessible.Indicator
- Accessible.name: UserModel.isUserConnected(UserModel.currentUserId()) ? qsTr("Connected") : qsTr("Disconnected")
- }
- }
-
- Column {
- id: accountLabels
- spacing: 4
- Layout.alignment: Qt.AlignLeft
- Layout.leftMargin: 6
- Label {
- id: currentAccountUser
-
- width: Style.currentAccountLabelWidth
- text: UserModel.currentUser.name
- elide: Text.ElideRight
- color: Style.ncTextColor
- font.pixelSize: Style.topLinePixelSize
- font.bold: true
- }
- Label {
- id: currentAccountServer
- width: Style.currentAccountLabelWidth
- text: UserModel.currentUser.server
- elide: Text.ElideRight
- color: Style.ncTextColor
- font.pixelSize: Style.subLinePixelSize
- }
- }
-
- ColorOverlay {
- cached: true
- color: Style.ncTextColor
- width: source.width
- height: source.height
- source: Image {
- Layout.alignment: Qt.AlignRight
- verticalAlignment: Qt.AlignCenter
- Layout.margins: Style.accountDropDownCaretMargin
- source: "qrc:///client/theme/white/caret-down.svg"
- sourceSize.width: Style.accountDropDownCaretSize
- sourceSize.height: Style.accountDropDownCaretSize
- }
- }
- }
- }
-
- // Filler between account dropdown and header app buttons
- Item {
- id: trayWindowHeaderSpacer
- Layout.fillWidth: true
- }
-
- HeaderButton {
- id: openLocalFolderButton
-
- visible: UserModel.currentUser.hasLocalFolder
- icon.source: "qrc:///client/theme/white/folder.svg"
- onClicked: UserModel.openCurrentAccountLocalFolder()
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Open local folder of current account")
- Accessible.onPressAction: openLocalFolderButton.clicked()
- }
-
- HeaderButton {
- id: trayWindowTalkButton
-
- visible: UserModel.currentUser.serverHasTalk
- icon.source: "qrc:///client/theme/white/talk-app.svg"
- onClicked: UserModel.openCurrentAccountTalk()
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Open Nextcloud Talk in browser")
- Accessible.onPressAction: trayWindowTalkButton.clicked()
- }
-
- HeaderButton {
- id: trayWindowAppsButton
- icon.source: "qrc:///client/theme/white/more-apps.svg"
- onClicked: {
- if(appsMenu.count <= 0) {
- UserModel.openCurrentAccountServer()
- } else if (appsMenu.visible) {
- appsMenu.close()
- } else {
- appsMenu.open()
- }
- }
-
- Accessible.role: Accessible.ButtonMenu
- Accessible.name: qsTr("More apps")
- Accessible.onPressAction: trayWindowAppsButton.clicked()
-
- Menu {
- id: appsMenu
- y: (trayWindowAppsButton.y + trayWindowAppsButton.height + 2)
- readonly property Item listContentItem: contentItem.contentItem
- width: Math.min(listContentItem.childrenRect.width + 4, Style.trayWindowWidth / 2)
- height: Math.min(implicitHeight, maxMenuHeight)
- closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape
-
- background: Rectangle {
- border.color: Style.menuBorder
- radius: 2
- }
-
- Accessible.role: Accessible.PopupMenu
- Accessible.name: qsTr("Apps menu")
-
- Instantiator {
- id: appsMenuInstantiator
- model: UserAppsModel
- onObjectAdded: appsMenu.insertItem(index, object)
- onObjectRemoved: appsMenu.removeItem(object)
- delegate: MenuItem {
- id: appEntry
- text: appName
- font.pixelSize: Style.topLinePixelSize
- icon.source: appIconUrl
- width: contentItem.implicitWidth + leftPadding + rightPadding
- onTriggered: UserAppsModel.openAppUrl(appUrl)
- hoverEnabled: true
-
- background: Item {
- width: appsMenu.width
- height: parent.height
-
- Rectangle {
- anchors.fill: parent
- anchors.margins: 1
- color: appEntry.hovered ? Style.lightHover : "transparent"
- }
- }
-
- Accessible.role: Accessible.MenuItem
- Accessible.name: qsTr("Open %1 in browser").arg(appName)
- Accessible.onPressAction: appEntry.triggered()
- }
- }
- }
- }
- }
- } // Rectangle trayWindowHeaderBackground
-
- ListView {
- id: activityListView
- anchors.top: trayWindowHeaderBackground.bottom
- anchors.left: trayWindowBackground.left
- anchors.right: trayWindowBackground.right
- anchors.bottom: trayWindowBackground.bottom
- clip: true
- ScrollBar.vertical: ScrollBar {
- id: listViewScrollbar
- }
-
- readonly property int maxActionButtons: 2
-
- keyNavigationEnabled: true
-
- Accessible.role: Accessible.List
- Accessible.name: qsTr("Activity list")
-
- model: activityModel
-
- delegate: RowLayout {
- id: activityItem
-
- readonly property variant links: model.links
-
- readonly property int itemIndex: model.index
-
- width: parent.width
- height: Style.trayWindowHeaderHeight
- spacing: 0
-
- Accessible.role: Accessible.ListItem
- Accessible.name: path !== "" ? qsTr("Open %1 locally").arg(displayPath)
- : message
- Accessible.onPressAction: activityMouseArea.clicked()
-
- MouseArea {
- id: activityMouseArea
- enabled: (path !== "" || link !== "")
- anchors.left: activityItem.left
- anchors.right: activityActionsLayout.right
- height: parent.height
- anchors.margins: 2
- hoverEnabled: true
- onClicked: activityModel.triggerDefaultAction(model.index)
-
- Rectangle {
- anchors.fill: parent
- color: (parent.containsMouse ? Style.lightHover : "transparent")
- }
- }
-
- Image {
- id: activityIcon
- anchors.left: activityItem.left
- anchors.leftMargin: 8
- anchors.rightMargin: 8
- Layout.preferredWidth: shareButton.icon.width
- Layout.preferredHeight: shareButton.icon.height
- verticalAlignment: Qt.AlignCenter
- cache: true
- source: icon
- sourceSize.height: 64
- sourceSize.width: 64
- }
-
- Column {
- id: activityTextColumn
- anchors.left: activityIcon.right
- anchors.right: activityActionsLayout.left
- anchors.leftMargin: 8
- spacing: 4
- Layout.alignment: Qt.AlignLeft
- Text {
- id: activityTextTitle
- text: (type === "Activity" || type === "Notification") ? subject : message
- width: parent.width
- elide: Text.ElideRight
- font.pixelSize: Style.topLinePixelSize
- color: activityTextTitleColor
- }
-
- Text {
- id: activityTextInfo
- text: (type === "Sync") ? displayPath
- : (type === "File") ? subject
- : (type === "Notification") ? message
- : ""
- height: (text === "") ? 0 : activityTextTitle.height
- width: parent.width
- elide: Text.ElideRight
- font.pixelSize: Style.subLinePixelSize
- }
-
- Text {
- id: activityTextDateTime
- text: dateTime
- height: (text === "") ? 0 : activityTextTitle.height
- width: parent.width
- elide: Text.ElideRight
- font.pixelSize: Style.subLinePixelSize
- color: "#808080"
- }
-
- ToolTip {
- id: toolTip
- visible: activityMouseArea.containsMouse
- text: activityTextTitle.text + ((activityTextInfo.text !== "") ? "\n\n" + activityTextInfo.text : "")
- delay: 250
- timeout: 10000
- // Can be dropped on more recent Qt, but on 5.12 it doesn't wrap...
- contentItem: Text {
- text: toolTip.text
- font: toolTip.font
- wrapMode: Text.Wrap
- color: toolTip.palette.toolTipText
- }
- }
- }
- RowLayout {
- id: activityActionsLayout
- anchors.right: activityItem.right
- spacing: 0
- Layout.alignment: Qt.AlignRight
-
- function actionButtonIcon(actionIndex) {
- const verb = String(model.links[actionIndex].verb);
- if (verb === "WEB" && (model.objectType === "chat" || model.objectType === "call")) {
- return "qrc:///client/theme/reply.svg";
- } else if (verb === "DELETE") {
- return "qrc:///client/theme/close.svg";
- }
-
- return "qrc:///client/theme/confirm.svg";
- }
-
- Repeater {
- model: activityItem.links.length > activityListView.maxActionButtons ? 1 : activityItem.links.length
-
- ActivityActionButton {
- id: activityActionButton
-
- readonly property int actionIndex: model.index
- readonly property bool primary: model.index === 0 && String(activityItem.links[actionIndex].verb) !== "DELETE"
-
- height: activityItem.height
-
- text: !primary ? "" : activityItem.links[actionIndex].label
-
- imageSource: !primary ? activityActionsLayout.actionButtonIcon(actionIndex) : ""
-
- textColor: primary ? Style.ncBlue : "black"
- textColorHovered: Style.lightHover
-
- textBorderColor: Style.ncBlue
-
- textBgColor: "transparent"
- textBgColorHovered: Style.ncBlue
-
- tooltipText: activityItem.links[actionIndex].label
-
- Layout.minimumWidth: primary ? 80 : -1
- Layout.minimumHeight: parent.height
-
- Layout.preferredWidth: primary ? -1 : parent.height
-
- onClicked: activityModel.triggerAction(activityItem.itemIndex, actionIndex)
- }
-
- }
-
- Button {
- id: moreActionsButton
-
- Layout.preferredWidth: parent.height
- Layout.preferredHeight: parent.height
- Layout.alignment: Qt.AlignRight
-
- flat: true
- hoverEnabled: true
- visible: activityItem.links.length > activityListView.maxActionButtons
- display: AbstractButton.IconOnly
- icon.source: "qrc:///client/theme/more.svg"
- icon.color: "transparent"
- background: Rectangle {
- color: parent.hovered ? Style.lightHover : "transparent"
- }
- ToolTip.visible: hovered
- ToolTip.delay: 1000
- ToolTip.text: qsTr("Show more actions")
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Show more actions")
- Accessible.onPressAction: moreActionsButton.clicked()
-
- onClicked: moreActionsButtonContextMenu.popup();
-
- Connections {
- target: trayWindow
- onActiveChanged: {
- if (!trayWindow.active) {
- moreActionsButtonContextMenu.close();
- }
- }
- }
-
- Connections {
- target: activityListView
-
- onMovementStarted: {
- moreActionsButtonContextMenu.close();
- }
- }
-
- Container {
- id: moreActionsButtonContextMenuContainer
- visible: moreActionsButtonContextMenu.opened
-
- width: moreActionsButtonContextMenu.width
- height: moreActionsButtonContextMenu.height
- anchors.right: moreActionsButton.right
- anchors.top: moreActionsButton.top
-
- Menu {
- id: moreActionsButtonContextMenu
- anchors.centerIn: parent
-
- // transform model to contain indexed actions with primary action filtered out
- function actionListToContextMenuList(actionList) {
- // early out with non-altered data
- if (activityItem.links.length <= activityListView.maxActionButtons) {
- return actionList;
- }
-
- // add index to every action and filter 'primary' action out
- var reducedActionList = actionList.reduce(function(reduced, action, index) {
- if (!action.primary) {
- var actionWithIndex = { actionIndex: index, label: action.label };
- reduced.push(actionWithIndex);
- }
- return reduced;
- }, []);
-
-
- return reducedActionList;
- }
-
- Repeater {
- id: moreActionsButtonContextMenuRepeater
-
- model: moreActionsButtonContextMenu.actionListToContextMenuList(activityItem.links)
-
- delegate: MenuItem {
- id: moreActionsButtonContextMenuEntry
- readonly property int actionIndex: model.modelData.actionIndex
- readonly property string label: model.modelData.label
- text: label
- onTriggered: activityModel.triggerAction(activityItem.itemIndex, actionIndex)
- }
- }
- }
- }
- }
-
- Button {
- id: shareButton
-
- Layout.preferredWidth: (path === "") ? 0 : parent.height
- Layout.preferredHeight: parent.height
- Layout.alignment: Qt.AlignRight
- flat: true
- hoverEnabled: true
- visible: (path === "") ? false : true
- display: AbstractButton.IconOnly
- icon.source: "qrc:///client/theme/share.svg"
- icon.color: "transparent"
- background: Rectangle {
- color: parent.hovered ? Style.lightHover : "transparent"
- }
- ToolTip.visible: hovered
- ToolTip.delay: 1000
- ToolTip.text: qsTr("Open share dialog")
- onClicked: Systray.openShareDialog(displayPath,absolutePath)
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Share %1").arg(displayPath)
- Accessible.onPressAction: shareButton.clicked()
- }
- }
- }
-
- /*add: Transition {
- NumberAnimation { properties: "y"; from: -60; duration: 100; easing.type: Easing.Linear }
- }
-
- remove: Transition {
- NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 100 }
- }
-
- removeDisplaced: Transition {
- SequentialAnimation {
- PauseAnimation { duration: 100}
- NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.Linear }
- }
- }
-
- displaced: Transition {
- NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.Linear }
- }*/
- }
-
- } // Rectangle trayWindowBackground
-}
+import QtQml 2.1 +import QtQml.Models 2.1 +import QtQuick 2.9 +import QtQuick.Window 2.3 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.2 +import QtGraphicalEffects 1.0 + +// Custom qml modules are in /theme (and included by resources.qrc) +import Style 1.0 + +import com.nextcloud.desktopclient 1.0 + +Window { + id: trayWindow + + width: Style.trayWindowWidth + height: Style.trayWindowHeight + color: "transparent" + flags: Qt.Dialog | Qt.FramelessWindowHint + + readonly property int maxMenuHeight: Style.trayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth + + Accessible.role: Accessible.Application + Accessible.name: qsTr("Nextcloud desktop main dialog") + + Component.onCompleted: Systray.forceWindowInit(trayWindow) + + // Close tray window when focus is lost (e.g. click somewhere else on the screen) + onActiveChanged: { + if(!active) { + trayWindow.hide(); + Systray.setClosed(); + } + } + + onVisibleChanged: { + currentAccountStateIndicator.source = "" + currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId) + ? Style.stateOnlineImageSource + : Style.stateOfflineImageSource + + // HACK: reload account Instantiator immediately by restting it - could be done better I guess + // see also id:accountMenu below + userLineInstantiator.active = false; + userLineInstantiator.active = true; + } + + Connections { + target: UserModel + onRefreshCurrentUserGui: { + currentAccountStateIndicator.source = "" + currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId) + ? Style.stateOnlineImageSource + : Style.stateOfflineImageSource + } + onNewUserSelected: { + accountMenu.close(); + } + } + + Connections { + target: Systray + onShowWindow: { + accountMenu.close(); + appsMenu.close(); + + Systray.positionWindow(trayWindow); + + trayWindow.show(); + trayWindow.raise(); + trayWindow.requestActivate(); + + Systray.setOpened(); + UserModel.fetchCurrentActivityModel(); + } + onHideWindow: { + trayWindow.hide(); + Systray.setClosed(); + } + } + + OpacityMask { + anchors.fill: parent + source: ShaderEffectSource { + sourceItem: trayWindowBackground + hideSource: true + } + maskSource: Rectangle { + width: trayWindowBackground.width + height: trayWindowBackground.height + radius: trayWindowBackground.radius + } + } + + Rectangle { + id: trayWindowBackground + + anchors.fill: parent + radius: Style.trayWindowRadius + border.width: Style.trayWindowBorderWidth + border.color: Style.menuBorder + + Accessible.role: Accessible.Grouping + Accessible.name: qsTr("Nextcloud desktop main dialog") + + Rectangle { + id: trayWindowHeaderBackground + + anchors.left: trayWindowBackground.left + anchors.right: trayWindowBackground.right + anchors.top: trayWindowBackground.top + height: Style.trayWindowHeaderHeight + color: Style.ncBlue + + RowLayout { + id: trayWindowHeaderLayout + + spacing: 0 + anchors.fill: parent + + Button { + id: currentAccountButton + + Layout.preferredWidth: Style.currentAccountButtonWidth + Layout.preferredHeight: Style.trayWindowHeaderHeight + display: AbstractButton.IconOnly + flat: true + + Accessible.role: Accessible.ButtonMenu + Accessible.name: qsTr("Current account") + Accessible.onPressAction: currentAccountButton.clicked() + + MouseArea { + id: accountBtnMouseArea + + anchors.fill: parent + hoverEnabled: Style.hoverEffectsEnabled + + // 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: (currentAccountButton.x + 2) + y: (currentAccountButton.y + Style.trayWindowHeaderHeight + 2) + + width: (Style.currentAccountButtonWidth - 2) + height: Math.min(implicitHeight, maxMenuHeight) + closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape + + background: Rectangle { + border.color: Style.menuBorder + radius: Style.currentAccountButtonRadius + } + + Accessible.role: PopupMenu + Accessible.name: qsTr("Account switcher and settings menu") + + 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: UserLine {} + onObjectAdded: accountMenu.insertItem(index, object) + onObjectRemoved: accountMenu.removeItem(object) + } + + MenuItem { + id: addAccountButton + height: Style.addAccountButtonHeight + hoverEnabled: true + + background: Item { + height: parent.height + width: parent.menu.width + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + RowLayout { + anchors.fill: parent + spacing: 0 + + Image { + Layout.leftMargin: 12 + verticalAlignment: Qt.AlignCenter + source: "qrc:///client/theme/black/add.svg" + sourceSize.width: Style.headerButtonIconSize + sourceSize.height: Style.headerButtonIconSize + } + Label { + Layout.leftMargin: 14 + text: qsTr("Add account") + color: "black" + font.pixelSize: Style.topLinePixelSize + } + // Filler on the right + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + onClicked: UserModel.addAccount() + + Accessible.role: Accessible.MenuItem + Accessible.name: qsTr("Add new account") + Accessible.onPressAction: addAccountButton.clicked() + } + + MenuSeparator { + contentItem: Rectangle { + implicitHeight: 1 + color: Style.menuBorder + } + } + + MenuItem { + id: syncPauseButton + font.pixelSize: Style.topLinePixelSize + hoverEnabled: true + onClicked: Systray.pauseResumeSync() + + background: Item { + height: parent.height + width: parent.menu.width + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + 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() + + background: Item { + height: parent.height + width: parent.menu.width + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + 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() + + background: Item { + height: parent.height + width: parent.menu.width + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: parent.parent.hovered ? Style.lightHover : "transparent" + } + } + + Accessible.role: Accessible.MenuItem + Accessible.name: text + Accessible.onPressAction: exitButton.clicked() + } + } + } + + background: Rectangle { + color: accountBtnMouseArea.containsMouse ? "white" : "transparent" + opacity: 0.2 + } + + RowLayout { + id: accountControlRowLayout + + height: Style.trayWindowHeaderHeight + width: Style.currentAccountButtonWidth + spacing: 0 + + Image { + id: currentAccountAvatar + + Layout.leftMargin: 8 + verticalAlignment: Qt.AlignCenter + cache: false + source: 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 user avatar") + + Rectangle { + id: currentAccountStateIndicatorBackground + width: Style.accountAvatarStateIndicatorSize + 2 + height: width + anchors.bottom: currentAccountAvatar.bottom + anchors.right: currentAccountAvatar.right + color: Style.ncBlue + radius: width*0.5 + } + + Rectangle { + width: Style.accountAvatarStateIndicatorSize + 2 + height: width + anchors.bottom: currentAccountAvatar.bottom + anchors.right: currentAccountAvatar.right + color: accountBtnMouseArea.containsMouse ? "white" : "transparent" + opacity: 0.2 + radius: width*0.5 + } + + Image { + id: currentAccountStateIndicator + source: UserModel.isUserConnected(UserModel.currentUserId) + ? Style.stateOnlineImageSource + : Style.stateOfflineImageSource + cache: false + x: currentAccountStateIndicatorBackground.x + 1 + y: currentAccountStateIndicatorBackground.y + 1 + sourceSize.width: Style.accountAvatarStateIndicatorSize + sourceSize.height: Style.accountAvatarStateIndicatorSize + + Accessible.role: Accessible.Indicator + Accessible.name: UserModel.isUserConnected(UserModel.currentUserId()) ? qsTr("Connected") : qsTr("Disconnected") + } + } + + Column { + id: accountLabels + spacing: 4 + Layout.alignment: Qt.AlignLeft + Layout.leftMargin: 6 + Label { + id: currentAccountUser + + width: Style.currentAccountLabelWidth + text: UserModel.currentUser.name + elide: Text.ElideRight + color: Style.ncTextColor + font.pixelSize: Style.topLinePixelSize + font.bold: true + } + Label { + id: currentAccountServer + width: Style.currentAccountLabelWidth + text: UserModel.currentUser.server + elide: Text.ElideRight + color: Style.ncTextColor + font.pixelSize: Style.subLinePixelSize + } + } + + ColorOverlay { + cached: true + color: Style.ncTextColor + width: source.width + height: source.height + source: Image { + Layout.alignment: Qt.AlignRight + verticalAlignment: Qt.AlignCenter + Layout.margins: Style.accountDropDownCaretMargin + source: "qrc:///client/theme/white/caret-down.svg" + sourceSize.width: Style.accountDropDownCaretSize + sourceSize.height: Style.accountDropDownCaretSize + } + } + } + } + + // Filler between account dropdown and header app buttons + Item { + id: trayWindowHeaderSpacer + Layout.fillWidth: true + } + + HeaderButton { + id: openLocalFolderButton + + visible: UserModel.currentUser.hasLocalFolder + icon.source: "qrc:///client/theme/white/folder.svg" + onClicked: UserModel.openCurrentAccountLocalFolder() + + Accessible.role: Accessible.Button + Accessible.name: qsTr("Open local folder of current account") + Accessible.onPressAction: openLocalFolderButton.clicked() + } + + HeaderButton { + id: trayWindowTalkButton + + visible: UserModel.currentUser.serverHasTalk + icon.source: "qrc:///client/theme/white/talk-app.svg" + onClicked: UserModel.openCurrentAccountTalk() + + Accessible.role: Accessible.Button + Accessible.name: qsTr("Open Nextcloud Talk in browser") + Accessible.onPressAction: trayWindowTalkButton.clicked() + } + + HeaderButton { + id: trayWindowAppsButton + icon.source: "qrc:///client/theme/white/more-apps.svg" + onClicked: { + if(appsMenu.count <= 0) { + UserModel.openCurrentAccountServer() + } else if (appsMenu.visible) { + appsMenu.close() + } else { + appsMenu.open() + } + } + + Accessible.role: Accessible.ButtonMenu + Accessible.name: qsTr("More apps") + Accessible.onPressAction: trayWindowAppsButton.clicked() + + Menu { + id: appsMenu + y: (trayWindowAppsButton.y + trayWindowAppsButton.height + 2) + readonly property Item listContentItem: contentItem.contentItem + width: Math.min(listContentItem.childrenRect.width + 4, Style.trayWindowWidth / 2) + height: Math.min(implicitHeight, maxMenuHeight) + closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape + + background: Rectangle { + border.color: Style.menuBorder + radius: 2 + } + + Accessible.role: Accessible.PopupMenu + Accessible.name: qsTr("Apps menu") + + Instantiator { + id: appsMenuInstantiator + model: UserAppsModel + onObjectAdded: appsMenu.insertItem(index, object) + onObjectRemoved: appsMenu.removeItem(object) + delegate: MenuItem { + id: appEntry + text: appName + font.pixelSize: Style.topLinePixelSize + icon.source: appIconUrl + width: contentItem.implicitWidth + leftPadding + rightPadding + onTriggered: UserAppsModel.openAppUrl(appUrl) + hoverEnabled: true + + background: Item { + width: appsMenu.width + height: parent.height + + Rectangle { + anchors.fill: parent + anchors.margins: 1 + color: appEntry.hovered ? Style.lightHover : "transparent" + } + } + + Accessible.role: Accessible.MenuItem + Accessible.name: qsTr("Open %1 in browser").arg(appName) + Accessible.onPressAction: appEntry.triggered() + } + } + } + } + } + } // Rectangle trayWindowHeaderBackground + + ListView { + id: activityListView + anchors.top: trayWindowHeaderBackground.bottom + anchors.left: trayWindowBackground.left + anchors.right: trayWindowBackground.right + anchors.bottom: trayWindowBackground.bottom + clip: true + ScrollBar.vertical: ScrollBar { + id: listViewScrollbar + } + + readonly property int maxActionButtons: 2 + + keyNavigationEnabled: true + + Accessible.role: Accessible.List + Accessible.name: qsTr("Activity list") + + model: activityModel + + delegate: RowLayout { + id: activityItem + + readonly property variant links: model.links + + readonly property int itemIndex: model.index + + width: parent.width + height: Style.trayWindowHeaderHeight + spacing: 0 + + Accessible.role: Accessible.ListItem + Accessible.name: path !== "" ? qsTr("Open %1 locally").arg(displayPath) + : message + Accessible.onPressAction: activityMouseArea.clicked() + + MouseArea { + id: activityMouseArea + enabled: (path !== "" || link !== "") + anchors.left: activityItem.left + anchors.right: activityActionsLayout.right + height: parent.height + anchors.margins: 2 + hoverEnabled: true + onClicked: activityModel.triggerDefaultAction(model.index) + + Rectangle { + anchors.fill: parent + color: (parent.containsMouse ? Style.lightHover : "transparent") + } + } + + Image { + id: activityIcon + anchors.left: activityItem.left + anchors.leftMargin: 8 + anchors.rightMargin: 8 + Layout.preferredWidth: shareButton.icon.width + Layout.preferredHeight: shareButton.icon.height + verticalAlignment: Qt.AlignCenter + cache: true + source: icon + sourceSize.height: 64 + sourceSize.width: 64 + } + + Column { + id: activityTextColumn + anchors.left: activityIcon.right + anchors.right: activityActionsLayout.left + anchors.leftMargin: 8 + spacing: 4 + Layout.alignment: Qt.AlignLeft + Text { + id: activityTextTitle + text: (type === "Activity" || type === "Notification") ? subject : message + width: parent.width + elide: Text.ElideRight + font.pixelSize: Style.topLinePixelSize + color: activityTextTitleColor + } + + Text { + id: activityTextInfo + text: (type === "Sync") ? displayPath + : (type === "File") ? subject + : (type === "Notification") ? message + : "" + height: (text === "") ? 0 : activityTextTitle.height + width: parent.width + elide: Text.ElideRight + font.pixelSize: Style.subLinePixelSize + } + + Text { + id: activityTextDateTime + text: dateTime + height: (text === "") ? 0 : activityTextTitle.height + width: parent.width + elide: Text.ElideRight + font.pixelSize: Style.subLinePixelSize + color: "#808080" + } + + ToolTip { + id: toolTip + visible: activityMouseArea.containsMouse + text: activityTextTitle.text + ((activityTextInfo.text !== "") ? "\n\n" + activityTextInfo.text : "") + delay: 250 + timeout: 10000 + // Can be dropped on more recent Qt, but on 5.12 it doesn't wrap... + contentItem: Text { + text: toolTip.text + font: toolTip.font + wrapMode: Text.Wrap + color: toolTip.palette.toolTipText + } + } + } + RowLayout { + id: activityActionsLayout + anchors.right: activityItem.right + spacing: 0 + Layout.alignment: Qt.AlignRight + + function actionButtonIcon(actionIndex) { + const verb = String(model.links[actionIndex].verb); + if (verb === "WEB" && (model.objectType === "chat" || model.objectType === "call")) { + return "qrc:///client/theme/reply.svg"; + } else if (verb === "DELETE") { + return "qrc:///client/theme/close.svg"; + } + + return "qrc:///client/theme/confirm.svg"; + } + + Repeater { + model: activityItem.links.length > activityListView.maxActionButtons ? 1 : activityItem.links.length + + ActivityActionButton { + id: activityActionButton + + readonly property int actionIndex: model.index + readonly property bool primary: model.index === 0 && String(activityItem.links[actionIndex].verb) !== "DELETE" + + height: activityItem.height + + text: !primary ? "" : activityItem.links[actionIndex].label + + imageSource: !primary ? activityActionsLayout.actionButtonIcon(actionIndex) : "" + + textColor: primary ? Style.ncBlue : "black" + textColorHovered: Style.lightHover + + textBorderColor: Style.ncBlue + + textBgColor: "transparent" + textBgColorHovered: Style.ncBlue + + tooltipText: activityItem.links[actionIndex].label + + Layout.minimumWidth: primary ? 80 : -1 + Layout.minimumHeight: parent.height + + Layout.preferredWidth: primary ? -1 : parent.height + + onClicked: activityModel.triggerAction(activityItem.itemIndex, actionIndex) + } + + } + + Button { + id: moreActionsButton + + Layout.preferredWidth: parent.height + Layout.preferredHeight: parent.height + Layout.alignment: Qt.AlignRight + + flat: true + hoverEnabled: true + visible: activityItem.links.length > activityListView.maxActionButtons + display: AbstractButton.IconOnly + icon.source: "qrc:///client/theme/more.svg" + icon.color: "transparent" + background: Rectangle { + color: parent.hovered ? Style.lightHover : "transparent" + } + ToolTip.visible: hovered + ToolTip.delay: 1000 + ToolTip.text: qsTr("Show more actions") + + Accessible.role: Accessible.Button + Accessible.name: qsTr("Show more actions") + Accessible.onPressAction: moreActionsButton.clicked() + + onClicked: moreActionsButtonContextMenu.popup(); + + Connections { + target: trayWindow + onActiveChanged: { + if (!trayWindow.active) { + moreActionsButtonContextMenu.close(); + } + } + } + + Connections { + target: activityListView + + onMovementStarted: { + moreActionsButtonContextMenu.close(); + } + } + + Container { + id: moreActionsButtonContextMenuContainer + visible: moreActionsButtonContextMenu.opened + + width: moreActionsButtonContextMenu.width + height: moreActionsButtonContextMenu.height + anchors.right: moreActionsButton.right + anchors.top: moreActionsButton.top + + Menu { + id: moreActionsButtonContextMenu + anchors.centerIn: parent + + // transform model to contain indexed actions with primary action filtered out + function actionListToContextMenuList(actionList) { + // early out with non-altered data + if (activityItem.links.length <= activityListView.maxActionButtons) { + return actionList; + } + + // add index to every action and filter 'primary' action out + var reducedActionList = actionList.reduce(function(reduced, action, index) { + if (!action.primary) { + var actionWithIndex = { actionIndex: index, label: action.label }; + reduced.push(actionWithIndex); + } + return reduced; + }, []); + + + return reducedActionList; + } + + Repeater { + id: moreActionsButtonContextMenuRepeater + + model: moreActionsButtonContextMenu.actionListToContextMenuList(activityItem.links) + + delegate: MenuItem { + id: moreActionsButtonContextMenuEntry + readonly property int actionIndex: model.modelData.actionIndex + readonly property string label: model.modelData.label + text: label + onTriggered: activityModel.triggerAction(activityItem.itemIndex, actionIndex) + } + } + } + } + } + + Button { + id: shareButton + + Layout.preferredWidth: (path === "") ? 0 : parent.height + Layout.preferredHeight: parent.height + Layout.alignment: Qt.AlignRight + flat: true + hoverEnabled: true + visible: (path === "") ? false : true + display: AbstractButton.IconOnly + icon.source: "qrc:///client/theme/share.svg" + icon.color: "transparent" + background: Rectangle { + color: parent.hovered ? Style.lightHover : "transparent" + } + ToolTip.visible: hovered + ToolTip.delay: 1000 + ToolTip.text: qsTr("Open share dialog") + onClicked: Systray.openShareDialog(displayPath,absolutePath) + + Accessible.role: Accessible.Button + Accessible.name: qsTr("Share %1").arg(displayPath) + Accessible.onPressAction: shareButton.clicked() + } + } + } + + /*add: Transition { + NumberAnimation { properties: "y"; from: -60; duration: 100; easing.type: Easing.Linear } + } + + remove: Transition { + NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 100 } + } + + removeDisplaced: Transition { + SequentialAnimation { + PauseAnimation { duration: 100} + NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.Linear } + } + } + + displaced: Transition { + NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.Linear } + }*/ + } + + } // Rectangle trayWindowBackground +} |