Warning, /plasma/kdeplasma-addons/applets/colorpicker/package/contents/ui/main.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 * SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
0003 *
0004 * SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006
0007 import QtQuick
0008 import QtQuick.Controls as QQC2
0009 import QtQuick.Layouts
0010 import QtQuick.Dialogs as QtDialogs
0011
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.kirigami 2.20 as Kirigami
0017 import org.kde.kcmutils as KCMUtils
0018 import org.kde.config as KConfig
0019 import org.kde.kwindowsystem 1.0
0020
0021 import org.kde.plasma.private.colorpicker 2.0 as ColorPicker
0022 import "logic.js" as Logic
0023
0024 PlasmoidItem {
0025 id: root
0026
0027 readonly property bool isVertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical
0028
0029 readonly property color recentColor: historyModel.count > 0 ? historyModel.get(0).color : "#00000000" // transparent as fallback
0030 readonly property string defaultFormat: Plasmoid.configuration.defaultFormat
0031 readonly property int maxColorCount: 9
0032
0033 preferredRepresentation: compactRepresentation
0034
0035 function addColorToHistory(color) {
0036 // this .toString() is needed otherwise Qt completely screws it up
0037 // replacing *all* items in the list by the new items and other nonsense
0038 historyModel.insert(0, { color: color.toString() });
0039 // limit to 9 entries
0040 if (historyModel.count > maxColorCount) {
0041 historyModel.remove(maxColorCount);
0042 }
0043 historyModel.save();
0044 }
0045
0046 function colorPicked(color) {
0047 if (color != recentColor) {
0048 addColorToHistory(color)
0049 }
0050
0051 if (Plasmoid.configuration.autoClipboard) {
0052 picker.copyToClipboard(Logic.formatColor(color, root.defaultFormat))
0053 }
0054 }
0055
0056 function pickColor() {
0057 root.expanded = false
0058 picker.pick()
0059 }
0060
0061 ColorPicker.GrabWidget {
0062 id: picker
0063 onCurrentColorChanged: colorPicked(currentColor)
0064 }
0065
0066 Component {
0067 id: colorWindowComponent
0068
0069 Window { // QTBUG-119055
0070 id: window
0071 width: Kirigami.Units.gridUnit * 19
0072 height: Kirigami.Units.gridUnit * 23
0073 visible: true
0074 title: Plasmoid.title
0075 QtDialogs.ColorDialog {
0076 id: colorDialog
0077 title: Plasmoid.title
0078 selectedColor: historyModel.count > 0 ? root.recentColor : undefined /* Prevent transparent colors */
0079 onAccepted: {
0080 root.colorPicked(selectedColor);
0081 window.destroy();
0082 }
0083 onRejected: window.destroy()
0084 }
0085 onClosing: destroy()
0086 Component.onCompleted: colorDialog.open()
0087 }
0088 }
0089
0090 // prevents the popup from actually opening, needs to be queued
0091 Timer {
0092 id: delayedPickTimer
0093 interval: 0
0094 onTriggered: root.pickColor()
0095 }
0096
0097 ListModel {
0098 id: historyModel
0099
0100 function save() {
0101 let history = [];
0102 for (let i = 0; i < count; i++) {
0103 history.push(get(i).color);
0104 }
0105 Plasmoid.configuration.history = history;
0106 }
0107 }
0108
0109 Plasmoid.onActivated: {
0110 if (Plasmoid.configuration.pickOnActivate) {
0111 delayedPickTimer.start();
0112 }
0113 }
0114
0115 Plasmoid.contextualActions: [
0116 PlasmaCore.Action {
0117 text: i18nc("@action", "Open Color Dialog")
0118 icon.name: "color-management"
0119 onTriggered: colorWindowComponent.createObject(root)
0120 },
0121 PlasmaCore.Action {
0122 text: i18nc("@action", "Clear History")
0123 icon.name: "edit-clear-history"
0124 onTriggered: {
0125 historyModel.clear();
0126 historyModel.save();
0127 }
0128 },
0129 PlasmaCore.Action {
0130 text: i18nc("@action", "View History")
0131 icon.name: "view-history"
0132 onTriggered: root.expanded = true
0133 }
0134 ]
0135
0136 Component.onCompleted: {
0137 Plasmoid.configuration.history.forEach(item => historyModel.append({ color: item }));
0138 Logic.copyToClipboardText = i18ndc("plasma_applet_org.kde.plasma.colorpicker", "@title:menu", "Copy to Clipboard"); // i18n is not supported in js library
0139 }
0140
0141 compactRepresentation: CompactRepresentation { }
0142
0143 fullRepresentation: GridView {
0144 id: fullRoot
0145
0146 readonly property int columns: 3
0147
0148 Layout.minimumWidth: columns * Kirigami.Units.gridUnit * 6
0149 Layout.minimumHeight: Layout.minimumWidth
0150 Layout.maximumWidth: Layout.minimumWidth
0151 Layout.maximumHeight: Layout.minimumHeight
0152
0153 cellWidth: Math.floor(fullRoot.width / fullRoot.columns)
0154 cellHeight: cellWidth
0155 boundsBehavior: Flickable.StopAtBounds
0156
0157 model: historyModel
0158
0159 highlight: PlasmaExtras.Highlight {}
0160 highlightMoveDuration: 0
0161
0162 Loader {
0163 width: parent.width - Kirigami.Units.gridUnit * 2
0164 anchors.centerIn: parent
0165 visible: active
0166
0167 active: fullRoot.count === 0 && root.expanded
0168 asynchronous: true
0169
0170 sourceComponent: PlasmaExtras.PlaceholderMessage {
0171 id: emptyHint
0172
0173 opacity: 0
0174 iconName: "edit-none"
0175
0176 readonly property bool compositingActive: KWindowSystem.isPlatformWayland || KX11Extras.compositingActive
0177
0178 text: compositingActive ? i18nc("@info:usagetip", "No colors") : i18nc("@info:status when color picking is unavailable", "Color picking unavailable when compositing is disabled")
0179 explanation: compositingActive ? "" : i18nc("@info:status when color pick is unavailable", "Compositing has been manually disabled or blocked by a running application")
0180
0181 helpfulAction: compositingActive ? pickColorAction : enableCompositingAction
0182
0183 QQC2.Action {
0184 id: pickColorAction
0185 icon.name: "color-picker"
0186 text: i18nc("@action:button", "Pick Color")
0187 onTriggered: root.pickColor()
0188 }
0189
0190 QQC2.Action {
0191 id: enableCompositingAction
0192 enabled: KConfig.KAuthorized.authorizeControlModule("kwincompositing")
0193 icon.name: "settings-configure"
0194 text: i18nc("@action:button open kwincompositing KCM", "Configure Compositing")
0195 onTriggered: KCMUtils.KCMLauncher.openSystemSettings("kwincompositing")
0196 }
0197
0198 NumberAnimation {
0199 duration: Kirigami.Units.longDuration
0200 easing.type: Easing.OutCubic
0201 property: "opacity"
0202 running: true
0203 target: emptyHint
0204 to: 1
0205 }
0206 }
0207 }
0208
0209 Connections {
0210 target: root
0211 function onExpandedChanged() {
0212 if (root.expanded) {
0213 fullRoot.forceActiveFocus()
0214 }
0215 }
0216 }
0217
0218 Keys.onPressed: event => {
0219 if (event.key === Qt.Key_Escape) {
0220 root.expanded = false;
0221 event.accepted = true;
0222 }
0223 }
0224
0225 // This item serves as a drag pixmap and is captured when a drag starts
0226 Rectangle {
0227 id: dragImageDummy
0228 border {
0229 color: Kirigami.Theme.textColor
0230 width: 1
0231 }
0232 radius: width
0233 width: Kirigami.Units.iconSizes.large
0234 height: Kirigami.Units.iconSizes.large
0235 visible: false
0236 }
0237
0238 delegate: MouseArea {
0239 id: delegateMouse
0240
0241 readonly property color currentColor: model.color
0242
0243 width: fullRoot.cellWidth
0244 height: fullRoot.cellHeight
0245
0246 drag.target: rect
0247 Drag.dragType: Drag.Automatic
0248 Drag.active: delegateMouse.drag.active
0249 Drag.mimeData: {
0250 "application/x-color": rect.color,
0251 "text/plain": colorLabel.text
0252 }
0253
0254 acceptedButtons: Qt.LeftButton | Qt.RightButton
0255 hoverEnabled: true
0256
0257 Keys.onDeletePressed: event => remove()
0258 Keys.onPressed: event => {
0259 switch (event.key) {
0260 case Qt.Key_Space:
0261 case Qt.Key_Enter:
0262 case Qt.Key_Return:
0263 case Qt.Key_Select:
0264 copy();
0265 break;
0266 case Qt.Key_Menu:
0267 openMenu();
0268 break;
0269 }
0270 }
0271
0272 Accessible.name: colorLabel.text
0273 Accessible.role: Accessible.ButtonMenu
0274
0275 onContainsMouseChanged: {
0276 if (containsMouse) {
0277 fullRoot.currentIndex = index;
0278 } else if (fullRoot.currentIndex === index) {
0279 fullRoot.currentIndex = -1;
0280 }
0281 }
0282
0283 onPressed: mouse => {
0284 // grab pixmap only once
0285 if (Drag.imageSource.toString() === "") { // cannot just do !Drag.imageSource on QUrl
0286 dragImageDummy.color = currentColor;
0287 dragImageDummy.grabToImage(result => {
0288 Drag.imageSource = result.url;
0289 });
0290 }
0291 }
0292
0293 onClicked: mouse => {
0294 if (mouse.button === Qt.LeftButton) {
0295 copy();
0296 } else if (mouse.button === Qt.RightButton) {
0297 openMenu();
0298 }
0299 }
0300
0301 function copy() {
0302 picker.copyToClipboard(Logic.formatColor(currentColor, root.defaultFormat))
0303 colorLabel.visible = false;
0304 copyIndicatorLabel.visible = true;
0305 colorLabelRestoreTimer.start()
0306 }
0307
0308 function openMenu() {
0309 const menu = Logic.createContextMenu(this, currentColor, picker, colorLabel, copyIndicatorLabel, colorLabelRestoreTimer);
0310 menu.openRelative();
0311 }
0312
0313 function remove() {
0314 historyModel.remove(index);
0315 historyModel.save();
0316 }
0317
0318 PlasmaCore.ToolTipArea {
0319 anchors.fill: parent
0320 active: colorLabel.truncated
0321 mainText: colorLabel.text
0322 }
0323
0324 Timer {
0325 id: colorLabelRestoreTimer
0326 interval: Kirigami.Units.humanMoment
0327 onTriggered: {
0328 colorLabel.visible = true;
0329 copyIndicatorLabel.visible = false;
0330 }
0331 }
0332
0333 Rectangle {
0334 id: rect
0335
0336 anchors {
0337 fill: parent
0338 margins: Kirigami.Units.smallSpacing
0339 }
0340
0341 color: delegateMouse.currentColor
0342
0343 border {
0344 color: Kirigami.Theme.textColor
0345 width: 1
0346 }
0347
0348 Rectangle {
0349 anchors {
0350 bottom: parent.bottom
0351 left: parent.left
0352 right: parent.right
0353 margins: rect.border.width
0354 }
0355 height: colorLabel.contentHeight + 2 * Kirigami.Units.smallSpacing
0356 color: Kirigami.Theme.backgroundColor
0357 opacity: 0.8
0358
0359 PlasmaComponents3.Label {
0360 id: colorLabel
0361 anchors.fill: parent
0362 horizontalAlignment: Text.AlignHCenter
0363 verticalAlignment: Text.AlignVCenter
0364 elide: Text.ElideLeft
0365 fontSizeMode: Text.HorizontalFit
0366 minimumPointSize: Kirigami.Theme.smallFont.pointSize
0367 text: Logic.formatColor(delegateMouse.currentColor, root.defaultFormat)
0368 textFormat: Text.PlainText
0369 }
0370
0371 PlasmaComponents3.Label {
0372 id: copyIndicatorLabel
0373 visible: false
0374 anchors.fill: parent
0375 horizontalAlignment: Text.AlignHCenter
0376 verticalAlignment: Text.AlignVCenter
0377 elide: Text.ElideLeft
0378 fontSizeMode: Text.HorizontalFit
0379 minimumPointSize: Kirigami.Theme.smallFont.pointSize
0380 text: i18nc("@info:progress just copied a color to clipboard", "Copied!")
0381 textFormat: Text.PlainText
0382 }
0383 }
0384 }
0385
0386 Loader {
0387 active: parent.containsMouse || Kirigami.Settings.tabletMode || Kirigami.Settings.hasTransientTouchInput
0388 anchors.right: parent.right
0389 anchors.top: parent.top
0390 sourceComponent: PlasmaComponents3.Button {
0391 text: i18nc("@action:button", "Delete")
0392 icon.name: "delete"
0393 display: PlasmaComponents3.AbstractButton.IconOnly
0394
0395 onClicked: delegateMouse.remove()
0396
0397 PlasmaComponents3.ToolTip {
0398 text: parent.text
0399 }
0400 }
0401 }
0402 }
0403 }
0404 }