From 1927813ab1e31af2a4756b223a5111a9ea109d15 Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Tue, 9 Apr 2019 17:59:33 +0200 Subject: [PATCH] QtDesignStudio Color Editor update Palettes, Favorite colors, Recent colors, changed layout. Change-Id: I6fca962923a3e7a230edebdab5a30bd0847c8ba9 Reviewed-by: Thomas Hartmann --- .../imports/HelperWidgets/ColorButton.qml | 255 +++++++++---- .../HelperWidgets/ColorCheckButton.qml | 57 ++- .../imports/HelperWidgets/ColorEditor.qml | 342 +++++++++++++----- .../imports/HelperWidgets/ColorLine.qml | 53 +++ .../imports/HelperWidgets/GradientLine.qml | 9 + .../HelperWidgets/SimpleColorPalette.qml | 113 ++++++ .../imports/HelperWidgets/qmldir | 2 + .../propertyeditor/gradientmodel.cpp | 25 +- .../components/propertyeditor/gradientmodel.h | 2 + .../propertyeditor/propertyeditor.pri | 10 +- .../quick2propertyeditorview.cpp | 2 + .../propertyeditor/simplecolorpalette.cpp | 113 ++++++ .../propertyeditor/simplecolorpalette.h | 75 ++++ .../simplecolorpalettemodel.cpp | 146 ++++++++ .../propertyeditor/simplecolorpalettemodel.h | 77 ++++ .../simplecolorpalettesingleton.cpp | 185 ++++++++++ .../simplecolorpalettesingleton.h | 72 ++++ .../designercore/model/texttomodelmerger.cpp | 9 + src/plugins/qmldesigner/designersettings.cpp | 1 + src/plugins/qmldesigner/designersettings.h | 1 + src/plugins/qmldesigner/qmldesignerplugin.qbs | 6 + 21 files changed, 1365 insertions(+), 190 deletions(-) create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml create mode 100644 share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp create mode 100644 src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml index 203e692a82f..c7d6435ad10 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml @@ -82,6 +82,9 @@ Item { lightnessSlider.value = lightness alphaSlider.value = alpha + redSlider.value = (color.r * 255) + greenSlider.value = (color.g * 255) + blueSlider.value = (color.b * 255) block = false } @@ -242,7 +245,6 @@ Item { anchors.margins: 6 y: 4 height: parent.height - 8 - //value: colorButton.hue onValueChanged: { if (colorButton.hue !== value) colorButton.hue = value @@ -250,101 +252,194 @@ Item { onClicked: colorButton.clicked() } - Column { + Row { anchors.left: hueSlider.right anchors.margins: colorButton.sliderMargins spacing: 10 - Row { - z: 3 - spacing: 4 - Label { - text: "H:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + Column { + + spacing: 10 + + Row { + z: 3 + spacing: 1 + Label { + text: "R" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: redSlider + width: 64 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueChanged: { + if (color.r !== value && !colorButton.block) { + color.r = (value / 255.0) + colorButton.clicked() + } + } + } } - DoubleSpinBox { - id: hueSlider2 - //value: colorButton.hue - onValueChanged: { - if (colorButton.hue !== value && !colorButton.block) { - colorButton.hue = value - colorButton.clicked() + + Row { + z: 2 + spacing: 1 + Controls.Label { + text: "G" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + + DoubleSpinBox { + id: greenSlider + width: 64 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueChanged: { + if (color.g !== value && !colorButton.block) { + color.g = (value / 255.0) + colorButton.clicked() + } + } + } + } + + Row { + z: 1 + spacing: 1 + Controls.Label { + text: "B" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: blueSlider + width: 64 + + stepSize: 1 + minimumValue: 0 + maximumValue: 255 + decimals: 0 + + onValueChanged: { + if (color.b !== value && !colorButton.block) { + color.b = (value / 255.0) + colorButton.clicked() + } + } + } + } + + Row { + z: 0 + spacing: 1 + Controls.Label { + text: "A" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + + DoubleSpinBox { + id: alphaSlider + width: 64 + onValueChanged: { + if (colorButton.alpha !== value && !colorButton.block) { + colorButton.alpha = value + colorButton.clicked() + } } } } } - Row { - z: 2 - spacing: 4 - Controls.Label { - text: "S:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + Column { + + spacing: 10 + Row { + z: 3 + spacing: 1 + Label { + text: "H" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: hueSlider2 + width: 64 + onValueChanged: { + if (colorButton.hue !== value && !colorButton.block) { + colorButton.hue = value + colorButton.clicked() + } + } + } } - DoubleSpinBox { - id: saturationSlider - //value: colorButton.saturation - onValueChanged: { - if (colorButton.saturation !== value && !colorButton.block) { - colorButton.saturation = value - colorButton.clicked() + Row { + z: 2 + spacing: 1 + Controls.Label { + text: "S" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + + DoubleSpinBox { + id: saturationSlider + width: 64 + onValueChanged: { + if (colorButton.saturation !== value && !colorButton.block) { + colorButton.saturation = value + colorButton.clicked() + } + } + } + } + + Row { + z: 1 + spacing: 1 + Controls.Label { + text: "L" + width: 16 + color: "#eee" + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + DoubleSpinBox { + id: lightnessSlider + width: 64 + onValueChanged: { + if (colorButton.lightness !== value && !colorButton.block) { + colorButton.lightness = value + colorButton.clicked() + } } } } } - - Row { - z: 1 - spacing: 4 - Controls.Label { - text: "L:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - DoubleSpinBox { - id: lightnessSlider - //value: colorButton.lightness - onValueChanged: { - if (colorButton.lightness !== value && !colorButton.block) { - colorButton.lightness = value - colorButton.clicked() - } - } - } - } - - Row { - z: 0 - spacing: 4 - Controls.Label { - text: "A:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - } - - DoubleSpinBox { - id: alphaSlider - //value: colorButton.alpha - onValueChanged: { - if (colorButton.alpha !== value && !colorButton.block) { - colorButton.alpha = value - colorButton.clicked() - } - } - } - } - } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml index 941d705abd0..5f094dc00d9 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml @@ -25,19 +25,54 @@ import QtQuick 2.1 -Rectangle { - id: checkBox - width: 18 - height: 18 - - border.color: "black" - border.width: 1 - +Item { + id: colorCheckButtonRoot property bool checked: false + property alias buttonColor: checkBox.color + width: 30 + height: 24 - MouseArea { - anchors.fill: parent - onClicked: checkBox.checked = !checkBox.checked + + Rectangle { + id: backgroundBox + width: 24 + height: 24 + anchors.right: parent.right + + color: "white" + border.color: "white" + border.width: 1 + + Rectangle { + id: checkBox + width: 22 + height: 22 + anchors.centerIn: parent + + border.color: "black" + border.width: 1 + } } + Image { + id: arrowImage + width: 8 + height: 4 + source: "image://icons/down-arrow" + anchors.verticalCenter: parent.verticalCenter + anchors.right: backgroundBox.left + anchors.rightMargin: 2 + opacity: colorToolTip.containsMouse ? 1 : 0.8 + rotation: colorCheckButtonRoot.checked ? 0.0 : 270.0 + } + + ToolTipArea { + id: colorToolTip + + onClicked: checked = !checked + hoverEnabled: true + anchors.fill: parent + anchors.leftMargin: -arrowImage.width + tooltip: qsTr("Toggle color picker view") + } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml index e2a1ba2b90d..31d8d263b6c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -38,7 +38,7 @@ Column { property bool supportGradient: false - property alias caption: label.text + property string caption: "Color" property variant backendValue @@ -50,8 +50,14 @@ Column { property alias transparent: transparentButton.checked + property color originalColor + function isNotInGradientMode() { - return (buttonRow.checkedIndex !== 1) + return (buttonRow.checkedIndex === 0 || transparent) + } + + function resetShapeColor() { + colorEditor.backendValue.resetValue() } onValueChanged: colorEditor.color = colorEditor.value @@ -73,7 +79,7 @@ Column { if (!gradientLine.isInValidState) return; - if (supportGradient && gradientLine.hasGradient) { + if (colorEditor.supportGradient && gradientLine.hasGradient) { textField.text = convertColorToString(color) gradientLine.currentColor = color } @@ -84,22 +90,27 @@ Column { } } + ColorLine { + visible: { + return (colorEditor.supportGradient && isNotInGradientMode()) + } + currentColor: colorEditor.color + width: parent.width + } + GradientLine { property bool isInValidState: false visible: { - if (colorEditor.shapeGradients) { - return buttonRow.checkedIndex > 0 && buttonRow.checkedIndex < 4 - } else { - return buttonRow.checkedIndex === 1 - } + return !(isNotInGradientMode()) } id: gradientLine width: parent.width onCurrentColorChanged: { - if (supportGradient && gradientLine.hasGradient) + if (colorEditor.supportGradient && gradientLine.hasGradient) { colorEditor.color = gradientLine.currentColor + } } onHasGradientChanged: { @@ -125,11 +136,21 @@ Column { buttonRow.initalChecked = 1 } colorEditor.color = gradientLine.currentColor + } else if (colorEditor.transparent) { + buttonRow.initalChecked = 4 } else { buttonRow.initalChecked = 0 colorEditor.color = colorEditor.value } + buttonRow.checkedIndex = buttonRow.initalChecked + colorEditor.originalColor = colorEditor.color + } + + onSelectedNodeChanged: { + if (colorEditor.supportGradient && gradientLine.hasGradient) { + colorEditor.originalColor = gradientLine.currentColor + } } Connections { @@ -137,18 +158,26 @@ Column { onSelectionToBeChanged: { colorEditorTimer.stop() gradientLine.isInValidState = false + if (colorEditor.originalColor !== colorEditor.color) { + if (colorEditor.color != "#ffffff" + && colorEditor.color != "#000000" + && colorEditor.color != "#00000000") { + colorPalette.addColorToPalette(colorEditor.color) + } + } } } Connections { target: modelNodeBackend onSelectionChanged: { - if (supportGradient && gradientLine.hasGradient) { + if (colorEditor.supportGradient && gradientLine.hasGradient) { colorEditor.color = gradientLine.currentColor gradientLine.currentColor = color textField.text = colorEditor.color } gradientLine.isInValidState = true + colorEditor.originalColor = colorEditor.color } } @@ -156,29 +185,21 @@ Column { SectionLayout { width: parent.width + columnSpacing: 0 + rowSpacing: checkButton.checked ? 8 : 2 rows: 5 + //spacer 1 Item { - height: 0 - width: 2 - } - - Item { - height: 0 - width: 2 - } - - Label { - id: label - text: "Color" + height: 6 } SecondColumnLayout { ColorCheckButton { id: checkButton - color: colorEditor.color + buttonColor: colorEditor.color } LineEdit { @@ -217,64 +238,30 @@ Column { iconSource: "images/icon_color_solid.png" onClicked: { - if (colorEditor.supportGradient) - gradientLine.deleteGradient() + gradientLine.deleteGradient() textField.text = colorEditor.color - colorEditor.backendValue.resetValue() + colorEditor.resetShapeColor() } tooltip: qsTr("Solid Color") } ButtonRowButton { - visible: supportGradient + visible: colorEditor.supportGradient iconSource: "images/icon_color_gradient.png" onClicked: { - colorEditor.backendValue.resetValue() - if (colorEditor.shapeGradients) { - gradientLine.deleteGradient() + colorEditor.resetShapeColor() + + if (colorEditor.shapeGradients) gradientLine.gradientTypeName = "LinearGradient" + else + gradientLine.gradientTypeName = "Gradient" + + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { + gradientLine.deleteGradient() + gradientLine.addGradient() } - gradientLine.addGradient() - } - - GradientPresetList { - id: presetList - visible: false - - function applyPreset() { - if (presetList.gradientData.presetType == 0) { - gradientLine.setPresetByID(presetList.gradientData.presetID); - } - else if (presetList.gradientData.presetType == 1) { - gradientLine.setPresetByStops( - presetList.gradientData.stops, - presetList.gradientData.colors, - presetList.gradientData.stopsCount); - } - else { console.log("INVALID GRADIENT TYPE: " + presetList.gradientData.presetType); } - } - - onApply: { - if (presetList.gradientData.stopsCount > 0) { - applyPreset(); - } - } - - onSaved: { - gradientLine.savePreset(); - presetList.updatePresets(); - } - - onAccepted: { //return key - if (presetList.gradientData.stopsCount > 0) { - applyPreset(); - } - } - - } - - onDoubleClicked: { - presetList.open() } tooltip: qsTr("Linear Gradient") @@ -345,15 +332,18 @@ Column { } } ButtonRowButton { - visible: supportGradient && colorEditor.shapeGradients + visible: colorEditor.supportGradient && colorEditor.shapeGradients iconSource: "images/icon_color_radial_gradient.png" onClicked: { - colorEditor.backendValue.resetValue() - if (colorEditor.shapeGradients) { + colorEditor.resetShapeColor() + gradientLine.gradientTypeName = "RadialGradient" + + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { gradientLine.deleteGradient() - gradientLine.gradientTypeName = "RadialGradient" + gradientLine.addGradient() } - gradientLine.addGradient() } tooltip: qsTr("Radial Gradient") @@ -442,18 +432,21 @@ Column { } } ButtonRowButton { - visible: supportGradient && colorEditor.shapeGradients + visible: colorEditor.supportGradient && colorEditor.shapeGradients iconSource: "images/icon_color_conical_gradient.png" onClicked: { - colorEditor.backendValue.resetValue() - if (colorEditor.shapeGradients) { + colorEditor.resetShapeColor() + gradientLine.gradientTypeName = "ConicalGradient" + + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { gradientLine.deleteGradient() - gradientLine.gradientTypeName = "ConicalGradient" + gradientLine.addGradient() } - gradientLine.addGradient() } - tooltip: qsTr("Concial Gradient") + tooltip: qsTr("Conical Gradient") GradientPopupIndicator { @@ -513,18 +506,104 @@ Column { id: transparentButton iconSource: "images/icon_color_none.png" onClicked: { + gradientLine.deleteGradient() + colorEditor.resetShapeColor() colorEditor.color = "#00000000" - if (colorEditor.supportGradient) - gradientLine.deleteGradient() } tooltip: qsTr("Transparent") } } + Rectangle { + id: gradientPickerButton + width: 20 + height: 20 + visible: colorEditor.supportGradient + + color: "white" + border.color: "white" + border.width: 1 + + ToolTipArea { + anchors.fill: parent + id: toolTipArea + tooltip: qsTr("Gradient Picker Dialog") + } + + GradientPresetList { + id: presetList + visible: false + + function applyPreset() { + if (presetList.gradientData.presetType == 0) { + gradientLine.setPresetByID(presetList.gradientData.presetID); + } + else if (presetList.gradientData.presetType == 1) { + gradientLine.setPresetByStops( + presetList.gradientData.stops, + presetList.gradientData.colors, + presetList.gradientData.stopsCount); + } + else { + console.log("INVALID GRADIENT TYPE: " + + presetList.gradientData.presetType); + } + } + + onApply: { + if (presetList.gradientData.stopsCount > 0) { + applyPreset(); + } + } + + onSaved: { + gradientLine.savePreset(); + presetList.updatePresets(); + } + + onAccepted: { //return key + if (presetList.gradientData.stopsCount > 0) { + applyPreset(); + } + } + } + + Rectangle { + width: 18 + height: 18 + anchors.centerIn: parent + color: "steelblue" + + border.color: "black" + border.width: 1 + + MouseArea { + anchors.fill: parent + onClicked: { + presetList.open() + } + } + } + } + ExpandingSpacer { } } + //empty spacer 2 + Item { + height: 6 + } + + Item { + height: 6 + } + + //spacer 3 + Item { + height: 6 + } + ColorButton { property color bindedColor: colorEditor.color @@ -536,24 +615,101 @@ Column { enabled: !colorEditor.transparent opacity: checkButton.checked ? 1 : 0 id: colorButton - width: 116 - height: checkButton.checked ? 116 : 0 - Layout.preferredWidth: 116 - Layout.preferredHeight: checkButton.checked ? 116 : 0 + Layout.preferredWidth: 124 + Layout.preferredHeight: checkButton.checked ? 124 : 0 - sliderMargins: Math.max(0, label.width - colorButton.width) + 4 + sliderMargins: 4 onClicked: colorEditor.color = colorButton.color } - SecondColumnLayout { + //empty spacer 4 + Item { height: 2 } + Item { height: 2 } + + //spacer 5 + Item { + height: 4 } Item { - height: 4 - width :4 - } + id: colorBoxes + Layout.preferredWidth: 134 + Layout.preferredHeight: checkButton.checked ? 70 : 0 + visible: checkButton.checked + + + SecondColumnLayout { + spacing: 16 + RowLayout { + spacing: 2 + Column { + spacing: 5 + Text { + text: qsTr("Original") + color: "#eee" + } + Rectangle { + id: originalColorRectangle + color: colorEditor.originalColor + height: 40 + width: 67 + + border.width: 1 + border.color: "#555555" + + MouseArea { + anchors.fill: parent + onClicked: { + if (!colorEditor.transparent) + colorEditor.color = colorEditor.originalColor + } + } + } + } + + Column { + spacing: 5 + Text { + text: qsTr("New") + color: "#eee" + } + Rectangle { + id: newColorRectangle + color: colorEditor.color + height: 40 + width: 67 + + border.width: 1 + border.color: "#555555" + } + } + } + + Column { + spacing: 5 + Text { + text: qsTr("Recent") + color: "#eee" + elide: Text.ElideRight + } + + SimpleColorPalette { + id: colorPalette + + clickable: !colorEditor.transparent + + onSelectedColorChanged: { + colorEditor.color = colorPalette.selectedColor; + } + } + } + + ExpandingSpacer { + } + } + } } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml new file mode 100644 index 00000000000..c7256ba8929 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Controls.Private 1.0 // showing a ToolTip + +Item { + width: 300 + height: 60 + + property alias currentColor : colorLine.color + + Column { + anchors.fill: parent + + Item { + width: 1 + height: 40 + } + Rectangle { + height: 16 + width: parent.width + border.color: "#555555" + border.width: 1 + + id: colorLine + color: "white" + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml index 8db236176f7..f1886ada433 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml @@ -40,6 +40,8 @@ Item { property alias gradientPropertyName: gradientModel.gradientPropertyName property alias gradientTypeName: gradientModel.gradientTypeName + signal selectedNodeChanged + onHasGradientChanged: { colorLine.invalidate() } @@ -75,6 +77,10 @@ Item { gradientModel.savePreset() } + function updateGradient() { + gradientModel.updateGradient() + } + Connections { target: modelNodeBackend onSelectionChanged: { @@ -105,6 +111,7 @@ Item { gradientModel.lock() currentColor = repeater.itemAt(index).item.color gradientModel.unlock() + selectedNodeChanged() } function invalidate() { @@ -134,6 +141,7 @@ Item { height: 40 anchors.left: parent.left anchors.right: parent.right + cursorShape: Qt.PointingHandCursor onClicked: { var currentPosition = mouseX / colorLine.effectiveWidth @@ -321,6 +329,7 @@ Item { drag.maximumX: colorLine.effectiveWidth drag.minimumY: !readOnly ? 0 : 20 drag.maximumY: 20 + cursorShape: Qt.PointingHandCursor // using pressed property instead of drag.active which was not working onExited: { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml new file mode 100644 index 00000000000..c6b6acf2429 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 2.5 +import HelperWidgets 2.0 +import QtQuick.Controls.Private 1.0 // showing a ToolTip + +Item { + property color selectedColor + property bool clickable : true + + + width: 200 + height: 40 + enabled: clickable + + function addColorToPalette(colorCode) + { + paletteModel.addItem(colorCode) + } + + Component { + id: colorItemDelegate + + + Rectangle { + id: backgroundColor + property var favorite : isFavorite + height: 27 + width: 27 + border.color: (backgroundColor.favorite ? "#ffd700" : "#555555") + border.width: (backgroundColor.favorite ? 2 : 1) + color: "white" + radius: 0 + + Rectangle { + id: colorRectangle + width: 25 + height: 25 + anchors.centerIn: parent + color: colorCode + + border.color: "black" + border.width: 1 + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { + if ((mouse.button === Qt.LeftButton) && clickable) + selectedColor = colorRectangle.color + } + onPressed: { + if (mouse.button === Qt.RightButton) + contextMenu.popup() + } + } + Menu { + id: contextMenu + modal: true + closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape + MenuItem { + text: (backgroundColor.favorite + ? qsTr("Remove from Favorites") + : qsTr("Add to Favorites")) + onTriggered: { + paletteModel.toggleFavorite(index) + } + } + + Overlay.modal: Rectangle { + color: "transparent" + } + } + } + } + + SimpleColorPaletteModel { id: paletteModel } + ListView { + id: colorPaletteView + model: paletteModel + delegate: colorItemDelegate + orientation: Qt.Horizontal + anchors.fill: parent + clip: true + interactive: false + spacing: 2 + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir index 43e4da76368..9480f1d9a3a 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir @@ -9,6 +9,7 @@ CheckBox 2.0 CheckBox.qml ColorButton 2.0 ColorButton.qml ColorCheckButton 2.0 ColorCheckButton.qml ColorEditor 2.0 ColorEditor.qml +ColorLine 2.0 ColorLine.qml ColorLogic 2.0 ColorLogic.qml ComboBox 2.0 ComboBox.qml CustomCheckBoxStyle 2.0 CustomCheckBoxStyle.qml @@ -33,6 +34,7 @@ ScrollView 2.0 ScrollView.qml SecondColumnLayout 2.0 SecondColumnLayout.qml Section 2.0 Section.qml SectionLayout 2.0 SectionLayout.qml +SimpleColorPalette 2.0 SimpleColorPalette.qml DoubleSpinBox 2.0 DoubleSpinBox.qml SpinBox 2.0 SpinBox.qml StandardTextSection 2.0 StandardTextSection.qml diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp index 5aadf8dad5f..5728c594d48 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp @@ -181,7 +181,7 @@ void GradientModel::addGradient() setupModel(); if (m_gradientTypeName != "Gradient") - QTimer::singleShot(100, [this](){ view()->resetPuppet(); }); /*Unfortunately required */ + QTimer::singleShot(1000, [this](){ view()->resetPuppet(); }); /*Unfortunately required */ emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -534,19 +534,20 @@ void GradientModel::setPresetByStops(const QList &stopsPositions, QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction( QByteArrayLiteral("GradientModel::setCustomPreset")); - //delete an old gradient without rewriter transaction deleteGradientNode(false); - //create a new gradient: if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) { try { + + if (m_gradientTypeName != "Gradient") + ensureShapesImport(); + QmlDesigner::ModelNode gradientNode = createGradientNode(); m_itemNode.modelNode() .nodeProperty(gradientPropertyName().toUtf8()) .reparentHere(gradientNode); - //create stops and give them positions and colors based on value for (int i = 0; i < stopsCount; i++) { QmlDesigner::ModelNode gradientStopNode = createGradientStopNode(); gradientStopNode.variantProperty("position").setValue(stopsPositions.at(i)); @@ -560,6 +561,9 @@ void GradientModel::setPresetByStops(const QList &stopsPositions, } setupModel(); + if (m_gradientTypeName != "Gradient") + QTimer::singleShot(200, [this]() { view()->resetPuppet(); }); /*Unfortunately required */ + emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -586,3 +590,16 @@ void GradientModel::savePreset() items.append(item); GradientPresetCustomListModel::storePresets(filename, items); } + +void GradientModel::updateGradient() +{ + QList stops; + QList colors; + int stopsCount = rowCount(); + for (int i = 0; i < stopsCount; i++) { + stops.append(getPosition(i)); + colors.append(getColor(i).name(QColor::HexArgb)); + } + + setPresetByStops(stops, colors, stopsCount); +} diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h index d5fb3aea2a9..0cc1a3c4ae5 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h @@ -77,6 +77,8 @@ public: Q_INVOKABLE void savePreset(); + Q_INVOKABLE void updateGradient(); + signals: void anchorBackendChanged(); void hasGradientChanged(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri index 9d53bda311d..b32a744016f 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri @@ -15,7 +15,10 @@ SOURCES += propertyeditorview.cpp \ gradientpresetitem.cpp \ gradientpresetlistmodel.cpp \ gradientpresetdefaultlistmodel.cpp \ - gradientpresetcustomlistmodel.cpp + gradientpresetcustomlistmodel.cpp \ + simplecolorpalette.cpp \ + simplecolorpalettemodel.cpp \ + simplecolorpalettesingleton.cpp HEADERS += propertyeditorview.h \ qmlanchorbindingproxy.h \ @@ -32,6 +35,9 @@ HEADERS += propertyeditorview.h \ gradientpresetitem.h \ gradientpresetlistmodel.h \ gradientpresetdefaultlistmodel.h \ - gradientpresetcustomlistmodel.h + gradientpresetcustomlistmodel.h \ + simplecolorpalette.h \ + simplecolorpalettemodel.h \ + simplecolorpalettesingleton.h QT += qml quick diff --git a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp index f9b42cf8eb8..862d16ba22f 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp @@ -30,6 +30,7 @@ #include "gradientmodel.h" #include "gradientpresetdefaultlistmodel.h" #include "gradientpresetcustomlistmodel.h" +#include "simplecolorpalettemodel.h" #include "qmlanchorbindingproxy.h" #include "theme.h" @@ -52,6 +53,7 @@ void Quick2PropertyEditorView::registerQmlTypes() GradientModel::registerDeclarativeType(); GradientPresetDefaultListModel::registerDeclarativeType(); GradientPresetCustomListModel::registerDeclarativeType(); + SimpleColorPaletteModel::registerDeclarativeType(); Internal::QmlAnchorBindingProxy::registerDeclarativeType(); } } diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp new file mode 100644 index 00000000000..7fada3f0d38 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "simplecolorpalette.h" + +#include "designersettings.h" + +#include + +namespace QmlDesigner { + +PaletteColor::PaletteColor() + : m_color(QColor()) + , m_colorCode(QColor().name()) + , m_isFavorite(false) +{} + +PaletteColor::PaletteColor(const QString &colorCode) + : m_color(colorCode) + , m_colorCode(colorCode) + , m_isFavorite(false) +{} + +PaletteColor::PaletteColor(const QColor &value) + : m_color(color) + , m_colorCode(color.name(QColor::HexArgb)) + , m_isFavorite(false) +{} + +QVariant PaletteColor::getProperty(Property id) const +{ + QVariant out; + + switch (id) { + case objectNameRole: + out.setValue(QString()); + break; + case colorRole: + out.setValue(color()); + break; + case colorCodeRole: + out.setValue(colorCode()); + break; + case isFavoriteRole: + out.setValue(isFavorite()); + break; + default: + qWarning() << "PaletteColor Property switch default case"; + break; //replace with assert before switch? + } + + return out; +} + +QColor PaletteColor::color() const +{ + return m_color; +} + +void PaletteColor::setColor(const QColor &value) +{ + m_color = value; + m_colorCode = m_color.name(QColor::HexArgb); +} + +QString PaletteColor::colorCode() const +{ + return m_colorCode; +} + +bool PaletteColor::isFavorite() const +{ + return m_isFavorite; +} + +void PaletteColor::setFavorite(bool favorite) +{ + m_isFavorite = favorite; +} + +bool PaletteColor::toggleFavorite() +{ + return m_isFavorite = !m_isFavorite; +} + +bool PaletteColor::operator==(const PaletteColor &other) const +{ + return (m_color == other.m_color); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h new file mode 100644 index 00000000000..342c9832e71 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace QmlDesigner { + +class PaletteColor +{ + Q_GADGET + + Q_PROPERTY(QColor color READ color FINAL) + Q_PROPERTY(QString colorCode READ colorCode FINAL) + Q_PROPERTY(bool isFavorite READ isFavorite FINAL) +public: + PaletteColor(); + PaletteColor(const QString &colorCode); + PaletteColor(const QColor &value); + ~PaletteColor() = default; + + enum Property { + objectNameRole = 0, + colorRole = 1, + colorCodeRole = 2, + isFavoriteRole = 3 + }; + + QVariant getProperty(Property id) const; + + QColor color() const; + void setColor(const QColor &value); + + QString colorCode() const; + + bool isFavorite() const; + void setFavorite(bool favorite); + bool toggleFavorite(); + + bool operator==(const PaletteColor &other) const; + +private: + QColor m_color; + QString m_colorCode; + bool m_isFavorite; +}; + +} // namespace QmlDesigner + +Q_DECLARE_METATYPE(QmlDesigner::PaletteColor) diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp new file mode 100644 index 00000000000..b3207f0006d --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "simplecolorpalettemodel.h" +#include "simplecolorpalette.h" +#include "simplecolorpalettesingleton.h" + +#include "designersettings.h" + +#include +#include +#include +#include + +namespace QmlDesigner { + +SimpleColorPaletteModel::SimpleColorPaletteModel(QObject *parent) + : QAbstractListModel(parent) +{ + connect(&SimpleColorPaletteSingleton::getInstance(), + &SimpleColorPaletteSingleton::paletteChanged, + this, + &SimpleColorPaletteModel::setPalette); + m_roleNames = {{static_cast(PaletteColor::Property::objectNameRole), "objectName"}, + {static_cast(PaletteColor::Property::colorRole), "color"}, + {static_cast(PaletteColor::Property::colorCodeRole), "colorCode"}, + {static_cast(PaletteColor::Property::isFavoriteRole), "isFavorite"}}; + + setPalette(); +} + +SimpleColorPaletteModel::~SimpleColorPaletteModel() +{ + clearItems(); +} + +int SimpleColorPaletteModel::rowCount(const QModelIndex & /*parent*/) const +{ + return m_items.count(); +} + +QVariant SimpleColorPaletteModel::data(const QModelIndex &index, int role) const +{ + if (index.isValid() && (index.row() >= 0) && (index.row() < m_items.count())) { + if (m_roleNames.contains(role)) { + QVariant value = m_items.at(index.row()) + .getProperty(static_cast(role)); + if (auto model = qobject_cast(value.value())) + return QVariant::fromValue(model); + + return value; + } + + qWarning() << Q_FUNC_INFO << "invalid role requested"; + return QVariant(); + } + + qWarning() << Q_FUNC_INFO << "invalid index requested"; + return QVariant(); +} + +QHash SimpleColorPaletteModel::roleNames() const +{ + return m_roleNames; +} + +void SimpleColorPaletteModel::clearItems() +{ + beginResetModel(); + m_items.clear(); + endResetModel(); +} + +void SimpleColorPaletteModel::addItem(const QString &item) +{ + PaletteColor palette(item); + addItem(palette); +} + +void SimpleColorPaletteModel::addItem(const PaletteColor &item) +{ + SimpleColorPaletteSingleton::getInstance().addItem(item); +} + +const QList &SimpleColorPaletteModel::items() const +{ + return m_items; +} + +void SimpleColorPaletteModel::sortItems() +{ + SimpleColorPaletteSingleton::getInstance().sortItems(); +} + +void SimpleColorPaletteModel::registerDeclarativeType() +{ + qmlRegisterType("HelperWidgets", 2, 0, "SimpleColorPaletteModel"); +} + +void SimpleColorPaletteModel::toggleFavorite(int id) +{ + SimpleColorPaletteSingleton::getInstance().toggleFavorite(id); +} + +void SimpleColorPaletteModel::setPalette() +{ + beginResetModel(); + m_items = SimpleColorPaletteSingleton::getInstance().getItems(); + m_favoriteOffset = SimpleColorPaletteSingleton::getInstance().getFavoriteOffset(); + m_paletteSize = SimpleColorPaletteSingleton::getInstance().getPaletteSize(); + endResetModel(); +} + +bool SimpleColorPaletteModel::read() +{ + return SimpleColorPaletteSingleton::getInstance().readPalette(); +} + +void SimpleColorPaletteModel::write() +{ + SimpleColorPaletteSingleton::getInstance().writePalette(); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h new file mode 100644 index 00000000000..3ed2cc8a31d --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace QmlDesigner { + +class PaletteColor; + +class SimpleColorPaletteModel : public QAbstractListModel +{ + Q_OBJECT +public: + explicit SimpleColorPaletteModel(QObject *parent = nullptr); + ~SimpleColorPaletteModel() override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + + void clearItems(); + Q_INVOKABLE void addItem(const QString &item); + void addItem(const PaletteColor &item); + + const QList &items() const; + + void sortItems(); + + static void registerDeclarativeType(); + + Q_INVOKABLE void toggleFavorite(int id); + + bool read(); + void write(); + +private slots: + void setPalette(); + +private: + void enqueue(const PaletteColor &item); + +private: + int m_paletteSize; + int m_favoriteOffset; + QList m_items; + QHash m_roleNames; +}; + +} // namespace QmlDesigner + +QML_DECLARE_TYPE(QmlDesigner::SimpleColorPaletteModel) diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp new file mode 100644 index 00000000000..ccea50bbf25 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "simplecolorpalettesingleton.h" +#include "simplecolorpalette.h" + +#include "designersettings.h" + +#include +#include + +namespace QmlDesigner { + +SimpleColorPaletteSingleton::SimpleColorPaletteSingleton() + : m_items() + , m_favoriteOffset(0) +{ + if (!readPalette()) { + for (int i = 0; i < m_paletteSize; i++) + m_items.append(PaletteColor()); + } +} + +SimpleColorPaletteSingleton &SimpleColorPaletteSingleton::getInstance() +{ + static SimpleColorPaletteSingleton singleton; + + return singleton; +} + +void SimpleColorPaletteSingleton::addItem(const PaletteColor &item) +{ + if (m_favoriteOffset >= m_paletteSize) + return; + + if (item.isFavorite()) { + int contains = m_items.indexOf(item); + if (contains != -1) { + if (m_items.at(contains).isFavorite()) + return; + else + m_items.removeAt(contains); + } + m_items.insert(0, item); + m_favoriteOffset++; + } else if (m_items.contains(item)) + return; + else + m_items.insert(m_favoriteOffset, item); + + while (m_items.size() > m_paletteSize) { + m_items.removeLast(); + } + + writePalette(); + + emit paletteChanged(); +} + +QList SimpleColorPaletteSingleton::getItems() const +{ + return m_items; +} + +int SimpleColorPaletteSingleton::getPaletteSize() const +{ + return m_paletteSize; +} + +int SimpleColorPaletteSingleton::getFavoriteOffset() const +{ + return m_favoriteOffset; +} + +void SimpleColorPaletteSingleton::sortItems() +{ + auto itemSort = [](const PaletteColor &first, const PaletteColor &second) { + return (static_cast(first.isFavorite()) < static_cast(second.isFavorite())); + }; + + std::sort(m_items.begin(), m_items.end(), itemSort); + + emit paletteChanged(); +} + +void SimpleColorPaletteSingleton::toggleFavorite(int id) +{ + bool toggleResult = m_items[id].toggleFavorite(); + + if (toggleResult) { + m_favoriteOffset++; + m_items.move(id, 0); + } else { + m_favoriteOffset--; + m_items.move(id, m_favoriteOffset); + } + + if (m_favoriteOffset < 0) + m_favoriteOffset = 0; + else if (m_favoriteOffset > m_paletteSize) + m_favoriteOffset = m_paletteSize; + + emit paletteChanged(); +} + +bool SimpleColorPaletteSingleton::readPalette() +{ + QList proxy; + const QStringList stringData = QmlDesigner::DesignerSettings::getValue( + QmlDesigner::DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT) + .toStringList(); + + int favCounter = 0; + + for (int i = 0; i < stringData.size(); i++) { + const QStringList strsep = stringData.at(i).split(";"); + if (strsep.size() != 2) { + continue; + } + PaletteColor colorItem(strsep.at(0)); + bool isFav = static_cast(strsep.at(1).toInt()); + colorItem.setFavorite(isFav); + if (isFav) + favCounter++; + proxy.append(colorItem); + } + + if (proxy.size() == 0) { + return false; + } + + while (proxy.size() > m_paletteSize) { + proxy.removeLast(); + } + while (proxy.size() < m_paletteSize) { + proxy.append(PaletteColor()); + } + + m_items.clear(); + m_items = proxy; + m_favoriteOffset = favCounter; + + return true; +} + +void SimpleColorPaletteSingleton::writePalette() +{ + QStringList output; + QString subres; + + for (int i = 0; i < m_items.size(); i++) { + subres = m_items.at(i).color().name(QColor::HexArgb); + subres += ";"; + subres += QString::number(static_cast(m_items.at(i).isFavorite())); + output.push_back(subres); + subres.clear(); + } + + QmlDesigner::DesignerSettings::setValue( + QmlDesigner::DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, output); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h new file mode 100644 index 00000000000..004feea5325 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace QmlDesigner { + +class PaletteColor; + +class SimpleColorPaletteSingleton : public QObject +{ + Q_OBJECT +public: + static SimpleColorPaletteSingleton &getInstance(); + + bool readPalette(); + void writePalette(); + + void addItem(const PaletteColor &item); + QList getItems() const; + + int getPaletteSize() const; + int getFavoriteOffset() const; + + void sortItems(); + + void toggleFavorite(int id); + + SimpleColorPaletteSingleton(const SimpleColorPaletteSingleton &) = delete; + void operator=(const SimpleColorPaletteSingleton &) = delete; + +signals: + void paletteChanged(); + +private: + SimpleColorPaletteSingleton(); + +private: + QList m_items; + const int m_paletteSize = 6; + int m_favoriteOffset; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index c86336d5509..b9b82f5714f 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -372,6 +372,13 @@ bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2) return false; } +bool smartColorCompare(const QVariant &value1, const QVariant &value2) +{ + if ((value1.type() == QVariant::Color) || (value2.type() == QVariant::Color)) + return value1.value().rgba() == value2.value().rgba(); + return false; +} + bool equals(const QVariant &a, const QVariant &b) { if (a.canConvert() && b.canConvert()) @@ -380,6 +387,8 @@ bool equals(const QVariant &a, const QVariant &b) return true; if (smartVeryFuzzyCompare(a, b)) return true; + if (smartColorCompare(a, b)) + return true; return false; } diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index 7df99bd59bb..5870927d529 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -76,6 +76,7 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); restoreValue(settings, DesignerSettingsKey::STANDALONE_MODE, false); restoreValue(settings, DesignerSettingsKey::ENABLE_TIMELINEVIEW, false); + restoreValue(settings, DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, QStringList()); settings->endGroup(); settings->endGroup(); diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index bdaa22bb4b2..410abc267e2 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -65,6 +65,7 @@ const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These setti const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ const char STANDALONE_MODE[] = "StandAloneMode"; const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView"; +const char SIMPLE_COLOR_PALETTE_CONTENT[] = "SimpleColorPaletteContent"; } class DesignerSettings : public QHash diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 6a2379ea05e..600fcab3fe9 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -588,6 +588,12 @@ Project { "propertyeditor/qmlanchorbindingproxy.h", "propertyeditor/qmlmodelnodeproxy.cpp", "propertyeditor/qmlmodelnodeproxy.h", + "propertyeditor/simplecolorpalette.cpp", + "propertyeditor/simplecolorpalette.h", + "propertyeditor/simplecolorpalettemodel.cpp", + "propertyeditor/simplecolorpalettemodel.h", + "propertyeditor/simplecolorpalettesingleton.cpp", + "propertyeditor/simplecolorpalettesingleton.h", "resources/resources.qrc", "stateseditor/stateseditorimageprovider.cpp", "stateseditor/stateseditorimageprovider.h",