/* SPDX-FileCopyrightText: 2016 Marco Martin SPDX-FileCopyrightText: 2020 Konrad Materka SPDX-FileCopyrightText: 2020 Nate Graham SPDX-License-Identifier: LGPL-2.0-or-later */ import QtQuick 2.2 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core as PlasmaCore import org.kde.plasma.components 3.0 as PlasmaComponents3 import org.kde.kirigami 2.20 as Kirigami import org.kde.ksvg 1.0 as KSvg PlasmaCore.ToolTipArea { id: abstractItem property var model: itemModel property string itemId property alias text: label.text property alias labelHeight: label.implicitHeight property alias iconContainer: iconContainer property int /*PlasmaCore.Types.ItemStatus*/ status: model.status || PlasmaCore.Types.UnknownStatus property int /*PlasmaCore.Types.ItemStatus*/ effectiveStatus: model.effectiveStatus || PlasmaCore.Types.UnknownStatus property bool effectivePressed: false property real minLabelHeight: 0 readonly property bool inHiddenLayout: effectiveStatus === PlasmaCore.Types.PassiveStatus readonly property bool inVisibleLayout: effectiveStatus === PlasmaCore.Types.ActiveStatus // input agnostic way to trigger the main action signal activated(var pos) // proxy signals for MouseArea signal clicked(var mouse) signal pressed(var mouse) signal wheel(var wheel) signal contextMenu(var mouse) /* subclasses need to assign to this tooltip properties mainText: subText: */ location: { if (inHiddenLayout) { if (LayoutMirroring.enabled && Plasmoid.location !== PlasmaCore.Types.RightEdge) { return PlasmaCore.Types.LeftEdge; } else if (Plasmoid.location !== PlasmaCore.Types.LeftEdge) { return PlasmaCore.Types.RightEdge; } } return Plasmoid.location; } /*PulseAnimation { targetItem: iconContainer running: (abstractItem.status === PlasmaCore.Types.NeedsAttentionStatus || abstractItem.status === PlasmaCore.Types.RequiresAttentionStatus) && Kirigami.Units.longDuration > 0 }*/ KSvg.FrameSvgItem { id: itemHighLight anchors.fill: parent //property int location property bool animationEnabled: true property var highlightedItem: null z: -1 // always draw behind icons opacity: mouseArea.containsMouse ? 1 : 0 imagePath: Qt.resolvedUrl("../svgs/tabbar.svgz") //imagePath: "widgets/tabbar" prefix: { var prefix = "" switch (Plasmoid.location) { case PlasmaCore.Types.LeftEdge: prefix = "west-active-tab"; break; case PlasmaCore.Types.TopEdge: prefix = "north-active-tab"; break; case PlasmaCore.Types.RightEdge: prefix = "east-active-tab"; break; default: prefix = "south-active-tab"; } if (!hasElementPrefix(prefix)) { prefix = "active-tab"; } return prefix; } Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } Rectangle { id: pressRect property alias activatedPress: pressRect.opacity anchors.fill: parent anchors.leftMargin: Kirigami.Units.smallSpacing / 2; // We don't want the rectangle to draw over the highlight texture itself. anchors.rightMargin: Kirigami.Units.smallSpacing / 2; gradient: Gradient { // The first and last gradient stops are offset by +/-0.1 to avoid a sudden gradient "cutoff". GradientStop { position: 0.1; color: "transparent"; } GradientStop { position: 0.5; color: "#66000000"; } GradientStop { position: 0.9; color: "transparent"; } } opacity: mouseArea.containsPress ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 150; easing.type: Easing.InOutQuad } } } } MouseArea { id: mouseArea propagateComposedEvents: true // This needs to be above applets when it's in the grid hidden area // so that it can receive hover events while the mouse is over an applet, // but below them on regular systray, so collapsing works //z: inHiddenLayout ? 1 : 0 z: 1 anchors.fill: abstractItem hoverEnabled: true drag.filterChildren: true // Necessary to make the whole delegate area forward all mouse events acceptedButtons: Qt.AllButtons // Using onPositionChanged instead of onEntered because changing the // index in a scrollable view also changes the view position. // onEntered will change the index while the items are scrolling, // making it harder to scroll. onContainsMouseChanged: { if(inHiddenLayout && !mouseArea.containsMouse) { root.hiddenLayout.currentIndex = -1; } } onPositionChanged: if (inHiddenLayout) { root.hiddenLayout.currentIndex = index } onClicked: mouse => { abstractItem.clicked(mouse) } onPressed: mouse => { if (inHiddenLayout) { root.hiddenLayout.currentIndex = index } abstractItem.hideImmediately() abstractItem.pressed(mouse) } onPressAndHold: mouse => { if (mouse.button === Qt.LeftButton) { abstractItem.contextMenu(mouse) } } onWheel: wheel => { abstractItem.wheel(wheel); //Don't accept the event in order to make the scrolling by mouse wheel working //for the parent scrollview this icon is in. wheel.accepted = false; } } ColumnLayout { anchors.fill: abstractItem spacing: 0 FocusScope { id: iconContainer //scale: (abstractItem.effectivePressed || mouseArea.containsPress) ? 0.8 : 1 Kirigami.Theme.colorSet: abstractItem.inHiddenLayout ? Kirigami.Theme.Tooltip : Kirigami.Theme.Window Kirigami.Theme.inherit: false activeFocusOnTab: true focus: true // Required in HiddenItemsView so keyboard events can be forwarded to this item Accessible.name: abstractItem.text Accessible.description: abstractItem.subText Accessible.role: Accessible.Button Accessible.onPressAction: abstractItem.activated(Plasmoid.popupPosition(iconContainer, iconContainer.width/2, iconContainer.height/2)); /*Behavior on scale { ScaleAnimator { duration: Kirigami.Units.longDuration easing.type: (effectivePressed || mouseArea.containsPress) ? Easing.OutCubic : Easing.InCubic } }*/ Keys.onPressed: event => { switch (event.key) { case Qt.Key_Space: case Qt.Key_Enter: case Qt.Key_Return: case Qt.Key_Select: abstractItem.activated(Qt.point(width/2, height/2)); break; case Qt.Key_Menu: abstractItem.contextMenu(null); event.accepted = true; break; } } property alias container: abstractItem property alias inVisibleLayout: abstractItem.inVisibleLayout readonly property int size: abstractItem.inVisibleLayout ? root.itemSize : Kirigami.Units.iconSizes.small Layout.alignment: Qt.Bottom | Qt.AlignHCenter Layout.fillHeight: abstractItem.inHiddenLayout ? true : false implicitWidth: root.vertical && abstractItem.inVisibleLayout ? abstractItem.width : size implicitHeight: !root.vertical && abstractItem.inVisibleLayout ? abstractItem.height : size //Layout.topMargin: abstractItem.inHiddenLayout ? Kirigami.Units.mediumSpacing : 0 } PlasmaComponents3.Label { id: label Layout.fillWidth: true Layout.fillHeight: abstractItem.inHiddenLayout ? true : false //! Minimum required height for all labels is used in order for all //! labels to be aligned properly at all items. At the same time this approach does not //! enforce labels with 3 lines at all cases so translations that require only one or two //! lines will always look consistent with no too much padding Layout.minimumHeight: abstractItem.inHiddenLayout ? abstractItem.minLabelHeight : 0 Layout.leftMargin: abstractItem.inHiddenLayout ? Kirigami.Units.smallSpacing : 0 Layout.rightMargin: abstractItem.inHiddenLayout ? Kirigami.Units.smallSpacing : 0 Layout.bottomMargin: abstractItem.inHiddenLayout ? Kirigami.Units.smallSpacing : 0 visible: false //abstractItem.inHiddenLayout verticalAlignment: Text.AlignTop horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight wrapMode: Text.Wrap maximumLineCount: 3 opacity: visible ? 1 : 0 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } } } }