Very early KDE 6 release.

This commit is contained in:
wackyideas 2024-08-09 03:20:25 +02:00
parent 7cc4ccabbc
commit 686046d4f7
6272 changed files with 140920 additions and 529657 deletions

View file

@ -0,0 +1,257 @@
/*
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 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
}
}
}
}
}

View file

@ -0,0 +1,31 @@
/*
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.0
Loader {
id: itemLoader
property real minLabelHeight: 0
z: x+1 // always be above what it's on top of, even for x==0
property var itemModel: model
Binding {
target: item
property: "minLabelHeight"
value: itemLoader.minLabelHeight
}
source: {
if (model.itemType === "Plasmoid" && model.hasApplet) {
return Qt.resolvedUrl("PlasmoidItem.qml")
} else if (model.itemType === "StatusNotifier") {
return Qt.resolvedUrl("StatusNotifierItem.qml")
}
console.warn("SystemTray ItemLoader: Invalid state, cannot determine source!")
return ""
}
}

View file

@ -0,0 +1,185 @@
/*
SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.15
import QtQml 2.15
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
AbstractItem {
id: plasmoidContainer
property Item applet: model.applet || null
text: applet ? applet.plasmoid.title : ""
itemId: applet ? applet.plasmoid.pluginName : ""
mainText: applet ? applet.toolTipMainText : ""
subText: applet ? applet.toolTipSubText : ""
mainItem: applet && applet.toolTipItem ? applet.toolTipItem : null
textFormat: applet ? applet.toolTipTextFormat : 0 /* Text.AutoText, the default value */
active: systemTrayState.activeApplet !== applet
// FIXME: Use an input type agnostic way to activate whatever the primary
// action of a plasmoid is supposed to be, even if it's just expanding the
// Plasmoid. Not all plasmoids are supposed to expand and not all plasmoids
// do anything with onActivated.
onActivated: {
if (applet) {
applet.plasmoid.activated()
}
}
onClicked: mouse => {
if (!applet) {
return
}
//forward click event to the applet
var appletItem = applet.compactRepresentationItem ?? applet.fullRepresentationItem
const mouseArea = findMouseArea(appletItem)
if (mouseArea && mouse.button !== Qt.RightButton) {
var temp = applet.expanded;
mouseArea.clicked(mouse);
if(mouse.button === Qt.LeftButton && inVisibleLayout && applet.expanded && temp) {
applet.expanded = false;
}
} else if (mouse.button === Qt.LeftButton) {//fallback
activated(null)
}
}
onPressed: mouse => {
// Only Plasmoids can show context menu on the mouse pressed event.
// SNI has few problems, for example legacy applications that still use XEmbed require mouse to be released.
if (mouse.button === Qt.RightButton) {
contextMenu(mouse);
} /*else {
const appletItem = applet.compactRepresentationItem ?? applet.fullRepresentationItem
const mouseArea = findMouseArea(appletItem)
}*/
}
onContextMenu: if (applet) {
effectivePressed = false;
Plasmoid.showPlasmoidMenu(applet, 0, inHiddenLayout ? applet.height : 0);
}
onWheel: (wheel) => {
if (!applet) {
return
}
//forward wheel event to the applet
var appletItem = applet.compactRepresentationItem ?? applet.fullRepresentationItem
const mouseArea = findMouseArea(appletItem)
if (mouseArea) {
mouseArea.wheel(wheel)
}
}
//some heuristics to find MouseArea
function findMouseArea(item: Item): MouseArea {
if (!item) {
return null
}
if (item instanceof MouseArea) {
return item
}
for (var i = 0; i < item.children.length; i++) {
const child = item.children[i]
if (child instanceof MouseArea && child.enabled) {
//check if MouseArea covers the entire item
if (child.anchors.fill === item || (child.x === 0 && child.y === 0 && child.height === item.height && child.width === item.width)) {
return child
}
}
}
return null
}
//This is to make preloading effective, minimizes the scene changes
function preloadFullRepresentationItem(fullRepresentationItem) {
if (fullRepresentationItem && fullRepresentationItem.parent === null) {
fullRepresentationItem.width = expandedRepresentation.width
fullRepresentationItem.height = expandedRepresentation.height
fullRepresentationItem.parent = preloadedStorage;
}
}
onAppletChanged: {
if (applet) {
applet.parent = iconContainer
applet.anchors.fill = applet.parent
applet.visible = true
preloadFullRepresentationItem(applet.fullRepresentationItem)
}
}
Connections {
enabled: plasmoidContainer.applet !== null
target: findMouseArea(
plasmoidContainer.applet?.compactRepresentationItem ??
plasmoidContainer.applet?.fullRepresentationItem ??
plasmoidContainer.applet
)
function onContainsPressChanged() {
plasmoidContainer.effectivePressed = target.containsPress;
}
// TODO For touch/stylus only, since the feature is not desired for mouse users
function onPressAndHold(mouse) {
if (mouse.button === Qt.LeftButton) {
plasmoidContainer.contextMenu(mouse)
}
}
}
Connections {
target: plasmoidContainer.applet?.plasmoid ?? null
//activation using global keyboard shortcut
function onActivated() {
plasmoidContainer.effectivePressed = true;
Qt.callLater(() => {
plasmoidContainer.effectivePressed = false;
});
}
}
Connections {
target: plasmoidContainer.applet
function onFullRepresentationItemChanged(fullRepresentationItem) {
preloadFullRepresentationItem(fullRepresentationItem)
}
function onExpandedChanged(expanded) {
if (expanded) {
systemTrayState.setActiveApplet(plasmoidContainer.applet, model.row)
effectivePressed = false;
}
}
}
/*PlasmaComponents3.BusyIndicator {
anchors.fill: parent
z: 999
running: plasmoidContainer.applet?.plasmoid.busy ?? false
}*/
Binding {
property: "hideOnWindowDeactivate"
value: !Plasmoid.configuration.pin
target: plasmoidContainer.applet
when: plasmoidContainer.applet !== null
restoreMode: Binding.RestoreBinding
}
}

View file

@ -0,0 +1,40 @@
/*
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.2
import org.kde.kirigami 2.20 as Kirigami
SequentialAnimation {
id: pulseAnimation
objectName: "pulseAnimation"
property Item targetItem
readonly property int duration: Kirigami.Units.veryLongDuration * 5
loops: Animation.Infinite
alwaysRunToEnd: true
ScaleAnimator {
target: targetItem
from: 1
to: 1.2
duration: pulseAnimation.duration * 0.15
easing.type: Easing.InQuad
}
ScaleAnimator {
target: targetItem
from: 1.2
to: 1
duration: pulseAnimation.duration * 0.15
easing.type: Easing.InQuad
}
PauseAnimation {
duration: pulseAnimation.duration * 0.7
}
}

View file

@ -0,0 +1,112 @@
/*
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.kirigami 2.20 as Kirigami
AbstractItem {
id: taskIcon
itemId: model.Id
text: model.Title || model.ToolTipTitle
mainText: model.ToolTipTitle !== "" ? model.ToolTipTitle : model.Title
subText: model.ToolTipSubTitle
textFormat: Text.AutoText
Kirigami.Icon {
id: iconItem
parent: taskIcon.iconContainer
anchors.fill: iconItem.parent
source: {
if (model.status === PlasmaCore.Types.NeedsAttentionStatus) {
if (model.AttentionIcon) {
return model.AttentionIcon
}
if (model.AttentionIconName) {
return model.AttentionIconName
}
}
return model.Icon || model.IconName
}
active: taskIcon.containsMouse
}
onActivated: pos => {
const service = model.Service;
const operation = service.operationDescription("Activate");
operation.x = pos.x; //mouseX
operation.y = pos.y; //mouseY
const job = service.startOperationCall(operation);
job.finished.connect(() => {
if (!job.result) {
// On error try to invoke the context menu.
// Workaround primarily for apps using libappindicator.
openContextMenu(pos);
}
})
}
onContextMenu: mouse => {
if (mouse === null) {
openContextMenu(Plasmoid.popupPosition(taskIcon, taskIcon.width / 2, taskIcon.height / 2));
} else {
openContextMenu(Plasmoid.popupPosition(taskIcon, mouse.x, mouse.y));
}
}
onClicked: mouse => {
var pos = Plasmoid.popupPosition(taskIcon, mouse.x, mouse.y);
switch (mouse.button) {
case Qt.LeftButton:
taskIcon.activated(pos)
break;
case Qt.RightButton:
openContextMenu(pos);
break;
case Qt.MiddleButton:
const service = model.Service;
const operation = service.operationDescription("SecondaryActivate");
operation.x = pos.x;
operation.y = pos.y;
service.startOperationCall(operation);
break;
}
}
function openContextMenu(pos = Qt.point(width/2, height/2)) {
const service = model.Service;
const operation = service.operationDescription("ContextMenu");
operation.x = pos.x;
operation.y = pos.y;
const job = service.startOperationCall(operation);
job.finished.connect(() => {
Plasmoid.showStatusNotifierContextMenu(job, taskIcon);
});
}
onWheel: wheel => {
//don't send activateVertScroll with a delta of 0, some clients seem to break (kmix)
if (wheel.angleDelta.y !== 0) {
const service = model.Service;
const operation = service.operationDescription("Scroll");
operation.delta = wheel.angleDelta.y;
operation.direction = "Vertical";
service.startOperationCall(operation);
}
if (wheel.angleDelta.x !== 0) {
const service = model.Service;
const operation = service.operationDescription("Scroll");
operation.delta = wheel.angleDelta.x;
operation.direction = "Horizontal";
service.startOperationCall(operation);
}
}
}