2020-01-12 18:16:24 +03:00
import QtQml 2.1
import QtQml . Models 2.1
2019-12-08 13:32:22 +03:00
import QtQuick 2.9
2020-01-21 15:54:04 +03:00
import QtQuick . Window 2.3
2020-09-14 18:25:20 +03:00
import QtQuick . Controls 2.3
2019-12-08 13:32:22 +03:00
import QtQuick . Layouts 1.2
import QtGraphicalEffects 1.0
2020-01-19 22:13:12 +03:00
// Custom qml modules are in /theme (and included by resources.qrc)
import Style 1.0
2020-06-15 18:01:39 +03:00
import com . nextcloud . desktopclient 1.0
2019-12-08 13:32:22 +03:00
Window {
2020-01-19 22:13:12 +03:00
id: trayWindow
2019-12-08 13:32:22 +03:00
2020-01-19 22:13:12 +03:00
width: Style . trayWindowWidth
height: Style . trayWindowHeight
color: "transparent"
2020-05-06 16:50:28 +03:00
flags: Qt . Dialog | Qt . FramelessWindowHint
2019-12-08 13:32:22 +03:00
2020-07-06 21:12:58 +03:00
readonly property int maxMenuHeight: Style . trayWindowHeight - Style . trayWindowHeaderHeight - 2 * Style . trayWindowBorderWidth
2020-08-25 14:16:42 +03:00
Accessible.role: Accessible . Application
2020-08-25 17:52:05 +03:00
Accessible.name: qsTr ( "Nextcloud desktop main dialog" )
2020-08-25 13:54:56 +03:00
2020-10-22 13:39:40 +03:00
Component.onCompleted: Systray . forceWindowInit ( trayWindow )
2020-01-19 22:13:12 +03:00
// Close tray window when focus is lost (e.g. click somewhere else on the screen)
2019-12-30 13:39:21 +03:00
onActiveChanged: {
if ( ! active ) {
trayWindow . hide ( ) ;
2020-06-15 18:01:39 +03:00
Systray . setClosed ( ) ;
2019-12-30 13:39:21 +03:00
}
}
2020-01-03 15:09:29 +03:00
onVisibleChanged: {
2021-03-16 22:24:11 +03:00
folderStateIndicator . source = ""
folderStateIndicator . source = UserModel . isUserConnected ( UserModel . currentUserId )
2020-11-23 08:45:26 +03:00
? Style . stateOnlineImageSource
: Style . stateOfflineImageSource
2020-01-11 17:05:37 +03:00
2020-01-19 22:13:12 +03:00
// HACK: reload account Instantiator immediately by restting it - could be done better I guess
// see also id:accountMenu below
2020-01-11 17:05:37 +03:00
userLineInstantiator . active = false ;
userLineInstantiator . active = true ;
2020-01-03 15:09:29 +03:00
}
2019-12-08 13:32:22 +03:00
Connections {
2020-06-15 18:01:39 +03:00
target: UserModel
2019-12-08 13:32:22 +03:00
onRefreshCurrentUserGui: {
2021-03-16 22:24:11 +03:00
folderStateIndicator . source = ""
folderStateIndicator . source = UserModel . isUserConnected ( UserModel . currentUserId )
2020-11-23 08:45:26 +03:00
? Style . stateOnlineImageSource
: Style . stateOfflineImageSource
2019-12-08 13:32:22 +03:00
}
onNewUserSelected: {
2020-01-03 15:09:29 +03:00
accountMenu . close ( ) ;
2019-12-08 13:32:22 +03:00
}
2019-12-30 13:52:07 +03:00
}
Connections {
2020-06-15 18:01:39 +03:00
target: Systray
2019-12-30 13:39:21 +03:00
onShowWindow: {
2020-01-05 18:25:32 +03:00
accountMenu . close ( ) ;
2020-06-15 20:01:04 +03:00
appsMenu . close ( ) ;
2020-05-20 20:36:57 +03:00
2020-06-23 12:20:30 +03:00
Systray . positionWindow ( trayWindow ) ;
2020-05-20 20:36:57 +03:00
trayWindow . show ( ) ;
trayWindow . raise ( ) ;
trayWindow . requestActivate ( ) ;
2020-06-15 18:01:39 +03:00
Systray . setOpened ( ) ;
UserModel . fetchCurrentActivityModel ( ) ;
2019-12-30 13:39:21 +03:00
}
onHideWindow: {
trayWindow . hide ( ) ;
2020-06-15 18:01:39 +03:00
Systray . setClosed ( ) ;
2019-12-30 13:39:21 +03:00
}
2019-12-08 13:32:22 +03:00
}
2020-07-27 18:27:23 +03:00
OpacityMask {
anchors.fill: parent
source: ShaderEffectSource {
sourceItem: trayWindowBackground
hideSource: true
}
maskSource: Rectangle {
width: trayWindowBackground . width
height: trayWindowBackground . height
radius: trayWindowBackground . radius
}
}
2019-12-08 13:32:22 +03:00
Rectangle {
id: trayWindowBackground
2020-01-19 22:13:12 +03:00
anchors.fill: parent
radius: Style . trayWindowRadius
border.width: Style . trayWindowBorderWidth
2020-06-15 20:06:59 +03:00
border.color: Style . menuBorder
2019-12-08 13:32:22 +03:00
2020-08-25 14:16:42 +03:00
Accessible.role: Accessible . Grouping
2020-08-25 17:52:05 +03:00
Accessible.name: qsTr ( "Nextcloud desktop main dialog" )
2020-08-25 14:16:42 +03:00
2019-12-08 13:32:22 +03:00
Rectangle {
id: trayWindowHeaderBackground
2020-01-19 22:13:12 +03:00
anchors.left: trayWindowBackground . left
2020-11-18 18:42:37 +03:00
anchors.right: trayWindowBackground . right
2020-01-19 22:13:12 +03:00
anchors.top: trayWindowBackground . top
height: Style . trayWindowHeaderHeight
color: Style . ncBlue
2019-12-08 13:32:22 +03:00
RowLayout {
id: trayWindowHeaderLayout
2020-01-19 22:13:12 +03:00
spacing: 0
anchors.fill: parent
2019-12-08 13:32:22 +03:00
Button {
id: currentAccountButton
2020-01-19 22:13:12 +03:00
Layout.preferredWidth: Style . currentAccountButtonWidth
Layout.preferredHeight: Style . trayWindowHeaderHeight
display: AbstractButton . IconOnly
flat: true
2019-12-08 13:32:22 +03:00
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . ButtonMenu
2020-08-25 15:59:10 +03:00
Accessible.name: qsTr ( "Current account" )
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: currentAccountButton . clicked ( )
2020-08-25 13:54:56 +03:00
2019-12-08 13:32:22 +03:00
MouseArea {
id: accountBtnMouseArea
2020-01-19 22:13:12 +03:00
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
2020-06-15 18:01:39 +03:00
onClicked: {
syncPauseButton . text = Systray . syncIsPaused ( ) ? qsTr ( "Resume sync for all" ) : qsTr ( "Pause sync for all" )
2020-09-14 19:03:57 +03:00
if ( accountMenu . visible ) {
accountMenu . close ( )
} else {
accountMenu . open ( )
}
2019-12-08 13:32:22 +03:00
}
Menu {
id: accountMenu
2020-01-19 22:13:12 +03:00
// x coordinate grows towards the right
// y coordinate grows towards the bottom
2019-12-08 13:32:22 +03:00
x: ( currentAccountButton . x + 2 )
2020-01-19 22:13:12 +03:00
y: ( currentAccountButton . y + Style . trayWindowHeaderHeight + 2 )
width: ( Style . currentAccountButtonWidth - 2 )
2020-07-06 21:12:58 +03:00
height: Math . min ( implicitHeight , maxMenuHeight )
2020-09-14 19:03:57 +03:00
closePolicy: Menu . CloseOnPressOutsideParent | Menu . CloseOnEscape
2019-12-08 13:32:22 +03:00
background: Rectangle {
2020-06-15 20:06:59 +03:00
border.color: Style . menuBorder
2020-01-19 22:13:12 +03:00
radius: Style . currentAccountButtonRadius
2019-12-08 13:32:22 +03:00
}
2020-08-25 13:54:56 +03:00
Accessible.role: PopupMenu
2020-08-25 17:52:05 +03:00
Accessible.name: qsTr ( "Account switcher and settings menu" )
2020-08-25 13:54:56 +03:00
2020-01-12 13:06:48 +03:00
onClosed: {
2020-01-19 22:13:12 +03:00
// HACK: reload account Instantiator immediately by restting it - could be done better I guess
// see also onVisibleChanged above
2020-01-12 13:06:48 +03:00
userLineInstantiator . active = false ;
userLineInstantiator . active = true ;
}
2019-12-08 13:32:22 +03:00
Instantiator {
2020-01-10 18:28:53 +03:00
id: userLineInstantiator
2020-06-15 18:01:39 +03:00
model: UserModel
2019-12-08 13:32:22 +03:00
delegate: UserLine { }
2020-01-05 23:06:42 +03:00
onObjectAdded: accountMenu . insertItem ( index , object )
2019-12-08 13:32:22 +03:00
onObjectRemoved: accountMenu . removeItem ( object )
}
2020-01-04 19:22:56 +03:00
MenuItem {
2020-01-11 22:28:00 +03:00
id: addAccountButton
2020-01-19 22:13:12 +03:00
height: Style . addAccountButtonHeight
2020-07-06 14:55:14 +03:00
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"
}
}
2020-01-11 22:28:00 +03:00
RowLayout {
2020-01-19 22:13:12 +03:00
anchors.fill: parent
2020-01-11 22:28:00 +03:00
spacing: 0
Image {
2020-01-19 22:13:12 +03:00
Layout.leftMargin: 12
2020-01-11 22:28:00 +03:00
verticalAlignment: Qt . AlignCenter
source: "qrc:///client/theme/black/add.svg"
2020-01-19 22:13:12 +03:00
sourceSize.width: Style . headerButtonIconSize
sourceSize.height: Style . headerButtonIconSize
2020-01-11 22:28:00 +03:00
}
Label {
2020-01-15 10:01:54 +03:00
Layout.leftMargin: 14
2020-01-14 09:59:28 +03:00
text: qsTr ( "Add account" )
2020-01-11 22:28:00 +03:00
color: "black"
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . topLinePixelSize
2020-01-11 22:28:00 +03:00
}
2020-01-19 22:13:12 +03:00
// Filler on the right
2020-01-11 22:28:00 +03:00
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}
2020-06-15 18:01:39 +03:00
onClicked: UserModel . addAccount ( )
2020-08-25 14:16:42 +03:00
Accessible.role: Accessible . MenuItem
Accessible.name: qsTr ( "Add new account" )
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: addAccountButton . clicked ( )
2020-01-04 19:22:56 +03:00
}
2020-06-22 01:49:06 +03:00
MenuSeparator {
contentItem: Rectangle {
implicitHeight: 1
color: Style . menuBorder
}
}
2020-01-04 19:22:56 +03:00
2020-01-05 18:25:32 +03:00
MenuItem {
2020-01-05 23:06:42 +03:00
id: syncPauseButton
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . topLinePixelSize
2020-07-06 14:55:14 +03:00
hoverEnabled: true
2020-06-15 18:01:39 +03:00
onClicked: Systray . pauseResumeSync ( )
2020-07-06 14:55:14 +03:00
background: Item {
height: parent . height
width: parent . menu . width
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: parent . parent . hovered ? Style.lightHover : "transparent"
}
}
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . MenuItem
Accessible.name: Systray . syncIsPaused ( ) ? qsTr ( "Resume sync for all" ) : qsTr ( "Pause sync for all" )
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: syncPauseButton . clicked ( )
2020-01-05 18:25:32 +03:00
}
2020-01-04 19:22:56 +03:00
MenuItem {
2020-09-15 17:45:22 +03:00
id: settingsButton
2020-06-29 20:41:51 +03:00
text: qsTr ( "Settings" )
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . topLinePixelSize
2020-07-06 14:55:14 +03:00
hoverEnabled: true
2020-06-15 18:01:39 +03:00
onClicked: Systray . openSettings ( )
2020-07-06 14:55:14 +03:00
background: Item {
height: parent . height
width: parent . menu . width
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: parent . parent . hovered ? Style.lightHover : "transparent"
}
}
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . MenuItem
Accessible.name: text
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: settingsButton . clicked ( )
2020-01-04 19:22:56 +03:00
}
2020-01-05 23:06:42 +03:00
MenuItem {
2020-09-15 17:45:22 +03:00
id: exitButton
2020-06-29 20:41:51 +03:00
text: qsTr ( "Exit" ) ;
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . topLinePixelSize
2020-07-06 14:55:14 +03:00
hoverEnabled: true
2020-06-15 18:01:39 +03:00
onClicked: Systray . shutdown ( )
2020-07-06 14:55:14 +03:00
background: Item {
height: parent . height
width: parent . menu . width
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: parent . parent . hovered ? Style.lightHover : "transparent"
}
}
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . MenuItem
Accessible.name: text
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: exitButton . clicked ( )
2020-01-04 19:22:56 +03:00
}
2019-12-08 13:32:22 +03:00
}
}
2020-07-27 18:27:23 +03:00
background: Rectangle {
color: accountBtnMouseArea . containsMouse ? "white" : "transparent"
opacity: 0.2
2019-12-08 13:32:22 +03:00
}
RowLayout {
id: accountControlRowLayout
2020-01-19 22:13:12 +03:00
height: Style . trayWindowHeaderHeight
width: Style . currentAccountButtonWidth
2019-12-08 13:32:22 +03:00
spacing: 0
2020-08-25 13:54:56 +03:00
2019-12-08 13:32:22 +03:00
Image {
id: currentAccountAvatar
2020-01-19 22:13:12 +03:00
2019-12-08 13:32:22 +03:00
Layout.leftMargin: 8
verticalAlignment: Qt . AlignCenter
2020-01-03 15:09:29 +03:00
cache: false
2020-07-21 14:24:59 +03:00
source: UserModel . currentUser . avatar != "" ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite"
2020-01-19 22:13:12 +03:00
Layout.preferredHeight: Style . accountAvatarSize
Layout.preferredWidth: Style . accountAvatarSize
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . Graphic
Accessible.name: qsTr ( "Current user avatar" )
2020-01-15 22:11:50 +03:00
Rectangle {
2021-03-16 22:24:11 +03:00
id: currentAccountStatusIndicatorBackground
2020-01-19 22:13:12 +03:00
width: Style . accountAvatarStateIndicatorSize + 2
2020-01-15 22:11:50 +03:00
height: width
anchors.bottom: currentAccountAvatar . bottom
anchors.right: currentAccountAvatar . right
2020-01-19 22:13:12 +03:00
color: Style . ncBlue
2020-01-15 22:11:50 +03:00
radius: width * 0.5
}
2020-01-19 22:13:12 +03:00
2020-10-21 12:24:06 +03:00
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
}
2020-01-12 11:10:06 +03:00
Image {
2021-03-16 22:24:11 +03:00
id: currentAccountStatusIndicator
source: UserModel . currentUser . statusIcon
2020-01-12 11:10:06 +03:00
cache: false
2021-03-16 22:24:11 +03:00
x: currentAccountStatusIndicatorBackground . x + 1
y: currentAccountStatusIndicatorBackground . y + 1
2020-01-19 22:13:12 +03:00
sourceSize.width: Style . accountAvatarStateIndicatorSize
sourceSize.height: Style . accountAvatarStateIndicatorSize
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . Indicator
2021-03-16 22:24:11 +03:00
Accessible.name: UserModel . isUserStatusOnline ( UserModel . currentUserId ( ) ) ? qsTr ( "Current user status is online" ) : qsTr ( "Current user status is do not disturb" )
2020-01-12 11:10:06 +03:00
}
2019-12-08 13:32:22 +03:00
}
Column {
id: accountLabels
spacing: 4
Layout.alignment: Qt . AlignLeft
Layout.leftMargin: 6
Label {
id: currentAccountUser
2020-06-16 15:06:30 +03:00
2020-01-19 22:13:12 +03:00
width: Style . currentAccountLabelWidth
2020-06-16 15:06:30 +03:00
text: UserModel . currentUser . name
2020-01-05 23:06:42 +03:00
elide: Text . ElideRight
2020-10-21 14:40:42 +03:00
color: Style . ncTextColor
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . topLinePixelSize
2019-12-08 13:32:22 +03:00
font.bold: true
}
Label {
2020-10-03 18:12:16 +03:00
id: currentUserStatus
2020-01-19 22:13:12 +03:00
width: Style . currentAccountLabelWidth
2021-03-16 22:24:11 +03:00
text: UserModel . currentUser . statusMessage
2020-01-05 23:06:42 +03:00
elide: Text . ElideRight
2020-10-21 14:40:42 +03:00
color: Style . ncTextColor
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . subLinePixelSize
2019-12-08 13:32:22 +03:00
}
}
2020-12-10 19:43:45 +03:00
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
}
2019-12-08 13:32:22 +03:00
}
}
}
2021-04-06 23:52:32 +03:00
RowLayout {
id: openLocalFolderRowLayout
height: Style . trayWindowHeaderHeight
width: height
anchors.left: accountControlRowLayout . right
anchors.top: accountControlRowLayout . top
spacing: 0
Layout.preferredWidth: Style . trayWindowHeaderHeight
Layout.preferredHeight: Style . trayWindowHeaderHeight
HeaderButton {
id: openLocalFolderButton
visible: UserModel . currentUser . hasLocalFolder
icon.source: "qrc:///client/theme/white/folder.svg"
onClicked: UserModel . openCurrentAccountLocalFolder ( )
}
Rectangle {
id: folderStateIndicatorBackground
width: Style . folderStateIndicatorSize
height: width
anchors.top: openLocalFolderButton . verticalCenter
anchors.left: openLocalFolderButton . horizontalCenter
color: Style . ncBlue
radius: width * 0.5
}
2020-01-19 22:13:12 +03:00
2021-04-06 23:52:32 +03:00
Image {
id: folderStateIndicator
source: UserModel . isUserConnected ( UserModel . currentUserId )
? Style . stateOnlineImageSource
: Style . stateOfflineImageSource
cache: false
x: folderStateIndicatorBackground . x
y: folderStateIndicatorBackground . y
sourceSize.width: Style . folderStateIndicatorSize
sourceSize.height: Style . folderStateIndicatorSize
Accessible.role: Accessible . Indicator
Accessible.name: UserModel . isUserConnected ( UserModel . currentUserId ( ) ) ? qsTr ( "Connected" ) : qsTr ( "Disconnected" )
}
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . Button
2020-08-25 17:52:05 +03:00
Accessible.name: qsTr ( "Open local folder of current account" )
2021-03-16 22:24:11 +03:00
}
2020-06-15 16:35:34 +03:00
HeaderButton {
2019-12-08 13:32:22 +03:00
id: trayWindowTalkButton
2021-04-07 13:06:37 +03:00
2020-06-16 15:06:30 +03:00
visible: UserModel . currentUser . serverHasTalk
2019-12-08 13:32:22 +03:00
icon.source: "qrc:///client/theme/white/talk-app.svg"
2020-06-15 18:01:39 +03:00
onClicked: UserModel . openCurrentAccountTalk ( )
2021-04-06 23:52:32 +03:00
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . Button
2020-08-25 17:52:05 +03:00
Accessible.name: qsTr ( "Open Nextcloud Talk in browser" )
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: trayWindowTalkButton . clicked ( )
2019-12-08 13:32:22 +03:00
}
2020-06-15 16:35:34 +03:00
HeaderButton {
2019-12-08 13:32:22 +03:00
id: trayWindowAppsButton
icon.source: "qrc:///client/theme/white/more-apps.svg"
2021-04-07 13:06:37 +03:00
2020-06-15 16:35:34 +03:00
onClicked: {
2020-09-14 19:03:57 +03:00
if ( appsMenu . count <= 0 ) {
2020-09-14 18:25:20 +03:00
UserModel . openCurrentAccountServer ( )
2020-09-14 19:03:57 +03:00
} else if ( appsMenu . visible ) {
appsMenu . close ( )
} else {
appsMenu . open ( )
2019-12-08 13:32:22 +03:00
}
2020-06-15 16:35:34 +03:00
}
2020-01-15 18:42:06 +03:00
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . ButtonMenu
2020-08-25 17:52:05 +03:00
Accessible.name: qsTr ( "More apps" )
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: trayWindowAppsButton . clicked ( )
2020-08-25 13:54:56 +03:00
2020-06-15 16:35:34 +03:00
Menu {
id: appsMenu
y: ( trayWindowAppsButton . y + trayWindowAppsButton . height + 2 )
2020-07-06 15:44:23 +03:00
readonly property Item listContentItem: contentItem . contentItem
width: Math . min ( listContentItem . childrenRect . width + 4 , Style . trayWindowWidth / 2 )
2020-07-06 21:12:58 +03:00
height: Math . min ( implicitHeight , maxMenuHeight )
2020-09-14 19:03:57 +03:00
closePolicy: Menu . CloseOnPressOutsideParent | Menu . CloseOnEscape
2020-01-15 18:42:06 +03:00
2020-06-15 16:35:34 +03:00
background: Rectangle {
2020-06-15 20:06:59 +03:00
border.color: Style . menuBorder
2020-06-15 16:35:34 +03:00
radius: 2
2020-01-15 18:42:06 +03:00
}
2019-12-08 13:32:22 +03:00
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . PopupMenu
Accessible.name: qsTr ( "Apps menu" )
2020-06-15 16:35:34 +03:00
Instantiator {
id: appsMenuInstantiator
2020-06-15 18:01:39 +03:00
model: UserAppsModel
2020-06-15 16:35:34 +03:00
onObjectAdded: appsMenu . insertItem ( index , object )
onObjectRemoved: appsMenu . removeItem ( object )
delegate: MenuItem {
2020-06-17 20:39:12 +03:00
id: appEntry
2020-06-15 16:35:34 +03:00
text: appName
font.pixelSize: Style . topLinePixelSize
icon.source: appIconUrl
width: contentItem . implicitWidth + leftPadding + rightPadding
2020-06-15 18:01:39 +03:00
onTriggered: UserAppsModel . openAppUrl ( appUrl )
2020-06-17 20:39:12 +03:00
hoverEnabled: true
background: Item {
width: appsMenu . width
height: parent . height
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: appEntry . hovered ? Style.lightHover : "transparent"
}
}
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . MenuItem
2020-10-10 01:26:18 +03:00
Accessible.name: qsTr ( "Open %1 in browser" ) . arg ( appName )
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: appEntry . triggered ( )
2019-12-08 13:32:22 +03:00
}
}
}
}
}
} // Rectangle trayWindowHeaderBackground
ListView {
id: activityListView
anchors.top: trayWindowHeaderBackground . bottom
2020-11-18 18:42:37 +03:00
anchors.left: trayWindowBackground . left
anchors.right: trayWindowBackground . right
anchors.bottom: trayWindowBackground . bottom
2019-12-08 13:32:22 +03:00
clip: true
2020-01-13 11:59:34 +03:00
ScrollBar.vertical: ScrollBar {
id: listViewScrollbar
}
2019-12-08 13:32:22 +03:00
2020-11-18 18:42:37 +03:00
readonly property int maxActionButtons: 2
2020-08-25 14:16:42 +03:00
keyNavigationEnabled: true
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . List
Accessible.name: qsTr ( "Activity list" )
2020-01-02 12:39:53 +03:00
model: activityModel
2019-12-08 13:32:22 +03:00
delegate: RowLayout {
id: activityItem
2020-01-19 22:13:12 +03:00
2020-11-18 18:42:37 +03:00
readonly property variant links: model . links
readonly property int itemIndex: model . index
2020-01-19 22:13:12 +03:00
width: parent . width
height: Style . trayWindowHeaderHeight
2019-12-08 13:32:22 +03:00
spacing: 0
2020-01-14 21:48:21 +03:00
2020-08-25 13:54:56 +03:00
Accessible.role: Accessible . ListItem
2020-10-10 01:26:18 +03:00
Accessible.name: path !== "" ? qsTr ( "Open %1 locally" ) . arg ( displayPath )
2020-11-18 18:42:37 +03:00
: message
2020-09-15 17:45:22 +03:00
Accessible.onPressAction: activityMouseArea . clicked ( )
2020-08-25 13:54:56 +03:00
2020-04-25 11:17:53 +03:00
MouseArea {
2020-09-08 17:43:45 +03:00
id: activityMouseArea
2020-06-15 20:08:16 +03:00
enabled: ( path !== "" || link !== "" )
2020-04-25 11:17:53 +03:00
anchors.left: activityItem . left
2020-11-18 18:42:37 +03:00
anchors.right: activityActionsLayout . right
2020-04-25 11:17:53 +03:00
height: parent . height
anchors.margins: 2
hoverEnabled: true
2020-11-18 18:42:37 +03:00
onClicked: activityModel . triggerDefaultAction ( model . index )
2020-09-08 17:43:45 +03:00
2020-04-25 11:17:53 +03:00
Rectangle {
anchors.fill: parent
color: ( parent . containsMouse ? Style.lightHover : "transparent" )
}
}
2019-12-08 13:32:22 +03:00
Image {
id: activityIcon
2020-04-25 11:17:53 +03:00
anchors.left: activityItem . left
anchors.leftMargin: 8
anchors.rightMargin: 8
Layout.preferredWidth: shareButton . icon . width
Layout.preferredHeight: shareButton . icon . height
2019-12-08 13:32:22 +03:00
verticalAlignment: Qt . AlignCenter
2020-01-13 11:59:34 +03:00
cache: true
source: icon
2020-01-17 12:38:21 +03:00
sourceSize.height: 64
sourceSize.width: 64
2019-12-08 13:32:22 +03:00
}
2020-04-25 11:17:53 +03:00
2019-12-08 13:32:22 +03:00
Column {
2020-01-03 18:15:15 +03:00
id: activityTextColumn
2020-04-25 11:17:53 +03:00
anchors.left: activityIcon . right
2020-11-18 18:42:37 +03:00
anchors.right: activityActionsLayout . left
2020-04-25 11:17:53 +03:00
anchors.leftMargin: 8
2019-12-08 13:32:22 +03:00
spacing: 4
Layout.alignment: Qt . AlignLeft
Text {
id: activityTextTitle
2020-01-17 16:50:05 +03:00
text: ( type === "Activity" || type === "Notification" ) ? subject : message
2020-11-18 18:42:37 +03:00
width: parent . width
2020-01-03 18:15:15 +03:00
elide: Text . ElideRight
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . topLinePixelSize
2020-01-17 22:26:48 +03:00
color: activityTextTitleColor
2019-12-08 13:32:22 +03:00
}
2020-01-14 21:48:21 +03:00
2019-12-08 13:32:22 +03:00
Text {
id: activityTextInfo
2020-06-15 20:02:27 +03:00
text: ( type === "Sync" ) ? displayPath
2020-05-25 21:03:01 +03:00
: ( type === "File" ) ? subject
2020-06-15 20:02:27 +03:00
: ( type === "Notification" ) ? message
: ""
2020-01-17 16:50:05 +03:00
height: ( text === "" ) ? 0 : activityTextTitle . height
2020-11-18 18:42:37 +03:00
width: parent . width
2020-01-03 18:15:15 +03:00
elide: Text . ElideRight
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . subLinePixelSize
2019-12-08 13:32:22 +03:00
}
2020-01-17 22:16:20 +03:00
Text {
id: activityTextDateTime
text: dateTime
height: ( text === "" ) ? 0 : activityTextTitle . height
2020-11-18 18:42:37 +03:00
width: parent . width
2020-01-17 22:16:20 +03:00
elide: Text . ElideRight
2020-01-19 22:13:12 +03:00
font.pixelSize: Style . subLinePixelSize
2020-01-17 22:16:20 +03:00
color: "#808080"
}
2020-09-08 17:43:45 +03:00
ToolTip {
2020-09-24 15:47:56 +03:00
id: toolTip
2020-09-08 17:43:45 +03:00
visible: activityMouseArea . containsMouse
2020-09-12 00:59:03 +03:00
text: activityTextTitle . text + ( ( activityTextInfo . text !== "" ) ? "\n\n" + activityTextInfo.text : "" )
2020-09-08 17:43:45 +03:00
delay: 250
2020-09-12 00:59:03 +03:00
timeout: 10000
2020-09-24 15:47:56 +03:00
// 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
}
2020-09-08 17:43:45 +03:00
}
2019-12-08 13:32:22 +03:00
}
2020-11-18 18:42:37 +03:00
RowLayout {
id: activityActionsLayout
2020-04-25 11:17:53 +03:00
anchors.right: activityItem . right
2020-11-18 18:42:37 +03:00
spacing: 0
2019-12-08 13:32:22 +03:00
Layout.alignment: Qt . AlignRight
2020-11-18 18:42:37 +03:00
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" ;
2020-01-13 13:46:49 +03:00
}
2020-08-25 13:54:56 +03:00
2020-11-18 18:42:37 +03:00
Repeater {
model: activityItem . links . length > activityListView . maxActionButtons ? 1 : activityItem . links . length
2020-09-29 20:22:43 +03:00
2020-11-18 18:42:37 +03:00
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 )
}
2020-09-29 20:22:43 +03:00
}
2020-11-18 18:42:37 +03:00
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 ( )
}
2020-09-29 20:22:43 +03:00
}
2019-12-08 13:32:22 +03:00
}
2020-01-16 19:11:08 +03:00
/ * a d d : T r a n s i t i o n {
2019-12-08 13:32:22 +03:00
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 }
2020-01-16 19:11:08 +03:00
} * /
2019-12-08 13:32:22 +03:00
}
} // Rectangle trayWindowBackground
}