--- /dev/null
+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
+ }
+}
roles[ActionRole] = "type";
roles[ActionIconRole] = "icon";
roles[ActionTextRole] = "subject";
+ roles[ActionsLinksRole] = "links";
roles[ActionTextColorRole] = "activityTextTitleColor";
roles[ObjectTypeRole] = "objectType";
roles[PointInTimeRole] = "dateTime";
}
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;
}
}
}
-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());
}
}
+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;
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
\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
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
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
: (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
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
}\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