Implemented notification action buttons and context menu for confirm/dismiss and...
authorallexzander <blackslayer4@gmail.com>
Wed, 18 Nov 2020 15:42:37 +0000 (17:42 +0200)
committerKevin Ottens (Rebase PR Action) <er-vin@users.noreply.github.com>
Wed, 2 Dec 2020 08:08:37 +0000 (08:08 +0000)
Signed-off-by: allexzander <blackslayer4@gmail.com>
resources.qrc
src/gui/CMakeLists.txt
src/gui/tray/ActivityActionButton.qml [new file with mode: 0644]
src/gui/tray/ActivityData.h
src/gui/tray/ActivityListModel.cpp
src/gui/tray/ActivityListModel.h
src/gui/tray/NotificationHandler.cpp
src/gui/tray/UserModel.cpp
src/gui/tray/Window.qml

index 437c9567ae0d0bc03693f0e1d0168dda6cad86a8..f2f122987d1cd666874d7201e54cb0d39369f253 100644 (file)
@@ -5,5 +5,6 @@
         <file>src/gui/tray/HeaderButton.qml</file>
         <file>theme/Style/Style.qml</file>
         <file>theme/Style/qmldir</file>
+        <file>src/gui/tray/ActivityActionButton.qml</file>
     </qresource>
 </RCC>
index 5a49920e031010cbd330e07b25c2b6547a4b7115..b6a66692487faf591ce28284b1b763e5435cb8a1 100644 (file)
@@ -43,6 +43,7 @@ set(client_UI_SRCS
     addcertificatedialog.ui
     proxyauthdialog.ui
     mnemonicdialog.ui
+    tray/ActivityActionButton.qml
     tray/Window.qml
     tray/UserLine.qml
     wizard/flow2authwidget.ui
diff --git a/src/gui/tray/ActivityActionButton.qml b/src/gui/tray/ActivityActionButton.qml
new file mode 100644 (file)
index 0000000..6bb127e
--- /dev/null
@@ -0,0 +1,106 @@
+import QtQuick 2.5
+import QtQuick.Controls 2.3
+import Style 1.0
+
+Item {
+    id: root
+    readonly property bool labelVisible: label.visible
+    readonly property bool iconVisible: icon.visible
+
+    // label value
+    property string text: ""
+
+    // icon value
+    property string imageSource: ""
+
+    // Tooltip value
+    property string tooltipText: text
+
+    // text color
+    property color textColor: Style.ncTextColor
+    property color textColorHovered: Style.lightHover
+
+    // text background color
+    property color textBgColor: "transparent"
+    property color textBgColorHovered: Style.lightHover
+
+    // icon background color
+    property color iconBgColor: "transparent"
+    property color iconBgColorHovered: Style.lightHover
+
+    // text border color
+    property color textBorderColor: "transparent"
+
+    property alias hovered: mouseArea.containsMouse
+
+    signal clicked()
+
+    Accessible.role: Accessible.Button
+    Accessible.name: text !== "" ? text : (tooltipText !== "" ? tooltipText : qsTr("Activity action button"))
+    Accessible.onPressAction: clicked()
+
+    // background with border around the Text
+    Rectangle {
+        visible: parent.labelVisible
+
+        anchors.fill: parent
+
+        // padding
+        anchors.topMargin: 10
+        anchors.bottomMargin: 10
+
+        border.color: parent.textBorderColor
+        border.width: 1
+
+        color: parent.hovered ? parent.textBgColorHovered : parent.textBgColor
+
+        radius: 25
+    }
+
+    // background with border around the Image
+    Rectangle {
+        visible: parent.iconVisible
+
+        anchors.fill: parent
+
+        color: parent.hovered ? parent.iconBgColorHovered : parent.iconBgColor
+    }
+
+    // label
+    Text {
+        id: label
+        visible: parent.text !== ""
+        text: parent.text
+        font: parent.font
+        color: parent.hovered ? parent.textColorHovered : parent.textColor
+        anchors.fill: parent
+        anchors.leftMargin: 10
+        anchors.rightMargin: 10
+        horizontalAlignment: Text.AlignHCenter
+        verticalAlignment: Text.AlignVCenter
+        elide: Text.ElideRight
+    }
+
+    // icon
+    Image {
+        id: icon
+        visible: parent.imageSource !== ""
+        anchors.centerIn: parent
+        source: parent.imageSource
+        sourceSize.width: visible ? 32 : 0
+        sourceSize.height: visible ? 32 : 0
+    }
+
+    MouseArea {
+        id: mouseArea
+        anchors.fill: parent
+        onClicked: parent.clicked()
+        hoverEnabled: true
+    }
+
+    ToolTip {
+        text: parent.tooltipText
+        delay: 1000
+        visible: text != "" && parent.hovered
+    }
+}
index be30f77a2ac01390316965838dc00067e41dbcc0..f8bbef1015567db6309e894a1783ce8ce8c95bec 100644 (file)
@@ -27,11 +27,18 @@ namespace OCC {
 
 class ActivityLink
 {
+    Q_GADGET
+
+    Q_PROPERTY(QString label MEMBER _label)
+    Q_PROPERTY(QString link MEMBER _link)
+    Q_PROPERTY(QByteArray verb MEMBER _verb)
+    Q_PROPERTY(bool primary MEMBER _primary)
+
 public:
     QString _label;
     QString _link;
     QByteArray _verb;
-    bool _isPrimary;
+    bool _primary;
 };
 
 /* ==================================================================== */
index 15d7a22bddfb9f86cedfb0c0af8295d32ff41f5d..a2d39252de464454a91da3f96a19bd328c280b23 100644 (file)
@@ -53,6 +53,7 @@ QHash<int, QByteArray> ActivityListModel::roleNames() const
     roles[ActionRole] = "type";
     roles[ActionIconRole] = "icon";
     roles[ActionTextRole] = "subject";
+    roles[ActionsLinksRole] = "links";
     roles[ActionTextColorRole] = "activityTextTitleColor";
     roles[ObjectTypeRole] = "objectType";
     roles[PointInTimeRole] = "dateTime";
@@ -139,10 +140,8 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
     }
     case ActionsLinksRole: {
         QList<QVariant> customList;
-        foreach (ActivityLink customItem, a._links) {
-            QVariant customVariant;
-            customVariant.setValue(customItem);
-            customList << customVariant;
+        foreach (ActivityLink activityLink, a._links) {
+            customList << QVariant::fromValue(activityLink);
         }
         return customList;
     }
@@ -418,17 +417,17 @@ void ActivityListModel::removeActivityFromActivityList(Activity activity)
     }
 }
 
-void ActivityListModel::triggerActionAtIndex(int id) const
+void ActivityListModel::triggerDefaultAction(int activityIndex) const
 {
-    if (id < 0 || id >= _finalList.size()) {
-        qCWarning(lcActivity) << "Couldn't trigger action at index" << id << "/ final list size:" << _finalList.size();
+    if (activityIndex < 0 || activityIndex >= _finalList.size()) {
+        qCWarning(lcActivity) << "Couldn't trigger default action at index" << activityIndex << "/ final list size:" << _finalList.size();
         return;
     }
 
-    const auto modelIndex = index(id);
+    const auto modelIndex = index(activityIndex);
     const auto path = data(modelIndex, PathRole).toUrl();
 
-    const auto activity = _finalList.at(id);
+    const auto activity = _finalList.at(activityIndex);
     if (activity._status == SyncFileItem::Conflict) {
         Q_ASSERT(!activity._file.isEmpty());
         Q_ASSERT(!activity._folder.isEmpty());
@@ -461,6 +460,30 @@ void ActivityListModel::triggerActionAtIndex(int id) const
     }
 }
 
+void ActivityListModel::triggerAction(int activityIndex, int actionIndex)
+{
+    if (activityIndex < 0 || activityIndex >= _finalList.size()) {
+        qCWarning(lcActivity) << "Couldn't trigger action on activity at index" << activityIndex << "/ final list size:" << _finalList.size();
+        return;
+    }
+
+    const auto activity = _finalList[activityIndex];
+
+    if (actionIndex < 0 || actionIndex >= activity._links.size()) {
+        qCWarning(lcActivity) << "Couldn't trigger action at index" << actionIndex << "/ actions list size:" << activity._links.size();
+        return;
+    }
+
+    const auto action = activity._links[actionIndex];
+
+    if (action._verb == "WEB") {
+        QDesktopServices::openUrl(QUrl(action._link));
+        return;
+    }
+
+    emit sendNotificationRequest(activity._accName, action._link, action._verb, activityIndex);
+}
+
 void ActivityListModel::combineActivityLists()
 {
     ActivityList resultList;
index f09d39d66e0d30ef3b7c6ce01b13642ff8d90f93..29b14e921c700f1b67f190bcd40dba48e6fef8ff 100644 (file)
@@ -74,7 +74,8 @@ public:
     void removeActivityFromActivityList(int row);
     void removeActivityFromActivityList(Activity activity);
 
-    Q_INVOKABLE void triggerActionAtIndex(int id) const;
+    Q_INVOKABLE void triggerDefaultAction(int activityIndex) const;
+    Q_INVOKABLE void triggerAction(int activityIndex, int actionIndex);
 
 public slots:
     void slotRefreshActivity();
@@ -86,6 +87,7 @@ private slots:
 
 signals:
     void activityJobStatusCode(int statusCode);
+    void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
 
 protected:
     QHash<int, QByteArray> roleNames() const override;
index 445d0a88a466f63dda653da31ab3d6a3ee912f58..98e5c1aa7875a0f1c2e262b826f9f48a072a4d1d 100644 (file)
@@ -128,7 +128,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
             al._label = QUrl::fromPercentEncoding(actionJson.value("label").toString().toUtf8());
             al._link = actionJson.value("link").toString();
             al._verb = actionJson.value("type").toString().toUtf8();
-            al._isPrimary = actionJson.value("primary").toBool();
+            al._primary = actionJson.value("primary").toBool();
 
             a._links.append(al);
         }
@@ -139,7 +139,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
         al._label = tr("Dismiss");
         al._link = Utility::concatUrlPath(ai->account()->url(), notificationsPath + "/" + QString::number(a._id)).toString();
         al._verb = "DELETE";
-        al._isPrimary = false;
+        al._primary = false;
         a._links.append(al);
 
         list.append(a);
index 9df3dd111c41b6d8cfc4579a9ce5d5daa3be9026..8e83bc936eeca283e4727bf7febe8370dbe5db50 100644 (file)
@@ -51,6 +51,8 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
     connect(this, &User::guiLog, Logger::instance(), &Logger::guiLog);
 
     connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
+
+    connect(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);
 }
 
 void User::slotBuildNotificationDisplay(const ActivityList &list)
@@ -329,7 +331,7 @@ void User::slotAddError(const QString &folderAlias, const QString &message, Erro
             link._label = tr("Retry all uploads");
             link._link = folderInstance->path();
             link._verb = "";
-            link._isPrimary = true;
+            link._primary = true;
             activity._links.append(link);
         }
 
index a007a9cb30c908376cb40a0f320952af794613ba..ac9de333f75f482f249ddca0142eb5a28c5597a3 100644 (file)
@@ -108,23 +108,11 @@ Window {
             id: trayWindowHeaderBackground\r
 \r
             anchors.left:   trayWindowBackground.left\r
+            anchors.right:  trayWindowBackground.right\r
             anchors.top:    trayWindowBackground.top\r
             height:         Style.trayWindowHeaderHeight\r
-            width:          Style.trayWindowWidth\r
             color:          Style.ncBlue\r
 \r
-            // The overlay rectangle below eliminates the rounded corners from the bottom of the header\r
-            // as Qt only allows setting the radius for all corners right now, not specific ones\r
-            Rectangle {\r
-                id: trayWindowHeaderButtomHalfBackground\r
-\r
-                anchors.left:   trayWindowHeaderBackground.left\r
-                anchors.bottom: trayWindowHeaderBackground.bottom\r
-                height:         Style.trayWindowHeaderHeight / 2\r
-                width:          Style.trayWindowWidth\r
-                color:          Style.ncBlue\r
-            }\r
-\r
             RowLayout {\r
                 id: trayWindowHeaderLayout\r
 \r
@@ -511,16 +499,17 @@ Window {
 \r
         ListView {\r
             id: activityListView\r
-\r
             anchors.top: trayWindowHeaderBackground.bottom\r
-            anchors.horizontalCenter: trayWindowBackground.horizontalCenter\r
-            width:  Style.trayWindowWidth - Style.trayWindowBorderWidth\r
-            height: Style.trayWindowHeight - Style.trayWindowHeaderHeight\r
+            anchors.left: trayWindowBackground.left\r
+            anchors.right: trayWindowBackground.right\r
+            anchors.bottom: trayWindowBackground.bottom\r
             clip: true\r
             ScrollBar.vertical: ScrollBar {\r
                 id: listViewScrollbar\r
             }\r
 \r
+            readonly property int maxActionButtons: 2\r
+\r
             keyNavigationEnabled: true\r
 \r
             Accessible.role: Accessible.List\r
@@ -531,26 +520,28 @@ Window {
             delegate: RowLayout {\r
                 id: activityItem\r
 \r
+                readonly property variant links: model.links\r
+\r
+                readonly property int itemIndex: model.index\r
+\r
                 width: parent.width\r
                 height: Style.trayWindowHeaderHeight\r
                 spacing: 0\r
 \r
                 Accessible.role: Accessible.ListItem\r
                 Accessible.name: path !== "" ? qsTr("Open %1 locally").arg(displayPath)\r
-                                                    : message\r
+                                             : message\r
                 Accessible.onPressAction: activityMouseArea.clicked()\r
 \r
                 MouseArea {\r
                     id: activityMouseArea\r
                     enabled: (path !== "" || link !== "")\r
                     anchors.left: activityItem.left\r
-                    anchors.right: (shareButton.visible) ? shareButton.left\r
-                                 : (replyButton.visible) ? replyButton.left\r
-                                 : activityItem.right\r
+                    anchors.right: activityActionsLayout.right\r
                     height: parent.height\r
                     anchors.margins: 2\r
                     hoverEnabled: true\r
-                    onClicked: activityModel.triggerActionAtIndex(model.index)\r
+                    onClicked: activityModel.triggerDefaultAction(model.index)\r
 \r
                     Rectangle {\r
                         anchors.fill: parent\r
@@ -575,13 +566,14 @@ Window {
                 Column {\r
                     id: activityTextColumn\r
                     anchors.left: activityIcon.right\r
+                    anchors.right: activityActionsLayout.left\r
                     anchors.leftMargin: 8\r
                     spacing: 4\r
                     Layout.alignment: Qt.AlignLeft\r
                     Text {\r
                         id: activityTextTitle\r
                         text: (type === "Activity" || type === "Notification") ? subject : message\r
-                        width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8\r
+                        width: parent.width\r
                         elide: Text.ElideRight\r
                         font.pixelSize: Style.topLinePixelSize\r
                         color: activityTextTitleColor\r
@@ -594,7 +586,7 @@ Window {
                             : (type === "Notification") ? message\r
                             : ""\r
                         height: (text === "") ? 0 : activityTextTitle.height\r
-                        width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8\r
+                        width: parent.width\r
                         elide: Text.ElideRight\r
                         font.pixelSize: Style.subLinePixelSize\r
                     }\r
@@ -603,7 +595,7 @@ Window {
                         id: activityTextDateTime\r
                         text: dateTime\r
                         height: (text === "") ? 0 : activityTextTitle.height\r
-                        width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8\r
+                        width: parent.width\r
                         elide: Text.ElideRight\r
                         font.pixelSize: Style.subLinePixelSize\r
                         color: "#808080"\r
@@ -624,56 +616,175 @@ Window {
                         }\r
                     }\r
                 }\r
-                Button {\r
-                    id: shareButton\r
+                RowLayout {\r
+                    id: activityActionsLayout\r
                     anchors.right: activityItem.right\r
-\r
-                    Layout.preferredWidth: (path === "") ? 0 : parent.height\r
-                    Layout.preferredHeight: parent.height\r
+                    spacing: 0\r
                     Layout.alignment: Qt.AlignRight\r
-                    flat: true\r
-                    hoverEnabled: true\r
-                    visible: (path === "") ? false : true\r
-                    display: AbstractButton.IconOnly\r
-                    icon.source: "qrc:///client/theme/share.svg"\r
-                    icon.color: "transparent"\r
-                    background: Rectangle {\r
-                        color: parent.hovered ? Style.lightHover : "transparent"\r
+\r
+                    function actionButtonIcon(actionIndex) {\r
+                        const verb = String(model.links[actionIndex].verb);\r
+                        if (verb === "WEB" && (model.objectType === "chat" || model.objectType === "call")) {\r
+                            return "qrc:///client/theme/reply.svg";\r
+                        } else if (verb === "DELETE") {\r
+                            return "qrc:///client/theme/close.svg";\r
+                        }\r
+\r
+                        return "qrc:///client/theme/confirm.svg";\r
                     }\r
-                    ToolTip.visible: hovered\r
-                    ToolTip.delay: 1000\r
-                    ToolTip.text: qsTr("Open share dialog")\r
-                    onClicked: Systray.openShareDialog(displayPath,absolutePath)\r
 \r
-                    Accessible.role: Accessible.Button\r
-                    Accessible.name: qsTr("Share %1").arg(displayPath)\r
-                    Accessible.onPressAction: shareButton.clicked()\r
-                }\r
+                    Repeater {\r
+                        model: activityItem.links.length > activityListView.maxActionButtons ? 1 : activityItem.links.length\r
 \r
-                Button {\r
-                    id: replyButton\r
-                    anchors.right: activityItem.right\r
+                        ActivityActionButton {\r
+                            id: activityActionButton\r
+\r
+                            readonly property int actionIndex: model.index\r
+                            readonly property bool primary: model.index === 0 && String(activityItem.links[actionIndex].verb) !== "DELETE"\r
+\r
+                            height: activityItem.height\r
+\r
+                            text: !primary ? "" : activityItem.links[actionIndex].label\r
+\r
+                            imageSource: !primary ? activityActionsLayout.actionButtonIcon(actionIndex) : ""\r
+\r
+                            textColor: primary ? Style.ncBlue : "black"\r
+                            textColorHovered: Style.lightHover\r
+\r
+                            textBorderColor: Style.ncBlue\r
+\r
+                            textBgColor: "transparent"\r
+                            textBgColorHovered: Style.ncBlue\r
+\r
+                            tooltipText: activityItem.links[actionIndex].label\r
+\r
+                            Layout.minimumWidth: primary ? 80 : -1\r
+                            Layout.minimumHeight: parent.height\r
+\r
+                            Layout.preferredWidth: primary ? -1 : parent.height\r
+\r
+                            onClicked: activityModel.triggerAction(activityItem.itemIndex, actionIndex)\r
+                        }\r
 \r
-                    Layout.preferredWidth: (objectType == "chat" || objectType == "call") ? parent.height : 0\r
-                    Layout.preferredHeight: parent.height\r
-                    Layout.alignment: Qt.AlignRight\r
-                    flat: true\r
-                    hoverEnabled: true\r
-                    visible: (objectType == "chat" || objectType == "call") ? true : false\r
-                    display: AbstractButton.IconOnly\r
-                    icon.source: "qrc:///client/theme/reply.svg"\r
-                    icon.color: "transparent"\r
-                    background: Rectangle {\r
-                        color: parent.hovered ? Style.lightHover : "transparent"\r
                     }\r
-                    ToolTip.visible: hovered\r
-                    ToolTip.delay: 1000\r
-                    ToolTip.text: qsTr("Open Talk")\r
-                    onClicked: Qt.openUrlExternally(link)\r
 \r
-                    Accessible.role: Accessible.Button\r
-                    Accessible.name: qsTr("Open Talk %1").arg(link)\r
-                    Accessible.onPressAction: replyButton.clicked()\r
+                    Button {\r
+                        id: moreActionsButton\r
+\r
+                        Layout.preferredWidth: parent.height\r
+                        Layout.preferredHeight: parent.height\r
+                        Layout.alignment: Qt.AlignRight\r
+\r
+                        flat: true\r
+                        hoverEnabled: true\r
+                        visible: activityItem.links.length > activityListView.maxActionButtons\r
+                        display: AbstractButton.IconOnly\r
+                        icon.source: "qrc:///client/theme/more.svg"\r
+                        icon.color: "transparent"\r
+                        background: Rectangle {\r
+                            color: parent.hovered ? Style.lightHover : "transparent"\r
+                        }\r
+                        ToolTip.visible: hovered\r
+                        ToolTip.delay: 1000\r
+                        ToolTip.text: qsTr("Show more actions")\r
+\r
+                        Accessible.role: Accessible.Button\r
+                        Accessible.name: qsTr("Show more actions")\r
+                        Accessible.onPressAction: moreActionsButton.clicked()\r
+\r
+                        onClicked:  moreActionsButtonContextMenu.popup();\r
+\r
+                        Connections {\r
+                            target: trayWindow\r
+                            onActiveChanged: {\r
+                                if (!trayWindow.active) {\r
+                                    moreActionsButtonContextMenu.close();\r
+                                }\r
+                            }\r
+                        }\r
+\r
+                        Connections {\r
+                            target: activityListView\r
+\r
+                            onMovementStarted: {\r
+                                moreActionsButtonContextMenu.close();\r
+                            }\r
+                        }\r
+\r
+                        Container {\r
+                            id: moreActionsButtonContextMenuContainer\r
+                            visible: moreActionsButtonContextMenu.opened\r
+\r
+                            width: moreActionsButtonContextMenu.width\r
+                            height: moreActionsButtonContextMenu.height\r
+                            anchors.right: moreActionsButton.right\r
+                            anchors.top: moreActionsButton.top\r
+\r
+                            Menu {\r
+                                id: moreActionsButtonContextMenu\r
+                                anchors.centerIn: parent\r
+\r
+                                // transform model to contain indexed actions with primary action filtered out\r
+                                function actionListToContextMenuList(actionList) {\r
+                                    // early out with non-altered data\r
+                                    if (activityItem.links.length <= activityListView.maxActionButtons) {\r
+                                        return actionList;\r
+                                    }\r
+\r
+                                    // add index to every action and filter 'primary' action out\r
+                                    var reducedActionList = actionList.reduce(function(reduced, action, index) {\r
+                                        if (!action.primary) {\r
+                                           var actionWithIndex = { actionIndex: index, label: action.label };\r
+                                           reduced.push(actionWithIndex);\r
+                                        }\r
+                                        return reduced;\r
+                                    }, []);\r
+\r
+\r
+                                    return reducedActionList;\r
+                                }\r
+\r
+                                Repeater {\r
+                                    id: moreActionsButtonContextMenuRepeater\r
+\r
+                                    model: moreActionsButtonContextMenu.actionListToContextMenuList(activityItem.links)\r
+\r
+                                    delegate: MenuItem {\r
+                                        id: moreActionsButtonContextMenuEntry\r
+                                        readonly property int actionIndex: model.modelData.actionIndex\r
+                                        readonly property string label: model.modelData.label\r
+                                        text: label\r
+                                        onTriggered: activityModel.triggerAction(activityItem.itemIndex, actionIndex)\r
+                                    }\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                    Button {\r
+                        id: shareButton\r
+\r
+                        Layout.preferredWidth: (path === "") ? 0 : parent.height\r
+                        Layout.preferredHeight: parent.height\r
+                        Layout.alignment: Qt.AlignRight\r
+                        flat: true\r
+                        hoverEnabled: true\r
+                        visible: (path === "") ? false : true\r
+                        display: AbstractButton.IconOnly\r
+                        icon.source: "qrc:///client/theme/share.svg"\r
+                        icon.color: "transparent"\r
+                        background: Rectangle {\r
+                            color: parent.hovered ? Style.lightHover : "transparent"\r
+                        }\r
+                        ToolTip.visible: hovered\r
+                        ToolTip.delay: 1000\r
+                        ToolTip.text: qsTr("Open share dialog")\r
+                        onClicked: Systray.openShareDialog(displayPath,absolutePath)\r
+\r
+                        Accessible.role: Accessible.Button\r
+                        Accessible.name: qsTr("Share %1").arg(displayPath)\r
+                        Accessible.onPressAction: shareButton.clicked()\r
+                    }\r
                 }\r
             }\r
 \r