You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

203 lines
7.4 KiB

/*
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
SPDX-FileCopyrightText: 2020 Nate Graham <nate@kde.org>
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 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaCore.ToolTipArea {
id: abstractItem
height: inVisibleLayout ? visibleLayout.cellHeight : hiddenTasks.cellHeight
width: inVisibleLayout ? visibleLayout.cellWidth : hiddenTasks.cellWidth
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
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)
// Make sure the proper item manages the keyboard
onActiveFocusChanged: {
if (activeFocus) {
iconContainer.forceActiveFocus();
}
}
/* 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 ) &&
PlasmaCore.Units.longDuration > 0
}
function startActivatedAnimation() {
activatedAnimation.start()
}
SequentialAnimation {
id: activatedAnimation
loops: 1
ScaleAnimator {
target: iconContainer
from: 1
to: 0.5
duration: PlasmaCore.Units.shortDuration
easing.type: Easing.InQuad
}
ScaleAnimator {
target: iconContainer
from: 0.5
to: 1
duration: PlasmaCore.Units.shortDuration
easing.type: Easing.OutQuad
}
}
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
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.
onPositionChanged: if (inHiddenLayout) {
root.hiddenLayout.currentIndex = index
}
onClicked: abstractItem.clicked(mouse)
onPressed: {
if (inHiddenLayout) {
root.hiddenLayout.currentIndex = index
}
abstractItem.hideImmediately()
abstractItem.pressed(mouse)
}
onPressAndHold: if (mouse.button === Qt.LeftButton) {
abstractItem.contextMenu(mouse)
}
onWheel: {
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
activeFocusOnTab: true
Accessible.name: abstractItem.text
Accessible.description: abstractItem.subText
Accessible.role: Accessible.Button
Accessible.onPressAction: abstractItem.activated(Qt.point(iconContainer.width/2, iconContainer.height/2));
Keys.onPressed: {
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 : PlasmaCore.Units.iconSizes.medium
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 ? Math.round(PlasmaCore.Units.smallSpacing * 1.5): 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 ? hiddenTasks.minLabelHeight : 0
Layout.leftMargin: abstractItem.inHiddenLayout ? PlasmaCore.Units.smallSpacing : 0
Layout.rightMargin: abstractItem.inHiddenLayout ? PlasmaCore.Units.smallSpacing : 0
Layout.bottomMargin: abstractItem.inHiddenLayout ? PlasmaCore.Units.smallSpacing : 0
visible: 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: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
}
}
}
}