Warning, /plasma/kdeplasma-addons/applets/notes/package/contents/ui/main.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2014 David Edmundson <davidedmundson@kde.org>
0003     SPDX-FileCopyrightText: 2014, 2015 Kai Uwe Broulik <kde@privat.broulik.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 import QtQuick
0009 import QtQuick.Controls as QQC2 // just for desktop-styled context menus
0010 import QtQuick.Layouts
0011 import QtQuick.Window
0012 import QtQuick.Dialogs
0013 
0014 import org.kde.draganddrop 2.0 as DragDrop
0015 
0016 import org.kde.plasma.core as PlasmaCore
0017 import org.kde.kirigami 2.20 as Kirigami
0018 import org.kde.ksvg 1.0 as KSvg
0019 import org.kde.plasma.components 3.0 as PlasmaComponents3
0020 import org.kde.plasma.extras 2.0 as PlasmaExtras
0021 import org.kde.plasma.plasmoid 2.0
0022 
0023 import org.kde.plasma.private.notes 0.1
0024 
0025 PlasmoidItem {
0026     id: root
0027 
0028     switchWidth: Kirigami.Units.gridUnit * 5
0029     switchHeight: Kirigami.Units.gridUnit * 5
0030 
0031     Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground
0032 
0033     // this isn't a frameSVG, the default SVG margins take up around 7% of the frame size, so we use that
0034     readonly property real horizontalMargins: fullRepresentationItem.width * 0.07
0035     readonly property real verticalMargins: fullRepresentationItem.height * 0.07
0036     readonly property PlasmaComponents3.TextArea mainTextArea: fullRepresentationItem.mainTextArea
0037 
0038     // note is of type Note
0039     property QtObject note: noteManager.loadNote(Plasmoid.configuration.noteId);
0040 
0041     // define colors used for icons in ToolButtons and for text in TextArea.
0042     // this is deliberately _NOT_ the theme color as we are over a known bright background!
0043     // an unknown colour over a known colour is a bad move as you end up with white on yellow.
0044     readonly property color textIconColor: {
0045         if (Plasmoid.configuration.color === "black" || Plasmoid.configuration.color === "translucent-light") {
0046             return "#dfdfdf";
0047         }
0048         return "#202020";
0049     }
0050 
0051     onExternalData: (mimetype, data) => {
0052         // if we dropped a text file, we want its contents,
0053         // otherwise we take the external data verbatim
0054         var contents = NotesHelper.fileContents(data) || data
0055         mainTextArea.text = String(contents).replace(/\n/g, "<br>") // what about richtext?
0056 
0057         // place cursor at the end of text, there's no "just move the cursor" function
0058         mainTextArea.moveCursorSelection(mainTextArea.length)
0059         mainTextArea.deselect()
0060     }
0061 
0062     Timer {
0063         id: forceFocusTimer
0064         interval: 1
0065         onTriggered: mainTextArea.forceActiveFocus()
0066     }
0067 
0068     Connections {
0069         target: Plasmoid
0070         function onActivated() {
0071             // FIXME doing forceActiveFocus here directly doesn't work
0072             forceFocusTimer.restart()
0073         }
0074     }
0075 
0076     NoteManager {
0077         id: noteManager
0078     }
0079 
0080     // Only exists because the default CompactRepresentation doesn't open on drag.
0081     // TODO remove once it gains that feature (perhaps optionally?)
0082     compactRepresentation: DragDrop.DropArea {
0083         id: compactDropArea
0084         onDragEnter: activationTimer.restart()
0085         onDragLeave: activationTimer.stop()
0086 
0087         Timer {
0088             id: activationTimer
0089             interval: 250 // matches taskmanager delay
0090             onTriggered: root.expanded = true
0091         }
0092 
0093         MouseArea {
0094             anchors.fill: parent
0095             hoverEnabled: true
0096 
0097             property bool wasExpanded
0098 
0099             onPressed: wasExpanded = root.expanded
0100             onClicked: root.expanded = !wasExpanded
0101 
0102             Kirigami.Icon {
0103                 anchors.fill: parent
0104                 source: "knotes-symbolic"
0105                 active: parent.containsMouse
0106             }
0107         }
0108     }
0109 
0110     preloadFullRepresentation: true
0111     fullRepresentation: KSvg.SvgItem {
0112         id: backgroundItem
0113 
0114         property alias mainTextArea: mainTextArea
0115         Layout.preferredWidth: Kirigami.Units.gridUnit * 25
0116         Layout.preferredHeight: Kirigami.Units.gridUnit * 25
0117         Layout.minimumWidth: Kirigami.Units.gridUnit * 2
0118         Layout.minimumHeight: Kirigami.Units.gridUnit * 2
0119 
0120         imagePath: "widgets/notes"
0121         elementId: Plasmoid.configuration.color + "-notes"
0122 
0123         DocumentHandler {
0124             id: documentHandler
0125             target: mainTextArea
0126             cursorPosition: mainTextArea.cursorPosition
0127             selectionStart: mainTextArea.selectionStart
0128             selectionEnd: mainTextArea.selectionEnd
0129             defaultFontSize: Plasmoid.configuration.fontSize
0130         }
0131 
0132         Connections {
0133             target: root
0134             function onExpandedChanged(expanded) {
0135                 // don't autofocus when we're on the desktop
0136                 if (expanded && (Plasmoid.formFactor === PlasmaCore.Types.Vertical || Plasmoid.formFactor === PlasmaCore.Types.Horizontal)) {
0137                     mainTextArea.forceActiveFocus()
0138                 }
0139             }
0140         }
0141         Component.onDestruction: {
0142             note.save(mainTextArea.text);
0143         }
0144 
0145         FocusScope {
0146             id: focusScope
0147             anchors {
0148                 fill: parent
0149                 leftMargin: horizontalMargins
0150                 rightMargin: horizontalMargins
0151                 topMargin: verticalMargins
0152                 bottomMargin: verticalMargins
0153             }
0154 
0155             PlasmaComponents3.ScrollView {
0156                 id: scrollview
0157                 anchors {
0158                     top: parent.top
0159                     left: parent.left
0160                     right: parent.right
0161                     bottom: fontButtons.top
0162                     bottomMargin: Kirigami.Units.largeSpacing
0163                 }
0164 
0165                 clip: true
0166 
0167                 PlasmaComponents3.TextArea {
0168                     id: mainTextArea
0169                     property int cfgFontPointSize: Plasmoid.configuration.fontSize
0170 
0171                     textFormat: TextEdit.RichText
0172                     onLinkActivated: Qt.openUrlExternally(link)
0173                     background: null
0174                     color: textIconColor
0175                     persistentSelection: true
0176                     wrapMode: TextEdit.Wrap
0177 
0178                     font.pointSize: cfgFontPointSize
0179 
0180                     Keys.onPressed: event => {
0181                         if (event.key === Qt.Key_Escape) {
0182                             root.expanded = false;
0183                             event.accepted = true;
0184                         } else if (event.modifiers === Qt.ControlModifier) {
0185                             if (event.key === Qt.Key_B) {
0186                                 documentHandler.bold = !documentHandler.bold;
0187                                 event.accepted = true;
0188                             } else if (event.key === Qt.Key_I) {
0189                                 documentHandler.italic = !documentHandler.italic;
0190                                 event.accepted = true;
0191                             } else if (event.key === Qt.Key_U) {
0192                                 documentHandler.underline = !documentHandler.underline;
0193                                 event.accepted = true;
0194                             } else if (event.key === Qt.Key_S) {
0195                                 documentHandler.strikeOut = !documentHandler.strikeOut;
0196                                 event.accepted = true;
0197                             } else if (event.matches(StandardKey.Paste)) {
0198                                 documentHandler.pasteWithoutFormatting();
0199                                 documentHandler.reset();
0200                                 event.accepted = true;
0201                             } else if (event.matches(StandardKey.Cut)) {
0202                                 cut();
0203                                 documentHandler.reset();
0204                                 event.accepted = true;
0205                             }
0206                         }
0207                     }
0208 
0209                     // Apply the font size change to existing texts
0210                     onCfgFontPointSizeChanged: {
0211                         const start = selectionStart;
0212                         const end = selectionEnd;
0213 
0214                         selectAll();
0215                         documentHandler.fontSize = cfgFontPointSize;
0216                         select(start, end);
0217                     }
0218 
0219                     // update the note if the source changes, but only if the user isn't editing it currently
0220                     Binding {
0221                         target: mainTextArea
0222                         property: "text"
0223                         value: note.noteText
0224                         when: !mainTextArea.activeFocus
0225                         // don't restore an empty value (which IS empty by default when the applet starts up),
0226                         // instead only remove this binding for the time when the user edits the content.
0227                         restoreMode: Binding.RestoreBinding
0228                     }
0229 
0230                     onActiveFocusChanged: {
0231                         const window = Window.window;
0232                         if (activeFocus && window && (window.flags & Qt.WindowDoesNotAcceptFocus)) {
0233                             Plasmoid.status = PlasmaCore.Types.AcceptingInputStatus
0234                         } else {
0235                             Plasmoid.status = PlasmaCore.Types.ActiveStatus
0236                             note.save(text);
0237                         }
0238                     }
0239 
0240                     onPressed: event => {
0241                         if (event.button === Qt.RightButton) {
0242                             event.accepted = true;
0243                             contextMenu.popup();
0244                             forceActiveFocus();
0245                         }
0246                         if (event.button === Qt.LeftButton && contextMenu.visible === true) {
0247                             event.accepted = true;
0248                             contextMenu.dismiss();
0249                             forceActiveFocus();
0250                         }
0251                     }
0252 
0253                     Component.onCompleted: {
0254                         if (!Plasmoid.configuration.fontSize) {
0255                             // Set fontSize to default if it is not set
0256                             Plasmoid.configuration.fontSize = font.pointSize
0257                         }
0258                     }
0259 
0260                     QQC2.Menu {
0261                         id: contextMenu
0262 
0263                         ShortcutMenuItem {
0264                             _sequence: StandardKey.Undo
0265                             _enabled: mainTextArea.canUndo
0266                             _iconName: "edit-undo"
0267                             _text: i18n("Undo")
0268                             onTriggered: contextMenu.retFocus(() => mainTextArea.undo())
0269                         }
0270 
0271                         ShortcutMenuItem {
0272                             _sequence: StandardKey.Redo
0273                             _enabled: mainTextArea.canRedo
0274                             _iconName: "edit-redo"
0275                             _text: i18n("Redo")
0276                             onTriggered: contextMenu.retFocus(() => mainTextArea.redo())
0277                         }
0278 
0279                         QQC2.MenuSeparator {}
0280 
0281                         ShortcutMenuItem {
0282                             _sequence: StandardKey.Cut
0283                             _enabled: mainTextArea.selectedText.length > 0
0284                             _iconName: "edit-cut"
0285                             _text: i18n("Cut")
0286                             onTriggered: contextMenu.retFocus(() => mainTextArea.cut())
0287                         }
0288 
0289                         ShortcutMenuItem {
0290                             _sequence: StandardKey.Copy
0291                             _enabled: mainTextArea.selectedText.length > 0
0292                             _iconName: "edit-copy"
0293                             _text: i18n("Copy")
0294                             onTriggered: contextMenu.retFocus(() => mainTextArea.copy())
0295                         }
0296 
0297                         ShortcutMenuItem {
0298                             _sequence: StandardKey.Paste
0299                             _enabled: mainTextArea.canPaste
0300                             _iconName: "edit-paste"
0301                             _text: i18n("Paste")
0302                             onTriggered: contextMenu.retFocus(() => documentHandler.pasteWithoutFormatting())
0303                         }
0304 
0305                         ShortcutMenuItem {
0306                             _enabled: mainTextArea.canPaste
0307                             _text: i18n("Paste with Full Formatting")
0308                             _iconName: "edit-paste"
0309                             onTriggered: contextMenu.retFocus(() => mainTextArea.paste())
0310                         }
0311 
0312                         ShortcutMenuItem {
0313                             _enabled: mainTextArea.selectedText.length > 0
0314                             _text: i18nc("@action:inmenu", "Remove Formatting")
0315                             _iconName: "edit-clear-all"
0316                             onTriggered: {
0317                                 var richText = mainTextArea.getFormattedText(mainTextArea.selectionStart, mainTextArea.selectionEnd)
0318                                 var unformattedText = documentHandler.strip(richText)
0319                                 unformattedText = unformattedText.replace(/\n/g, "<br>")
0320                                 mainTextArea.remove(mainTextArea.selectionStart, mainTextArea.selectionEnd)
0321                                 contextMenu.retFocus(() => mainTextArea.insert(mainTextArea.selectionStart, unformattedText))
0322                             }
0323                         }
0324 
0325                         ShortcutMenuItem {
0326                             _sequence: StandardKey.Delete
0327                             _enabled: mainTextArea.selectedText.length > 0
0328                             _iconName: "edit-delete"
0329                             _text: i18n("Delete")
0330                             onTriggered: contextMenu.retFocus(() => mainTextArea.remove(mainTextArea.selectionStart, mainTextArea.selectionEnd))
0331                         }
0332 
0333                         ShortcutMenuItem {
0334                             _enabled: mainTextArea.text.length > 0
0335                             _iconName: "edit-clear"
0336                             _text: i18n("Clear")
0337                             onTriggered: contextMenu.retFocus(() => mainTextArea.clear())
0338                         }
0339 
0340                         QQC2.MenuSeparator {}
0341 
0342                         ShortcutMenuItem {
0343                             _sequence: StandardKey.SelectAll
0344                             _enabled: mainTextArea.text.length > 0
0345                             _iconName: "edit-select-all"
0346                             _text: i18n("Select All")
0347                             onTriggered: contextMenu.retFocus(() => mainTextArea.selectAll())
0348                         }
0349 
0350                         function retFocus(f) {
0351                             f()
0352                             documentHandler.reset()
0353                             mainTextArea.forceActiveFocus()
0354                         }
0355                     }
0356                 }
0357 
0358                 // Save scrolling position when it changes, but throttle to avoid
0359                 // killing a storage disk.
0360                 Connections {
0361                     target: scrollview.contentItem
0362                     function onContentXChanged() {
0363                         throttedScrollSaver.restart();
0364                     }
0365                     function onContentYChanged() {
0366                         throttedScrollSaver.restart();
0367                     }
0368                 }
0369                 Connections {
0370                     target: mainTextArea
0371                     function onCursorPositionChanged() {
0372                         throttedScrollSaver.restart();
0373                     }
0374                 }
0375 
0376                 Timer {
0377                     id: throttedScrollSaver
0378                     interval: Kirigami.Units.humanMoment
0379                     repeat: false
0380                     running: false
0381                     onTriggered: scrollview.saveScroll()
0382                 }
0383 
0384                 function saveScroll() {
0385                     const flickable = scrollview.contentItem;
0386                     Plasmoid.configuration.scrollX = flickable.contentX;
0387                     Plasmoid.configuration.scrollY = flickable.contentY;
0388                     Plasmoid.configuration.cursorPosition = mainTextArea.cursorPosition;
0389                 }
0390 
0391                 function restoreScroll() {
0392                     const flickable = scrollview.contentItem;
0393                     flickable.contentX = Plasmoid.configuration.scrollX;
0394                     flickable.contentY = Plasmoid.configuration.scrollY;
0395                     mainTextArea.cursorPosition = Plasmoid.configuration.cursorPosition;
0396                 }
0397 
0398                 // Give it some time to lay out the text, because at this
0399                 // point in time content size is not reliable yet.
0400                 Component.onCompleted: Qt.callLater(restoreScroll)
0401                 Component.onDestruction: saveScroll()
0402             }
0403 
0404             DragDrop.DropArea {
0405                 id: dropArea
0406                 anchors.fill: scrollview
0407 
0408                 function positionOfDrop(event) {
0409                     return mainTextArea.positionAt(event.x, event.y)
0410                 }
0411 
0412                 onDrop: {
0413                     var mimeData = event.mimeData
0414                     var text = ""
0415                     if (mimeData.hasUrls) {
0416                         var urls = mimeData.urls
0417                         for (var i = 0, j = urls.length; i < j; ++i) {
0418                             var url = urls[i]
0419                             text += "<a href=\"" + url + "\">" + url + "</a><br>"
0420                         }
0421                     } else {
0422                         text = mimeData.text.replace(/\n/g, "<br>")
0423                     }
0424 
0425                     mainTextArea.insert(positionOfDrop(event), text)
0426                     event.accept(Qt.CopyAction)
0427                 }
0428                 onDragMove: {
0429                     // there doesn't seem to be a "just move the cursor", so we move
0430                     // the selection and then unselect so the cursor follows the mouse
0431                     mainTextArea.moveCursorSelection(positionOfDrop(event))
0432                     mainTextArea.deselect()
0433                 }
0434 
0435                 MouseArea {
0436                     anchors.fill: parent
0437                     cursorShape: mainTextArea.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor
0438                     acceptedButtons: Qt.NoButton
0439                 }
0440             }
0441 
0442             RowLayout {
0443                 id: fontButtons
0444                 spacing: Kirigami.Units.smallSpacing
0445                 anchors {
0446                     bottom: parent.bottom
0447                     left: parent.left
0448                     right: parent.right
0449                 }
0450                 height: visible ? implicitHeight : 0
0451                 visible: opacity > 0
0452                 opacity: focusScope.activeFocus ? 1 : 0
0453                 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } }
0454 
0455                 readonly property int requiredWidth: formatButtonsRow.width + spacing + settingsButton.width + removeButton.width
0456                 readonly property bool showFormatButtons: width > requiredWidth
0457 
0458                 Row {
0459                     id: formatButtonsRow
0460                     spacing: Kirigami.Units.smallSpacing
0461                     // show format buttons if TextField or any of the buttons have focus
0462                     enabled: opacity > 0
0463                     visible: fontButtons.showFormatButtons
0464 
0465                     PlasmaComponents3.ToolButton {
0466                         focusPolicy: Qt.TabFocus
0467                         icon.name: "format-text-bold"
0468                         icon.color: textIconColor
0469                         checked: documentHandler.bold
0470                         onClicked: documentHandler.bold = !documentHandler.bold
0471                         Accessible.name: boldTooltip.text
0472                         PlasmaComponents3.ToolTip {
0473                             id: boldTooltip
0474                             text: i18nc("@info:tooltip", "Bold")
0475                         }
0476                     }
0477                     PlasmaComponents3.ToolButton {
0478                         focusPolicy: Qt.TabFocus
0479                         icon.name: "format-text-italic"
0480                         icon.color: textIconColor
0481                         checked: documentHandler.italic
0482                         onClicked: documentHandler.italic = !documentHandler.italic
0483                         Accessible.name: italicTooltip.text
0484                         PlasmaComponents3.ToolTip {
0485                             id: italicTooltip
0486                             text: i18nc("@info:tooltip", "Italic")
0487                         }
0488                     }
0489                     PlasmaComponents3.ToolButton {
0490                         focusPolicy: Qt.TabFocus
0491                         icon.name: "format-text-underline"
0492                         icon.color: textIconColor
0493                         checked: documentHandler.underline
0494                         onClicked: documentHandler.underline = !documentHandler.underline
0495                         Accessible.name: underlineTooltip.text
0496                         PlasmaComponents3.ToolTip {
0497                             id: underlineTooltip
0498                             text: i18nc("@info:tooltip", "Underline")
0499                         }
0500                     }
0501                     PlasmaComponents3.ToolButton {
0502                         focusPolicy: Qt.TabFocus
0503                         icon.name: "format-text-strikethrough"
0504                         icon.color: textIconColor
0505                         checked: documentHandler.strikeOut
0506                         onClicked: documentHandler.strikeOut = !documentHandler.strikeOut
0507                         Accessible.name: strikethroughTooltip.text
0508                         PlasmaComponents3.ToolTip {
0509                             id: strikethroughTooltip
0510                             text: i18nc("@info:tooltip", "Strikethrough")
0511                         }
0512                     }
0513                 }
0514 
0515                 Item { // spacer
0516                     Layout.fillWidth: true
0517                     Layout.fillHeight: true
0518                 }
0519 
0520                 PlasmaComponents3.ToolButton {
0521                     id: settingsButton
0522                     focusPolicy: Qt.TabFocus
0523                     icon.name: "configure"
0524                     icon.color: textIconColor
0525                     onClicked: Plasmoid.internalAction("configure").trigger()
0526                     Accessible.name: settingsTooltip.text
0527                     PlasmaComponents3.ToolTip {
0528                         id: settingsTooltip
0529                         text: Plasmoid.internalAction("configure").text
0530                     }
0531                 }
0532 
0533                 PlasmaComponents3.ToolButton {
0534                     id: removeButton
0535                     focusPolicy: Qt.TabFocus
0536                     icon.name: "edit-delete"
0537                     icon.color: textIconColor
0538                     onClicked: {
0539                         // No need to ask for confirmation in the cases when...
0540                         // ...the note is blank
0541                         if (mainTextArea.length === 0 ||
0542                             // ...the note's content is equal to the clipboard text
0543 
0544                             // Note that we are intentionally not using
0545                             // mainTextArea.getText() because it has a method of
0546                             // converting the text to plainText that does not produce
0547                             // the same exact output of various other methods, and if
0548                             // we go out of our way to match it, we will be
0549                             // depending on an implementation detail. So we instead
0550                             // roll our own version to ensure that the conversion
0551                             // is done in the same way every time.
0552                             documentHandler.stripAndSimplify(mainTextArea.text) === documentHandler.strippedClipboardText()
0553                         ) {
0554                             Plasmoid.internalAction("remove").trigger();
0555                         } else {
0556                             discardConfirmationDialogLoader.open();
0557                         }
0558                     }
0559                     Accessible.name: removeTooltip.text
0560                     PlasmaComponents3.ToolTip {
0561                         id: removeTooltip
0562                         text: Plasmoid.internalAction("remove").text
0563                     }
0564                 }
0565             }
0566         }
0567 
0568         Loader {
0569             id: discardConfirmationDialogLoader
0570 
0571             function open() {
0572                 if (item) {
0573                     item.open();
0574                 } else {
0575                     active = true;
0576                 }
0577                 item.visible = true;
0578             }
0579 
0580             active: false
0581 
0582             sourceComponent: MessageDialog {
0583                 visible: false
0584                 title: i18n("Discard this note?")
0585                 text: i18n("Are you sure you want to discard this note?")
0586 
0587                 buttons: MessageDialog.Discard | MessageDialog.Cancel
0588 
0589                 onButtonClicked: (button, role) => {
0590                     if (button === MessageDialog.Discard) {
0591                         Plasmoid.internalAction("remove").trigger()
0592                         visible = false;
0593                     }
0594                 }
0595 
0596                 onRejected: {
0597                     visible = false
0598                 }
0599             }
0600         }
0601     }
0602 
0603     Plasmoid.contextualActions: [
0604         PlasmaCore.Action {
0605             text: i18nc("@item:inmenu", "White")
0606             onTriggered: Plasmoid.configuration.color = "white"
0607         },
0608         PlasmaCore.Action {
0609             text: i18nc("@item:inmenu", "Black")
0610             onTriggered: Plasmoid.configuration.color = "black"
0611         },
0612         PlasmaCore.Action {
0613             text: i18nc("@item:inmenu", "Red")
0614             onTriggered: Plasmoid.configuration.color = "red"
0615         },
0616         PlasmaCore.Action {
0617             text: i18nc("@item:inmenu", "Orange")
0618             onTriggered: Plasmoid.configuration.color = "orange"
0619         },
0620         PlasmaCore.Action {
0621             text: i18nc("@item:inmenu", "Yellow")
0622             onTriggered: Plasmoid.configuration.color = "yellow"
0623         },
0624         PlasmaCore.Action {
0625             text: i18nc("@item:inmenu", "Green")
0626             onTriggered: Plasmoid.configuration.color = "green"
0627         },
0628         PlasmaCore.Action {
0629             text: i18nc("@item:inmenu", "Blue")
0630             onTriggered: Plasmoid.configuration.color = "blue"
0631         },
0632         PlasmaCore.Action {
0633             text: i18nc("@item:inmenu", "Pink")
0634             onTriggered: Plasmoid.configuration.color = "pink"
0635         },
0636         PlasmaCore.Action {
0637             text: i18nc("@item:inmenu", "Transparent")
0638             onTriggered: Plasmoid.configuration.color = "translucent"
0639         },
0640         PlasmaCore.Action {
0641             text: i18nc("@item:inmenu", "Transparent Light")
0642             onTriggered: Plasmoid.configuration.color = "translucent-light"
0643         },
0644         PlasmaCore.Action {
0645             isSeparator: true
0646         }
0647     ]
0648 
0649     Component.onCompleted: {
0650         // Plasmoid configuration doesn't check before emitting change signal
0651         // explicit check is needed (at time of writing)
0652         if (note.id != Plasmoid.configuration.noteId) {
0653             Plasmoid.configuration.noteId = note.id;
0654         }
0655     }
0656 }