Warning, /plasma/plasma-desktop/containments/panel/contents/ui/ConfigOverlay.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
0003     SPDX-FileCopyrightText: 2022 Niccolò Venerandi <niccolo@venerandi.com>
0004     SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 import QtQuick 2.5
0010 import QtQuick.Layouts 1.0
0011 import QtQuick.Window
0012 import org.kde.plasma.plasmoid 2.0
0013 import org.kde.plasma.core as PlasmaCore
0014 import org.kde.plasma.components 3.0 as PlasmaComponents3
0015 import org.kde.plasma.extras 2.0 as PlasmaExtras
0016 import org.kde.kquickcontrolsaddons 2.0
0017 import org.kde.kirigami 2.20 as Kirigami
0018 
0019 MouseArea {
0020     id: configurationArea
0021 
0022     z: 1000
0023     hoverEnabled: true
0024 
0025     property Item currentApplet
0026     property real startDragOffset: 0.0
0027 
0028     onPositionChanged: mouse => {
0029         if (pressed) {
0030 
0031             // If the object has been dragged outside of the panel and there's
0032             // a different containment there, we remove it from the panel
0033             // containment and add it to the new one.
0034             var padding = Kirigami.Units.gridUnit * 5;
0035             if (currentApplet && (mouse.x < -padding || mouse.y < -padding ||
0036                 mouse.x > width + padding || mouse.y > height + padding)) {
0037                 var newCont = root.containmentItemAt(mouse.x, mouse.y);
0038 
0039                 if (newCont && newCont !== plasmoid) {
0040                     var newPos = newCont.mapFromApplet(currentApplet.applet.plasmoid, mouse.x, mouse.y);
0041                     var applet = currentApplet.applet;
0042                     appletsModel.remove(placeHolder.parent.index);
0043                     currentApplet.destroy();
0044                     applet.anchors.fill = undefined
0045                     newCont.plasmoid.addApplet(applet.plasmoid, Qt.rect(newPos.x, newPos.y, applet.width, applet.height));
0046                     return;
0047                 }
0048             }
0049             if (Plasmoid.formFactor === PlasmaCore.Types.Vertical && currentApplet) {
0050                 currentApplet.y = mouse.y - startDragOffset;
0051             } else {
0052                 currentApplet.x = mouse.x - startDragOffset;
0053             }
0054 
0055             const item = root.layoutManager.childAtCoordinates(mouse.x, mouse.y);
0056 
0057             if (item && item.applet !== placeHolder) {
0058                 var posInItem = mapToItem(item, mouse.x, mouse.y)
0059                 var pos = root.isHorizontal ? posInItem.x : posInItem.y
0060                 var size = root.isHorizontal ? item.width : item.height
0061                 if (pos < size / 3) {
0062                     root.layoutManager.move(placeHolder.parent, item.index)
0063                 } else if (pos > size / 3 * 2) {
0064                     root.layoutManager.move(placeHolder.parent, item.index+1)
0065                 }
0066             }
0067 
0068         } else {
0069             const item = currentLayout.childAt(mouse.x, mouse.y);
0070             if (item && item !== lastSpacer) {
0071                 currentApplet = item;
0072             }
0073         }
0074 
0075         if (currentApplet) {
0076             hideTimer.stop();
0077             tooltip.raise();
0078         }
0079     }
0080 
0081     onEntered: hideTimer.stop();
0082 
0083     onExited: hideTimer.restart()
0084 
0085     onCurrentAppletChanged: {
0086         if (!currentApplet) {
0087             hideTimer.start();
0088             return;
0089         }
0090     }
0091 
0092     onPressed: mouse => {
0093         // Need to set currentApplet here too, to make touch selection + drag
0094         // with with a touchscreen, because there are no entered events in that
0095         // case
0096         let item = currentLayout.childAt(mouse.x, mouse.y);
0097         // BUG 454095: Don't allow dragging lastSpacer as it's not a real applet
0098         if (!item || item == lastSpacer || item == addWidgetsButton) {
0099             configurationArea.currentApplet = null
0100             return;
0101         }
0102         tooltip.raise();
0103         hideTimer.stop();
0104 
0105         // We set the current applet being dragged as a property of placeHolder
0106         // to be able to read its properties from the LayoutManager
0107         appletsModel.insert(item.index, {applet: placeHolder});
0108         placeHolder.parent.inThickArea = item.inThickArea
0109         currentApplet = appletContainerComponent.createObject(dropArea, {applet: item.applet, x: item.x,
0110                                                                      y: item.y, z: 900,
0111                                                                      width: item.width, height: item.height, index: -1})
0112         placeHolder.parent.dragging = currentApplet
0113         appletsModel.remove(item.index)
0114         root.dragAndDropping = true
0115 
0116         if (Plasmoid.formFactor === PlasmaCore.Types.Vertical) {
0117             startDragOffset = mouse.y - currentApplet.y;
0118         } else {
0119             startDragOffset = mouse.x - currentApplet.x;
0120         }
0121     }
0122 
0123     onReleased: mouse => finishDragOperation()
0124 
0125     onCanceled: finishDragOperation()
0126 
0127     function finishDragOperation() {
0128         root.dragAndDropping = false
0129         if (!currentApplet) {
0130             return;
0131         }
0132         appletsModel.set(placeHolder.parent.index, {applet: currentApplet.applet})
0133         let newCurrentApplet = currentApplet.applet.parent
0134         newCurrentApplet.animateFrom(currentApplet.x, currentApplet.y)
0135         newCurrentApplet.dragging = null
0136         placeHolder.parent = this
0137         currentApplet.destroy()
0138         root.layoutManager.save()
0139     }
0140 
0141     Item {
0142         id: placeHolder
0143         property Item dragging
0144         property bool busy: false
0145         visible: configurationArea.containsMouse
0146         Layout.preferredWidth: configurationArea.currentApplet?.Layout.preferredWidth ?? 0
0147         Layout.preferredHeight: configurationArea.currentApplet?.Layout.preferredHeight ?? 0
0148         Layout.maximumWidth: configurationArea.currentApplet?.Layout.maximumWidth ?? 0
0149         Layout.maximumHeight: configurationArea.currentApplet?.Layout.maximumHeight ?? 0
0150         Layout.minimumWidth: configurationArea.currentApplet?.Layout.minimumWidth ?? 0
0151         Layout.minimumHeight: configurationArea.currentApplet?.Layout.minimumHeight ?? 0
0152         Layout.fillWidth: configurationArea.currentApplet?.Layout.fillWidth ?? false
0153         Layout.fillHeight: configurationArea.currentApplet?.Layout.fillHeight ?? false
0154     }
0155 
0156     Timer {
0157         id: hideTimer
0158         interval: Kirigami.Units.longDuration * 5
0159         onTriggered: configurationArea.currentApplet = null
0160     }
0161 
0162     Rectangle {
0163         id: handle
0164 
0165         x: configurationArea.currentApplet?.x ?? 0
0166         y: configurationArea.currentApplet?.y ?? 0
0167         width: configurationArea.currentApplet?.width ?? 0
0168         height: configurationArea.currentApplet?.height ?? 0
0169 
0170         color: Kirigami.Theme.backgroundColor
0171         radius: 3
0172         opacity: configurationArea.currentApplet && configurationArea.containsMouse ? 0.5 : 0
0173 
0174         Kirigami.Icon {
0175             visible: !root.dragAndDropping
0176             source: "transform-move"
0177             width: Math.min(parent.width, parent.height)
0178             height: width
0179             anchors.centerIn: parent
0180         }
0181         Behavior on x {
0182             enabled: !configurationArea.pressed
0183             NumberAnimation {
0184                 duration: Kirigami.Units.longDuration
0185                 easing.type: Easing.InOutQuad
0186             }
0187         }
0188         Behavior on y {
0189             enabled: !configurationArea.pressed
0190             NumberAnimation {
0191                 duration: Kirigami.Units.longDuration
0192                 easing.type: Easing.InOutQuad
0193             }
0194         }
0195         Behavior on width {
0196             enabled: !configurationArea.pressed
0197             NumberAnimation {
0198                 duration: Kirigami.Units.longDuration
0199                 easing.type: Easing.InOutQuad
0200             }
0201         }
0202         Behavior on height {
0203             enabled: !configurationArea.pressed
0204             NumberAnimation {
0205                 duration: Kirigami.Units.longDuration
0206                 easing.type: Easing.InOutQuad
0207             }
0208         }
0209         Behavior on opacity {
0210             NumberAnimation {
0211                 duration: Kirigami.Units.longDuration
0212                 easing.type: Easing.InOutQuad
0213             }
0214         }
0215     }
0216     PlasmaCore.PopupPlasmaWindow {
0217         id: tooltip
0218         visible: configurationArea.currentApplet && !root.dragAndDropping
0219         visualParent: configurationArea.currentApplet
0220         // Try to dodge the ruler, as we can't cover it since it's a layershell surface
0221         margin: configurationArea.Window.window?.lengthMode === 2 ? Kirigami.Units.gridUnit * 2 : 0
0222         width: mainItem.implicitWidth + leftPadding + rightPadding
0223         height: mainItem.implicitHeight + topPadding + bottomPadding
0224 
0225         popupDirection: switch (Plasmoid.location) {
0226             case PlasmaCore.Types.TopEdge:
0227                 return Qt.BottomEdge
0228             case PlasmaCore.Types.LeftEdge:
0229                 return Qt.RightEdge
0230             case PlasmaCore.Types.RightEdge:
0231                 return Qt.LeftEdge
0232             default:
0233                 return Qt.TopEdge
0234         }
0235 
0236         onVisualParentChanged: {
0237             if (visualParent) {
0238                 const thisPlasmoid = configurationArea.currentApplet.applet.plasmoid;
0239                 thisPlasmoid.contextualActionsAboutToShow();
0240                 alternativesButton.visible = thisPlasmoid.internalAction("alternatives")?.enabled ?? false;
0241                 configureButton.visible = thisPlasmoid.internalAction("configure")?.enabled ?? false;
0242                 label.text = thisPlasmoid.title;
0243             }
0244         }
0245 
0246         mainItem: MouseArea {
0247             enabled: tooltip.visible
0248             implicitWidth: handleButtons.width
0249             implicitHeight: handleButtons.height
0250             hoverEnabled: true
0251             onEntered: hideTimer.stop();
0252             onExited:  hideTimer.restart();
0253 
0254             ColumnLayout {
0255                 id: handleButtons
0256                 spacing: Kirigami.Units.smallSpacing
0257 
0258                 PlasmaExtras.PlasmoidHeading {
0259                     leftPadding: Kirigami.Units.smallSpacing * 2
0260                     rightPadding: Kirigami.Units.smallSpacing * 2
0261 
0262                     contentItem: Kirigami.Heading {
0263                         id: label
0264                         level: 3
0265                         horizontalAlignment: Text.AlignHCenter
0266                         textFormat: Text.PlainText
0267                     }
0268                 }
0269 
0270                 PlasmaComponents3.ToolButton {
0271                     Layout.fillWidth: true
0272                     // we want destructive actions to be far from the initial
0273                     // cursor position, so show this on the top unless it's on
0274                     // a top panel
0275                     visible: tooltip.location !== PlasmaCore.Types.TopEdge
0276                              && (configurationArea.currentApplet?.applet.plasmoid.internalAction("remove")?.enabled ?? false)
0277                     icon.name: "delete"
0278                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Remove")
0279                     onClicked: {
0280                         configurationArea.currentApplet.applet.plasmoid.internalAction("remove").trigger();
0281                         configurationArea.currentApplet = null;
0282                     }
0283                 }
0284                 PlasmaComponents3.ToolButton {
0285                     id: configureButton
0286                     Layout.fillWidth: true
0287                     icon.name: "configure"
0288                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Configure…")
0289                     visible: configurationArea.currentApplet.applet.plasmoid.hasConfigurationInterface
0290                     onClicked: {
0291                         configurationArea.currentApplet.applet.plasmoid.internalAction("configure").trigger();
0292                         configurationArea.currentApplet = null;
0293                     }
0294                 }
0295                 PlasmaComponents3.ToolButton {
0296                     id: alternativesButton
0297                     Layout.fillWidth: true
0298                     icon.name: "widget-alternatives"
0299                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Show Alternatives…")
0300                     onClicked: {
0301                         configurationArea.currentApplet.applet.plasmoid.internalAction("alternatives").trigger();
0302                         configurationArea.currentApplet = null;
0303                     }
0304                 }
0305                 PlasmaComponents3.ToolButton {
0306                     Layout.fillWidth: true
0307                     // we want destructive actions to be far from the initial
0308                     // cursor position, so show this on the bottom for top panels
0309                     visible: tooltip.location === PlasmaCore.Types.TopEdge
0310                              && (configurationArea.currentApplet?.applet.plasmoid.internalAction("remove")?.enabled ?? false)
0311                     icon.name: "delete"
0312                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Remove")
0313                     onClicked: {
0314                         configurationArea.currentApplet.applet.plasmoid.internalAction("remove").trigger();
0315                         configurationArea.currentApplet = null;
0316                     }
0317                 }
0318 
0319                 Kirigami.Heading {
0320                     Layout.fillWidth: true
0321                     visible: panelSpacerWidth.visible
0322                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Spacer width")
0323                     textFormat: Text.PlainText
0324                     level: 3
0325                     horizontalAlignment: Text.AlignHCenter
0326                 }
0327 
0328                 PlasmaComponents3.SpinBox {
0329                     id: panelSpacerWidth
0330                     editable: true
0331                     Layout.fillWidth: true
0332                     focus: !Kirigami.InputMethod.willShowOnActive
0333                     visible: configurationArea.currentApplet?.applet.plasmoid.pluginName === "org.kde.plasma.panelspacer"
0334                         && !configurationArea.currentApplet.applet.plasmoid.configuration.expanding
0335                     from: 0
0336                     stepSize: 10
0337                     to: root.width
0338                     value: configurationArea.currentApplet?.applet.plasmoid.configuration.length ?? 0
0339                     onValueModified: {
0340                         configurationArea.currentApplet.applet.plasmoid.configuration.length = value
0341                     }
0342                 }
0343             }
0344         }
0345     }
0346 }