diff options
114 files changed, 6365 insertions, 486 deletions
diff --git a/doc/api/qtcreator-documentation.qdoc b/doc/api/qtcreator-documentation.qdoc index 28e1b32fdc..1d54a86912 100644 --- a/doc/api/qtcreator-documentation.qdoc +++ b/doc/api/qtcreator-documentation.qdoc @@ -165,18 +165,14 @@ the \QC Manual, observe the guidelines listed in this section when taking screen shots. - To make the images look similar regardless of the operating system they were - taken on, you are asked to adjust their size to 75%. This makes the screen - shots hard to read, but they are provided more as reassurance for users that - they are in the correct place in the UI than as an actual source of - information. To make sure that no important information is lost, always - place example values also in the text. + \note Do not rely on screen shots present reasonable example values to + users, but always place example values also in the text. \list - \li Use the screen resolution of 1024x768 (this is available on all - screens). + \li Use the screen resolution of 1366x768 (available on the most + commonly used screens, as of this writing). - \li Use the aspect ratio of 4:3. + \li Use the aspect ratio of 16:9. \li Open the application in the maximum size on full screen. @@ -185,9 +181,6 @@ \li Include only the part of the screen that you need (you can crop the image also in the screen capture tool). - \li In the screen capture tool, open the screen shot and adjust its size - to 75%. - \li To highlight parts of the screen shot, use the images of numbers that are stored in \c{doc\images\numbers} in the \QC repository. @@ -212,13 +205,8 @@ \c doc\images\numbers directory (or in the \c qtdoc module sources in \c doc\images\numbers). - To use the numbers: - - \list - \li Take a screenshot as described above. - \li After resizing the screenshot, copy-paste the number images on - the screenshot to the places that you want to refer to from text. - \endlist + To use the numbers, copy-paste the number images on the screenshot to the + places that you want to refer to from text. \section2 Optimizing Images @@ -234,8 +222,8 @@ You can use a web service, such as \l{https://tinypng.com}, or an image optimization tool to shrink the images. For example, you can use the Radical - Image Optimization Tool (RIOT) on Windows (very efficient) or ImageOptim on - \macos (much less efficient), or some other tool available on Linux. + Image Optimization Tool (RIOT) or OptiPNG on Windows, ImageOptim on + \macos, or some other tool available on Linux. With ImageOptim, you simply drag and drop the image files to the application. The following section describes the settings to use for RIOT. diff --git a/doc/src/howto/creator-sidebar-views.qdoc b/doc/src/howto/creator-sidebar-views.qdoc index d92a1067b5..4461c14be7 100644 --- a/doc/src/howto/creator-sidebar-views.qdoc +++ b/doc/src/howto/creator-sidebar-views.qdoc @@ -196,16 +196,6 @@ files, as well as compare the selected file with the currently open file in the diff editor. For more information, see \l{Comparing Files}. - \section1 Viewing Open Documents - - To see a list of open documents, switch to the \uicontrol {Open Documents} - view. By right-clicking an open document, you can: - - \list - \li Pin files to ensure they stay at the top of the list and are not - closed when \uicontrol {Close All} is used. - \endlist - \section1 Viewing the File System If you cannot see a file in the \uicontrol Projects view, switch to the @@ -274,6 +264,22 @@ \endlist + \section1 Viewing Open Documents + + To see a list of open documents, switch to the \uicontrol {Open Documents} + view. You can use the context-menu to perform some of the functions also + available in the \uicontrol File menu and in the context menu in the + \uicontrol {File System} view. + + In addition, you can: + + \list + \li Copy the full path of the file or just the filename to the + clipboard. + \li Pin files to ensure they stay at the top of the list and are not + closed when \uicontrol {Close All} is used. + \endlist + \section1 Viewing Defined Types and Symbols The \uicontrol Outline view shows an overview of defined types and other diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml index d68e021d7f..3cf02f122e 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml @@ -55,7 +55,7 @@ Section { minimumValue: 0.01 stepSize: 0.1 maximumValue: 10 - Layout.preferredWidth: 80 + Layout.preferredWidth: 100 } ExpandingSpacer { } @@ -70,7 +70,7 @@ Section { decimals: 2 minimumValue: -360 maximumValue: 360 - Layout.preferredWidth: 80 + Layout.preferredWidth: 100 } ExpandingSpacer { } @@ -84,7 +84,7 @@ Section { hasSlider: true minimumValue: -100 maximumValue: 100 - Layout.preferredWidth: 80 + Layout.preferredWidth: 100 } ExpandingSpacer { } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml index 5c7f0302a3..2dbbbff76b 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml @@ -76,6 +76,7 @@ Rectangle { typeLineEdit.forceActiveFocus() } tooltip: qsTr("Change the type of this item.") + enabled: !modelNodeBackend.multiSelection } ExpressionTextField { @@ -118,15 +119,18 @@ Rectangle { Layout.fillWidth: true showTranslateCheckBox: false showExtendedFunctionButton: false + enabled: !modelNodeBackend.multiSelection } // workaround: without this item the lineedit does not shrink to the // right size after resizing to a wider width Image { + visible: !modelNodeBackend.multiSelection Layout.preferredWidth: 16 Layout.preferredHeight: 16 source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked" ToolTipArea { + enabled: !modelNodeBackend.multiSelection anchors.fill: parent onClicked: toogleExportAlias() tooltip: qsTr("Toggles whether this item is exported as an alias property of the root item.") diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml index 143f950b38..6570497297 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml @@ -73,7 +73,7 @@ Column { SpinBox { backendValue: backendValues.border_width hasSlider: true - Layout.preferredWidth: 80 + Layout.preferredWidth: 120 } ExpandingSpacer { @@ -86,7 +86,7 @@ Column { SpinBox { backendValue: backendValues.radius hasSlider: true - Layout.preferredWidth: 80 + Layout.preferredWidth: 120 minimumValue: 0 maximumValue: Math.min(backendValues.height.value, backendValues.width.value) / 2 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml index d69490d53a..48d8ffaa53 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml @@ -24,26 +24,25 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.1 as Controls +import StudioControls 1.0 as Controls import QtQuick.Controls.Styles 1.1 Controls.CheckBox { - id: checkBox - property color textColor: colorLogic.textColor - - opacity: enabled ? 1 : 0.5 - property variant backendValue + property string tooltip - ExtendedFunctionButton { - x: 22 - anchors.verticalCenter: parent.verticalCenter + ExtendedFunctionLogic { + id: extFuncLogic backendValue: checkBox.backendValue - visible: checkBox.enabled } + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + + labelColor: colorLogic.textColor ColorLogic { id: colorLogic backendValue: checkBox.backendValue @@ -58,8 +57,4 @@ Controls.CheckBox { backendValue.value = checkBox.checked; } - style: CustomCheckBoxStyle { - } - - } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml index 203e692a82..c7d6435ad1 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: 2 - spacing: 4 - Controls.Label { - text: "S:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + 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() + } + } + } } - DoubleSpinBox { - id: saturationSlider - //value: colorButton.saturation - onValueChanged: { - if (colorButton.saturation !== value && !colorButton.block) { - colorButton.saturation = value - 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: 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() + 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() + } } } } - } - Row { - z: 0 - spacing: 4 - Controls.Label { - text: "A:" - width: 16 - color: "#eee" - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter + 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() + } + } + } } - DoubleSpinBox { - id: alphaSlider - //value: colorButton.alpha - onValueChanged: { - if (colorButton.alpha !== value && !colorButton.block) { - colorButton.alpha = 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() + } } } } } - } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml index 941d705abd..5f094dc00d 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 +Item { + id: colorCheckButtonRoot + property bool checked: false + property alias buttonColor: checkBox.color + width: 30 + height: 24 - border.color: "black" - border.width: 1 - property bool checked: false + Rectangle { + id: backgroundBox + width: 24 + height: 24 + anchors.right: parent.right - MouseArea { - anchors.fill: parent - onClicked: checkBox.checked = !checkBox.checked + 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 e2a1ba2b90..8bbb5698ef 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -25,9 +25,7 @@ import QtQuick 2.1 import QtQuick.Layouts 1.0 -import QtQuick.Controls 1.0 as Controls import QtQuickDesignerTheme 1.0 -import QtQuick.Controls.Styles 1.1 Column { id: colorEditor @@ -38,7 +36,7 @@ Column { property bool supportGradient: false - property alias caption: label.text + property string caption: "Color" property variant backendValue @@ -50,8 +48,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 +77,7 @@ Column { if (!gradientLine.isInValidState) return; - if (supportGradient && gradientLine.hasGradient) { + if (colorEditor.supportGradient && gradientLine.hasGradient) { textField.text = convertColorToString(color) gradientLine.currentColor = color } @@ -84,22 +88,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 +134,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 +156,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 +183,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 +236,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() - gradientLine.gradientTypeName = "LinearGradient" - } - gradientLine.addGradient() - } + colorEditor.resetShapeColor() - 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(); - } + if (colorEditor.shapeGradients) + gradientLine.gradientTypeName = "LinearGradient" + else + gradientLine.gradientTypeName = "Gradient" - onAccepted: { //return key - if (presetList.gradientData.stopsCount > 0) { - applyPreset(); - } + if (gradientLine.hasGradient) + gradientLine.updateGradient() + else { + gradientLine.deleteGradient() + gradientLine.addGradient() } - - } - - onDoubleClicked: { - presetList.open() } tooltip: qsTr("Linear Gradient") @@ -345,15 +330,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 +430,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 +504,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 +613,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 - width :4 } + Item { + 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 0000000000..c7256ba892 --- /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/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml index 08f76b4f25..18f30dce1c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml @@ -24,7 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.1 as Controls +import StudioControls 1.0 as Controls import QtQuick.Controls.Styles 1.1 Controls.ComboBox { @@ -32,7 +32,7 @@ Controls.ComboBox { property variant backendValue - property color textColor: colorLogic.textColor + labelColor: colorLogic.textColor property string scope: "Qt" property bool useInteger: false @@ -45,6 +45,15 @@ Controls.ComboBox { property bool block: false + ExtendedFunctionLogic { + id: extFuncLogic + backendValue: comboBox.backendValue + } + + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + ColorLogic { id: colorLogic backendValue: comboBox.backendValue @@ -84,7 +93,7 @@ Controls.ComboBox { } } - onCurrentTextChanged: { + onActivated: { if (!__isCompleted) return; @@ -106,14 +115,4 @@ Controls.ComboBox { __isCompleted = true; } - style: CustomComboBoxStyle { - textColor: comboBox.textColor - } - - ExtendedFunctionButton { - x: 2 - anchors.verticalCenter: parent.verticalCenter - backendValue: comboBox.backendValue - visible: comboBox.enabled - } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml new file mode 100644 index 0000000000..f6fdf3d2cb --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 StudioControls 1.0 as StudioControls +import StudioTheme 1.0 as StudioTheme +import QtQuickDesignerTheme 1.0 + +Item { + id: extendedFunctionButton + + property variant backendValue + property bool isBoundBackend: backendValue.isBound + property string backendExpression: backendValue.expression + + property string glyph: StudioTheme.Constants.actionIcon + property string color: StudioTheme.Constants.themeTextColor + property alias menuLoader: menuLoader + + signal reseted + + function show() { + menuLoader.show() + } + + function setIcon() { + extendedFunctionButton.color = StudioTheme.Values.themeTextColor + if (backendValue === null) { + extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon + } else if (backendValue.isBound) { + if (backendValue.isTranslated) { + // translations are a special case + extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon + } else { + extendedFunctionButton.glyph = StudioTheme.Constants.closeCross + extendedFunctionButton.color = StudioTheme.Values.themeInteraction + } + } else { + if (backendValue.complexNode !== null + && backendValue.complexNode.exists) { + + } else { + extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon + } + } + } + + onBackendValueChanged: { + setIcon() + } + + onIsBoundBackendChanged: { + setIcon() + } + + onBackendExpressionChanged: { + setIcon() + } + + Loader { + id: menuLoader + + active: false + + function show() { + active = true + item.popup() + } + + sourceComponent: Component { + StudioControls.Menu { + id: menu + + onAboutToShow: { + exportMenuItem.checked = backendValue.hasPropertyAlias() + exportMenuItem.enabled = !backendValue.isAttachedProperty() + } + + StudioControls.MenuItem { + text: qsTr("Reset") + onTriggered: { + transaction.start() + backendValue.resetValue() + backendValue.resetValue() + transaction.end() + extendedFunctionButton.reseted() + } + } + StudioControls.MenuItem { + text: qsTr("Set Binding") + onTriggered: expressionDialogLoader.show() + } + StudioControls.MenuItem { + id: exportMenuItem + text: qsTr("Export Property as Alias") + onTriggered: { + if (checked) + backendValue.exportPopertyAsAlias() + else + backendValue.removeAliasExport() + } + checkable: true + } + + StudioControls.MenuItem { + text: qsTr("Insert Keyframe") + enabled: hasActiveTimeline + onTriggered: insertKeyframe(backendValue.name) + } + } + } + } + + Loader { + id: expressionDialogLoader + parent: itemPane + anchors.fill: parent + + visible: false + active: visible + + function show() { + expressionDialogLoader.visible = true + } + + sourceComponent: Component { + Item { + id: expressionDialog + anchors.fill: parent + + Component.onCompleted: { + textField.text = backendValue.expression + textField.forceActiveFocus() + } + + Rectangle { + anchors.fill: parent + color: Theme.qmlDesignerBackgroundColorDarker() + opacity: 0.6 + } + + MouseArea { + anchors.fill: parent + onDoubleClicked: expressionDialog.visible = false + } + + Rectangle { + x: 4 + Component.onCompleted: { + var pos = itemPane.mapFromItem( + extendedFunctionButton.parent, 0, 0) + y = pos.y + 2 + } + + width: parent.width - 8 + height: 260 + + radius: 2 + color: Theme.qmlDesignerBackgroundColorDarkAlternate() + border.color: Theme.qmlDesignerBorderColor() + + Label { + x: 8 + y: 6 + font.bold: true + text: qsTr("Binding Editor") + } + ExpressionTextField { + id: textField + onRejected: expressionDialogLoader.visible = false + onAccepted: { + backendValue.expression = textField.text.trim() + expressionDialogLoader.visible = false + } + anchors.fill: parent + anchors.leftMargin: 8 + anchors.rightMargin: 8 + anchors.topMargin: 24 + anchors.bottomMargin: 32 + } + } + } + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml index 8db236176f..f1886ada43 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/Label.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml index 8498f838ac..23901e8dc9 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml @@ -28,6 +28,7 @@ import QtQuick.Controls 1.1 as Controls import QtQuick.Layouts 1.0 import QtQuick.Controls.Private 1.0 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Controls.Label { id: label @@ -40,6 +41,8 @@ Controls.Label { color: Theme.color(Theme.PanelTextColorLight) elide: Text.ElideRight + font.pixelSize: StudioTheme.Values.myFontSize + Layout.preferredWidth: width Layout.minimumWidth: width Layout.maximumWidth: width diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml index c4ff04b7f1..18b25924b3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml @@ -24,24 +24,20 @@ ****************************************************************************/ import QtQuick 2.2 -import QtQuick.Controls 1.1 as Controls +import StudioControls 1.0 as Controls import QtQuick.Controls.Styles 1.0 import QtQuickDesignerTheme 1.0 Controls.TextField { - - Controls.Action { - //Workaround to avoid that "Delete" deletes the item. - shortcut: "Delete" - } - id: lineEdit + property variant backendValue property color borderColor: "#222" property color highlightColor: "orange" - property color textColor: colorLogic.textColor + color: colorLogic.textColor property bool showTranslateCheckBox: true + translationIndicatorVisible: showTranslateCheckBox property bool writeValueManually: false @@ -58,19 +54,21 @@ Controls.TextField { if (translateFunction() === "qsTranslate") { backendValue.expression = translateFunction() + "(\"" + backendValue.getTranslationContext() - + "\", " + "\"" + trCheckbox.escapeString(text) + "\")" + + "\", " + "\"" + escapeString(text) + "\")" } else { - backendValue.expression = translateFunction() + "(\"" + trCheckbox.escapeString(text) + "\")" + backendValue.expression = translateFunction() + "(\"" + escapeString(text) + "\")" } } - ExtendedFunctionButton { - x: 4 - anchors.verticalCenter: parent.verticalCenter + ExtendedFunctionLogic { + id: extFuncLogic backendValue: lineEdit.backendValue - visible: lineEdit.enabled && showExtendedFunctionButton } + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + ColorLogic { id: colorLogic backendValue: lineEdit.backendValue @@ -102,7 +100,6 @@ Controls.TextField { } onEditingFinished: { - if (writeValueManually) return @@ -118,87 +115,35 @@ Controls.TextField { __dirty = false } - style: TextFieldStyle { - - selectionColor: Theme.color(Theme.PanelTextColorLight) - selectedTextColor: Theme.color(Theme.PanelTextColorMid) - textColor: lineEdit.textColor - placeholderTextColor: Theme.color(Theme.PanelTextColorMid) - - padding.top: 2 - padding.bottom: 2 - padding.left: 18 - padding.right: lineEdit.showTranslateCheckBox ? 16 : 1 - background: Rectangle { - implicitWidth: 100 - implicitHeight: 24 - color: Theme.qmlDesignerBackgroundColorDarker() - border.color: Theme.qmlDesignerBorderColor() - } - } - - Controls.CheckBox { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - id: trCheckbox - - - property bool isTranslated: colorLogic.backendValue.isTranslated - property bool backendValueValue: colorLogic.backendValue.value - - onIsTranslatedChanged: { - checked = lineEdit.backendValue.isTranslated - } + property bool isTranslated: colorLogic.backendValue.isTranslated - onBackendValueValueChanged: { - checked = lineEdit.backendValue.isTranslated + translationIndicator.onClicked: { + if (translationIndicator.checked) { + setTranslateExpression() + } else { + var textValue = lineEdit.text + lineEdit.backendValue.value = textValue } + colorLogic.evaluate(); + } - onClicked: { - if (trCheckbox.checked) { - setTranslateExpression() - } else { - var textValue = lineEdit.text - lineEdit.backendValue.value = textValue - } - colorLogic.evaluate(); - } + property variant backendValueValueInternal: backendValue.value + onBackendValueValueInternalChanged: { + lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated + } - function escapeString(string) { - var str = string; - str = str.replace(/\\/g, "\\\\"); - str.replace(/\"/g, "\\\""); - str = str.replace(/\t/g, "\\t"); - str = str.replace(/\r/g, "\\r"); - str = str.replace(/\n/g, '\\n'); - return str; - } + onIsTranslatedChanged: { + lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated + } - visible: showTranslateCheckBox - - - style: CheckBoxStyle { - spacing: 8 - indicator: Item { - implicitWidth: 15 - implicitHeight: 15 - x: 7 - y: 1 - Rectangle { - anchors.fill: parent - border.color: Theme.qmlDesignerBorderColor() - color: Theme.qmlDesignerBackgroundColorDarker() - opacity: control.hovered || control.pressed ? 1 : 0.75 - } - Image { - x: 1 - y: 1 - width: 13 - height: 13 - source: "image://icons/tr" - opacity: control.checked ? 1 : 0.3; - } - } - } + function escapeString(string) { + var str = string; + str = str.replace(/\\/g, "\\\\"); + str.replace(/\"/g, "\\\""); + str = str.replace(/\t/g, "\\t"); + str = str.replace(/\r/g, "\\r"); + str = str.replace(/\n/g, '\\n'); + return str; } + } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index b7c2664bdc..10b09287b7 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -27,6 +27,7 @@ import QtQuick 2.1 import QtQuick.Controls 1.1 as Controls import QtQuick.Layouts 1.0 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Item { id: section @@ -54,6 +55,7 @@ Item { color: Theme.color(Theme.PanelTextColorLight) x: 22 font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize } Image { 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 0000000000..c6b6acf242 --- /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/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml index cc50509cc0..196974d103 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml @@ -24,42 +24,77 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.1 as Controls import QtQuick.Controls.Styles 1.1 +import StudioControls 1.0 as StudioControls -Controls.SpinBox { - id: spinBox +Item { + id: wrapper - property color textColor: colorLogic.textColor - property variant backendValue; + property alias decimals: spinBox.decimals + property alias hasSlider: spinBox.hasSlider - implicitWidth: 74 + property real minimumValue: 0.0 + property real maximumValue: 99 + property real stepSize: 1.0 - ExtendedFunctionButton { - x: 4 - anchors.verticalCenter: parent.verticalCenter - backendValue: spinBox.backendValue - visible: spinBox.enabled - } + property alias backendValue: spinBox.backendValue - ColorLogic { - id: colorLogic - backendValue: spinBox.backendValue - onValueFromBackendChanged: { - spinBox.value = valueFromBackend; - } - } + width: 120 + implicitHeight: spinBox.height - property bool hasSlider: false + property bool __initialized: false - height: hasSlider ? 32 : implicitHeight + Component.onCompleted: { + wrapper.__initialized = true - onValueChanged: { - if (backendValue.value !== value) - backendValue.value = value; + convert("stepSize", stepSize) + convert("from", minimumValue) + convert("to", maximumValue) } - style: CustomSpinBoxStyle { + onStepSizeChanged: convert("stepSize", stepSize) + onMinimumValueChanged: convert("from", minimumValue) + onMaximumValueChanged: convert("to", maximumValue) + + function convert(target, value) { + if (!wrapper.__initialized) + return + spinBox[target] = Math.round(value * spinBox.factor) } + StudioControls.SpinBox { + id: spinBox + + property real realValue: value / factor + property variant backendValue + property bool hasSlider: false + + from: minimumValue * factor + to: maximumValue * factor + width: wrapper.width + + ExtendedFunctionLogic { + id: extFuncLogic + backendValue: spinBox.backendValue + } + + actionIndicator.icon.color: extFuncLogic.color + actionIndicator.icon.text: extFuncLogic.glyph + actionIndicator.onClicked: extFuncLogic.show() + + ColorLogic { + id: colorLogic + backendValue: spinBox.backendValue + onValueFromBackendChanged: { + spinBox.value = valueFromBackend * spinBox.factor; + } + } + + textColor: colorLogic.textColor + + onCompressedValueModified: { + if (backendValue.value !== realValue) + backendValue.value = realValue; + } + } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml index 22c1923fad..b5e0ac0221 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml @@ -27,6 +27,7 @@ import QtQuick 2.1 import QtQuick.Controls 1.0 as Controls import QtQuick.Controls.Styles 1.1 import QtQuickDesignerTheme 1.0 +import StudioTheme 1.0 as StudioTheme Controls.TabView { id: root @@ -42,6 +43,7 @@ Controls.TabView { Text { id: text font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize anchors.centerIn: parent anchors.verticalCenterOffset: -1 text: styleData.title diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir index 43e4da7636..9480f1d9a3 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/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml new file mode 100644 index 0000000000..3241eb405d --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.AbstractButton { + id: myButton + + property alias buttonIcon: buttonIcon.text + property alias backgroundVisible: buttonBackground.visible + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + height: StudioTheme.Values.height + width: StudioTheme.Values.height + z: myButton.checked ? 10 : 3 + activeFocusOnTab: false // TODO Decision pending. Focus for AbstractButtons? + + background: Rectangle { + id: buttonBackground + color: myButton.checked ? StudioTheme.Values.themeControlBackgroundChecked : StudioTheme.Values.themeControlBackground + border.color: myButton.checked ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } + + indicator: Item { + x: 0 + y: 0 + implicitWidth: myButton.width + implicitHeight: myButton.height + + T.Label { + id: buttonIcon + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + renderType: Text.QtRendering + } + } + + states: [ + State { + name: "default" + when: myButton.enabled && !myButton.hovered && !myButton.pressed + && !myButton.checked + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackground + } + PropertyChanges { + target: myButton + z: 3 + } + }, + State { + name: "hovered" + when: myButton.hovered && !myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: myButton.hovered && myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundPressed + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: myButton + z: 10 + } + }, + State { + name: "disabled" + when: !myButton.enabled + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml new file mode 100644 index 0000000000..e263f9337a --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: actionIndicator + + property Item myControl + + property alias icon: actionIndicatorIcon + + property bool hover: false + property bool pressed: false + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + state: "default" + + implicitWidth: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + + signal clicked + + T.Label { + id: actionIndicatorIcon + anchors.fill: parent + text: StudioTheme.Constants.actionIcon + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + MouseArea { + id: actionIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: actionIndicator.hover = containsMouse + onClicked: actionIndicator.clicked() + } + + states: [ + State { + name: "default" + when: myControl.enabled && !actionIndicator.hover + && !actionIndicator.pressed && !myControl.hover + && !myControl.activeFocus && !myControl.drag + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "hovered" + when: actionIndicator.hover && !actionIndicator.pressed + && !myControl.activeFocus && !myControl.drag + PropertyChanges { + target: actionIndicatorIcon + scale: 1.2 + } + }, + State { + name: "globalHover" + when: myControl.hover && !actionIndicator.hover + && !actionIndicator.pressed && !myControl.activeFocus + && !myControl.drag + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: myControl.activeFocus + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: actionIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml new file mode 100644 index 0000000000..40713d3ed1 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +ButtonRow { + id: myButtonRow + + property alias buttonIcon: myAbstractButton.buttonIcon + property alias checkable: myAbstractButton.checkable + + AbstractButton { + id: myAbstractButton + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml new file mode 100644 index 0000000000..1b233c590b --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T + +T.ButtonGroup { + +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml new file mode 100644 index 0000000000..614847f340 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Layouts 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Row { + // TODO When using Item as root it won't react to outer layout + id: myButtonGroup + + property alias actionIcon: actionIndicator.icon + + //property bool hover: myCheckBox.hovered // TODO + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + ActionIndicator { + id: actionIndicator + myControl: myButtonGroup // TODO global hover issue. Can be solved with extra property in ActionIndicator + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + spacing: -StudioTheme.Values.border // TODO Which one is better? Spacing vs. layout function. ALso depends on root item +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml new file mode 100644 index 0000000000..2f122a7b89 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.CheckBox { + id: myCheckBox + + property alias actionIndicator: actionIndicator + + property bool hover: myCheckBox.hovered // TODO two underscores + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property alias labelVisible: checkBoxLabel.visible + property alias labelColor: checkBoxLabel.color + + font.pixelSize: StudioTheme.Values.myFontSize + + height: StudioTheme.Values.height + width: StudioTheme.Values.height * 5 + + spacing: StudioTheme.Values.checkBoxSpacing + hoverEnabled: true + activeFocusOnTab: false // TODO Decision pending. Focus for CheckBoxes? + + contentItem: T.Label { + id: checkBoxLabel + leftPadding: 0 + rightPadding: 0 + + width: 20 // TODO Not working + elide: Text.ElideRight + + verticalAlignment: Text.AlignVCenter + text: myCheckBox.text + font: myCheckBox.font + color: StudioTheme.Values.themeTextColor + } + + ActionIndicator { + id: actionIndicator + myControl: myCheckBox // TODO global hover issue. Can be solved with extra property in ActionIndicator + + x: checkBoxLabel.visible ? checkBoxLabel.contentWidth + + (myCheckBox.spacing + * StudioTheme.Values.scaleFactor) : 0 // TODO scale factor + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + indicator: Rectangle { + id: checkBoxBackground + x: actionIndicator.x + actionIndicator.width + - (actionIndicator.visible ? StudioTheme.Values.border : 0) + y: 0 + z: 5 + implicitWidth: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + T.Label { + id: checkBoxIcon + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + text: StudioTheme.Constants.tickIcon + visible: myCheckBox.checkState === Qt.Checked + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + + /* + // Tristate only + Rectangle { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: 16 + height: 3 + color: myCheckBox.palette.text + visible: myCheckBox.checkState === Qt.PartiallyChecked + } +*/ + } + + states: [ + State { + name: "default" + when: myCheckBox.enabled && !myCheckBox.hovered + && !myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: myCheckBox.hovered && !myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: myCheckBox.hovered && myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myCheckBox.enabled + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: checkBoxIcon + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: checkBoxLabel + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml new file mode 100644 index 0000000000..73788710bd --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: checkIndicator + + property T.Control myControl + property T.Popup myPopup + + property bool hover: false + property bool checked: false + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + state: "default" + + Connections { + target: myPopup + onClosed: checkIndicator.checked = false + onOpened: checkIndicator.checked = true + } + + MouseArea { + id: checkIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: checkIndicator.hover = checkIndicatorMouseArea.containsMouse + onPressed: { + myControl.forceActiveFocus() // TODO + myPopup.opened ? myPopup.close() : myPopup.open() + } + } + + T.Label { + id: checkIndicatorIcon + anchors.fill: parent + color: StudioTheme.Values.themeTextColor + text: StudioTheme.Constants.upDownSquare2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(checkIndicator.hover + || myControl.hover) + && !checkIndicator.checked && !myControl.activeFocus + && !myControl.drag + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "hovered" + when: (checkIndicator.hover || myControl.hover) + && !checkIndicator.checked && !myControl.activeFocus + && !myControl.drag + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "checked" + when: checkIndicator.checked + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.activeFocus && !checkIndicator.checked + && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: myControl.drag && !checkIndicator.checked + && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: checkIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml new file mode 100644 index 0000000000..3ee5a02b7c --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Window 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ComboBox { + id: myComboBox + + property alias actionIndicator: actionIndicator + + property alias labelColor: comboBoxInput.color + + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property string __lastAcceptedText: "" + signal compressedActivated + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: popupIndicator.width - StudioTheme.Values.border + font.pixelSize: StudioTheme.Values.myFontSize + wheelEnabled: false + + onFocusChanged: { + if (!focus) + comboBoxPopup.close() + } + + ActionIndicator { + id: actionIndicator + myControl: myComboBox + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + contentItem: ComboBoxInput { + id: comboBoxInput + myControl: myComboBox + text: myComboBox.editText + } + + indicator: CheckIndicator { + id: popupIndicator + myControl: myComboBox + myPopup: myComboBox.popup + x: comboBoxInput.x + comboBoxInput.width - StudioTheme.Values.border + y: 0 + width: StudioTheme.Values.squareComponentWidth + height: StudioTheme.Values.height + } + + background: Rectangle { + id: comboBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + width: myComboBox.width + height: myComboBox.height + } + + // Set the initial value for __lastAcceptedText + Component.onCompleted: __lastAcceptedText = myComboBox.editText + + onAccepted: { + if (myComboBox.editText != __lastAcceptedText) { + var pos = find(myComboBox.editText) + activated(pos) + } + __lastAcceptedText = myComboBox.editText + } + + Timer { + id: myTimer + repeat: false + running: false + interval: 100 + onTriggered: myComboBox.compressedActivated() + } + + onActivated: myTimer.restart() + + delegate: ItemDelegate { + id: myItemDelegate + + width: comboBoxPopup.width - comboBoxPopup.leftPadding - comboBoxPopup.rightPadding + - (comboBoxPopupScrollBar.visible ? comboBoxPopupScrollBar.contentItem.implicitWidth + + 2 : 0) // TODO Magic number + height: StudioTheme.Values.height - 2 * StudioTheme.Values.border + padding: 0 + + contentItem: Text { + leftPadding: itemDelegateIconArea.width + text: modelData + color: StudioTheme.Values.themeTextColor + font: myComboBox.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + + Item { + id: itemDelegateIconArea + width: myItemDelegate.height + height: myItemDelegate.height + + T.Label { + id: itemDelegateIcon + text: StudioTheme.Constants.tickIcon + color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeInteraction + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + visible: myComboBox.currentIndex === index ? true : false + anchors.fill: parent + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + highlighted: myComboBox.highlightedIndex === index + + background: Rectangle { + id: itemDelegateBackground + x: 0 + y: 0 + width: myItemDelegate.width + height: myItemDelegate.height + color: myItemDelegate.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + } + } + + popup: T.Popup { + id: comboBoxPopup + x: comboBoxInput.x + y: myComboBox.height - StudioTheme.Values.border + width: comboBoxInput.width + popupIndicator.width - StudioTheme.Values.border + // TODO Setting the height on the popup solved the problem with the popup of height 0, + // but it has the problem that it sometimes extend over the border of the actual window + // and is then cut off. + height: Math.min(contentItem.implicitHeight + comboBoxPopup.topPadding + + comboBoxPopup.bottomPadding, + myComboBox.Window.height - topMargin - bottomMargin, + StudioTheme.Values.maxComboBoxPopupHeight) + padding: StudioTheme.Values.border + margins: 0 // If not defined margin will be -1 + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: myComboBox.popup.visible ? myComboBox.delegateModel : null + currentIndex: myComboBox.highlightedIndex + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar { + id: comboBoxPopupScrollBar + } + } + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + border.width: StudioTheme.Values.border + } + + enter: Transition { + } + exit: Transition { + } + } + + states: [ + State { + name: "default" + when: !myComboBox.hover && !myComboBox.activeFocus + PropertyChanges { + target: myComboBox + wheelEnabled: false + } + PropertyChanges { + target: comboBoxInput + selectByMouse: false + } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "focus" + when: myComboBox.activeFocus && !myComboBox.editable + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + focus: true + } + }, + State { + name: "edit" + when: myComboBox.activeFocus && myComboBox.editable + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + selectByMouse: true + } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + } + ] + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + myComboBox.focus = false + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml new file mode 100644 index 0000000000..06e6ecb2b6 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: false + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + Rectangle { + id: textInputArea + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + if (textInput.readOnly) { + if (myControl.popup.opened) { + myControl.popup.close() + } else { + myControl.popup.open() + myControl.forceActiveFocus() + } + } else { + textInput.forceActiveFocus() + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.activeFocus + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.activeFocus && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "focus" + when: textInput.activeFocus && !myControl.editable + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: textInput.activeFocus && myControl.editable + extend: "focus" + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml new file mode 100644 index 0000000000..ba5fec19e2 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Controls 2.12 as Controls2 + +Menu { + id: contextMenu + + property Item myTextEdit + + Controls2.Action { + text: "Undo" + enabled: myTextEdit.canUndo + onTriggered: myTextEdit.undo() + shortcut: StandardKey.Undo + } + Controls2.Action { + text: "Redo" + enabled: myTextEdit.canRedo + onTriggered: myTextEdit.redo() + shortcut: StandardKey.Redo + } + + MenuSeparator { + } + + Controls2.Action { + text: "Copy" + enabled: myTextEdit.selectedText !== "" + onTriggered: myTextEdit.copy() + shortcut: StandardKey.Copy + } + Controls2.Action { + text: "Cut" + enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly + onTriggered: myTextEdit.cut() + shortcut: StandardKey.Cut + } + Controls2.Action { + text: "Paste" + enabled: myTextEdit.canPaste + onTriggered: myTextEdit.paste() + shortcut: StandardKey.Paste + } + Controls2.Action { + text: "Delete" + enabled: myTextEdit.selectedText !== "" + onTriggered: myTextEdit.remove(myTextEdit.selectionStart, + myTextEdit.selectionEnd) + shortcut: StandardKey.Delete + } + Controls2.Action { + text: "Clear" + enabled: myTextEdit.text !== "" + onTriggered: myTextEdit.clear() + shortcut: StandardKey.DeleteCompleteLine + } + + MenuSeparator { + } + + Controls2.Action { + text: "Select All" + enabled: myTextEdit.text !== "" + && myTextEdit.selectedText !== myTextEdit.text + onTriggered: myTextEdit.selectAll() + shortcut: StandardKey.SelectAll + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml new file mode 100644 index 0000000000..9e48128c49 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Layouts 1.12 + +Item { + Layout.fillWidth: true +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml new file mode 100644 index 0000000000..c2190c5d83 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T + +T.ItemDelegate { + +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml new file mode 100644 index 0000000000..f9db27c6ac --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Window 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Menu { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + font.family: StudioTheme.Constants.font.family + font.pixelSize: StudioTheme.Values.myFontSize + + margins: 0 + overlap: 1 + padding: 0 + + delegate: MenuItem { + } + + contentItem: ListView { + model: control.contentModel + interactive: Window.window ? contentHeight > Window.window.height : false + clip: false + currentIndex: control.currentIndex + } + + background: Rectangle { + implicitWidth: contentItem.childrenRect.width + implicitHeight: contentItem.childrenRect.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml new file mode 100644 index 0000000000..ff3c139679 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme +import QtQuick.Controls 2.12 + +T.MenuItem { + id: control + + property int labelSpacing: StudioTheme.Values.contextMenuLabelSpacing + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max( + implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 0 + spacing: 0 + horizontalPadding: StudioTheme.Values.contextMenuHorizontalPadding + action: Action {} + + contentItem: Item { + id: menuItem + + width: control.menu.width + height: StudioTheme.Values.height + + Text { + id: textLabel + text: control.text + font: control.font + color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled + anchors.verticalCenter: parent.verticalCenter + } + + Text { + id: shortcutLabel + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: shortcut.nativeText + font: control.font + color: textLabel.color + + Shortcut { + id: shortcut + property int shortcutWorkaround: control.action.shortcut ? control.action.shortcut : 0 + sequence: shortcutWorkaround + } + } + } + + background: Rectangle { + implicitWidth: textLabel.implicitWidth + control.labelSpacing + shortcutLabel.implicitWidth + + control.leftPadding + control.rightPadding // TODO + implicitHeight: StudioTheme.Values.height + x: StudioTheme.Values.border + y: StudioTheme.Values.border + width: control.width - (StudioTheme.Values.border * 2) + height: control.height - (StudioTheme.Values.border * 2) + color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml new file mode 100644 index 0000000000..4e226f5c58 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.MenuSeparator { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 0 + verticalPadding: padding + + contentItem: Rectangle { + implicitWidth: 10 + implicitHeight: StudioTheme.Values.border + color: StudioTheme.Values.themeControlOutline + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml new file mode 100644 index 0000000000..886e92206b --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollBar { + id: control + + // This needs to be set, when using T.ScrollBar + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + active: true + interactive: true + visible: control.size < 1.0 || T.ScrollBar.AlwaysOn + + snapMode: T.ScrollBar.SnapAlways // TODO + policy: T.ScrollBar.AsNeeded + + padding: 1 // TODO 0 + size: 1.0 + position: 1.0 + //orientation: Qt.Vertical + + contentItem: Rectangle { + id: controlHandle + implicitWidth: 4 + implicitHeight: 4 + radius: width / 2 // TODO 0 + color: StudioTheme.Values.themeScrollBarHandle + } + + background: Rectangle { + id: controlTrack + color: StudioTheme.Values.themeScrollBarTrack + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml new file mode 100644 index 0000000000..bf1b3937b9 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollView { + id: control + + property alias horizontalThickness: horizontalScrollBar.height + property alias verticalThickness: verticalScrollBar.width + property bool bothVisible: verticalScrollBar.visible + && horizontalScrollBar.visible + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + ScrollBar.vertical: ScrollBar { + id: verticalScrollBar + parent: control + x: control.width - width - StudioTheme.Values.border + y: StudioTheme.Values.border + height: control.availableHeight - 2 * StudioTheme.Values.border + - (bothVisible ? horizontalThickness : 0) + active: control.ScrollBar.horizontal.active + } + + ScrollBar.horizontal: ScrollBar { + id: horizontalScrollBar + parent: control + x: StudioTheme.Values.border + y: control.height - height - StudioTheme.Values.border + width: control.availableWidth - 2 * StudioTheme.Values.border + - (bothVisible ? verticalThickness : 0) + active: control.ScrollBar.vertical.active + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml new file mode 100644 index 0000000000..d5c917f5ce --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Layouts 1.12 + +RowLayout { + Layout.fillWidth: true + spacing: 4 +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml new file mode 100644 index 0000000000..98a163a322 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Layouts 1.12 +import StudioTheme 1.0 as StudioTheme + +Item { + id: section + property alias caption: label.text + property int leftPadding: 8 + property int topPadding: 4 + property int rightPadding: 0 + + property int animationDuration: 0 + + property bool expanded: true + + clip: true + + Rectangle { + id: header + height: StudioTheme.Values.height + + anchors.left: parent.left + anchors.right: parent.right + + color: StudioTheme.Values.themeControlBackground + + SectionLabel { + id: label + anchors.verticalCenter: parent.verticalCenter + color: StudioTheme.Values.themeTextColor + x: 22 + //font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize + // TODO font size? + } + + SectionLabel { + id: arrow + width: StudioTheme.Values.spinControlIconSizeMulti + height: StudioTheme.Values.spinControlIconSizeMulti + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + anchors.left: parent.left + anchors.leftMargin: 4 + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + Behavior on rotation { + NumberAnimation { + easing.type: Easing.OutCubic + duration: animationDuration + } + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + section.animationDuration = 120 + section.expanded = !section.expanded + if (!section.expanded) // TODO + section.forceActiveFocus() + } + } + } + + default property alias __content: row.children + + readonly property alias contentItem: row + + implicitHeight: Math.round(row.height + header.height) + + Row { + id: row + anchors.left: parent.left + anchors.leftMargin: leftPadding + anchors.right: parent.right + anchors.rightMargin: rightPadding + anchors.top: header.bottom + anchors.topMargin: topPadding + } + + Behavior on implicitHeight { + NumberAnimation { + easing.type: Easing.OutCubic + duration: animationDuration + } + } + + states: [ + State { + name: "Collapsed" + when: !section.expanded + PropertyChanges { + target: section + implicitHeight: header.height + } + PropertyChanges { + target: arrow + rotation: -90 + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml new file mode 100644 index 0000000000..73fec21ce0 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.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.12 +import QtQuick.Layouts 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Label { + id: label + + //property alias tooltip: toolTipArea.tooltip + // workaround because PictureSpecifics.qml still use this + //property alias toolTip: toolTipArea.tooltip + + width: Math.max(Math.min(240, parent.width - 220), 80) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.myFontSize // TODO + elide: Text.ElideRight + + Layout.preferredWidth: width + Layout.minimumWidth: width + Layout.maximumWidth: width +/* + ToolTipArea { + id: toolTipArea + anchors.fill: parent + tooltip: label.text + } +*/ +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml new file mode 100644 index 0000000000..22054feebb --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Layouts 1.12 + +GridLayout { + columns: 2 + columnSpacing: 12 + rowSpacing: 4 + width: parent.width - 16 +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml new file mode 100644 index 0000000000..955d73d6c7 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Shapes 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Slider { + id: slider + + property int decimals: 0 + property bool labels: true + property bool tickMarks: false + property real tickMarkStepSize: 0.0 // StepSize bug QTBUG-76136 + property real tickMarkWidth: 1.0 + property real tickMarkHeight: 4.0 + readonly property int tickMarkCount: tickMarkStepSize + !== 0.0 ? (to - from) / tickMarkStepSize + 1 : 0 + readonly property real tickMarkSpacing: tickMarkCount + !== 0 ? (sliderTrack.width - tickMarkWidth + * tickMarkCount) / (tickMarkCount - 1) : 0.0 + + property string __activeColor: StudioTheme.Values.themeSliderActiveTrack + property string __inactiveColor: StudioTheme.Values.themeSliderInactiveTrack + + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitHandleWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitHandleHeight + topPadding + bottomPadding, + StudioTheme.Values.height) + padding: 0 + leftPadding: actionIndicator.width + - (actionIndicatorVisible ? StudioTheme.Values.border + - StudioTheme.Values.sliderPadding : 0) + + wheelEnabled: false + + ActionIndicator { + id: actionIndicator + myControl: slider + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + handle: Rectangle { + id: sliderHandle + x: slider.leftPadding + (slider.visualPosition * slider.availableWidth) + - sliderHandle.width / 2 + y: slider.topPadding + slider.availableHeight / 2 - sliderHandle.height / 2 + z: 20 + implicitWidth: StudioTheme.Values.sliderHandleWidth + implicitHeight: StudioTheme.Values.sliderHandleHeight + color: StudioTheme.Values.themeSliderHandle + + Shape { + id: sliderHandleLabelPointer + + property real __width: StudioTheme.Values.sliderPointerWidth + property real __height: StudioTheme.Values.sliderPointerHeight + property bool antiAlias: true + + layer.enabled: antiAlias + layer.smooth: antiAlias + layer.textureSize: Qt.size(width * 2, height * 2) + + implicitWidth: __width + implicitHeight: __height + + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: sliderHandleLabelBackground.bottom + + ShapePath { + id: sliderHandleLabelPointerPath + strokeColor: "transparent" + strokeWidth: 0 + fillColor: StudioTheme.Values.themeInteraction + + startX: 0 + startY: 0 + + PathLine { + x: sliderHandleLabelPointer.__width + y: 0 + } + PathLine { + x: sliderHandleLabelPointer.__width / 2 + y: sliderHandleLabelPointer.__height + } + } + } + + Rectangle { + id: sliderHandleLabelBackground + x: -(sliderHandleLabelBackground.width / 2) + (sliderHandle.width / 2) + width: makeEven( + sliderHandleLabel.width + StudioTheme.Values.inputHorizontalPadding) + height: sliderHandleLabel.height + anchors.bottom: parent.top + anchors.bottomMargin: StudioTheme.Values.sliderMargin + color: StudioTheme.Values.themeInteraction + + Text { + id: sliderHandleLabel + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + text: Number.parseFloat(slider.value).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + } + } + } + + function makeEven(value) { + var v = Math.round(value) + return (v % 2 === 0) ? v : v + 1 + } + + background: Rectangle { + id: sliderTrack + x: slider.leftPadding + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + color: __inactiveColor + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: __activeColor + } + } + + Item { + id: tickmarkBounds + x: sliderTrack.x + y: sliderTrack.y + + Text { + id: tickmarkFromLabel + x: 0 + y: StudioTheme.Values.sliderPadding + text: Number.parseFloat(slider.from).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + visible: slider.labels + } + + Text { + id: tickmarkToLabel + x: slider.availableWidth - width + y: StudioTheme.Values.sliderPadding + text: Number.parseFloat(slider.to).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + visible: slider.labels + } + + Row { + id: tickmarkRow + spacing: tickMarkSpacing + visible: slider.tickMarks + + Repeater { + id: tickmarkRepeater + model: tickMarkCount + delegate: Rectangle { + implicitWidth: tickMarkWidth + implicitHeight: StudioTheme.Values.sliderTrackHeight + color: x < (slider.visualPosition + * slider.availableWidth) ? __inactiveColor : __activeColor + } + } + } + } + + MouseArea { + id: mouseArea + x: actionIndicator.width + y: 0 + width: slider.width - actionIndicator.width + height: slider.height + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: slider.hover = containsMouse + onPressed: mouse.accepted = false + } + + states: [ + State { + name: "default" + when: slider.enabled && !slider.hover && !slider.activeFocus + PropertyChanges { + target: slider + wheelEnabled: false + } + }, + State { + name: "hovered" + when: slider.enabled && slider.hover && !slider.activeFocus + PropertyChanges { + target: slider + __activeColor: StudioTheme.Values.themeSliderActiveTrackHover + __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackHover + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeSliderHandleHover + } + }, + State { + name: "focus" + when: slider.enabled && slider.activeFocus + PropertyChanges { + target: slider + wheelEnabled: true + __activeColor: StudioTheme.Values.themeSliderActiveTrackFocus + __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackFocus + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeSliderHandleFocus + } + }, + State { + name: "disabled" + when: !slider.enabled + PropertyChanges { + target: tickmarkFromLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: tickmarkToLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: sliderHandleLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: slider + __activeColor: StudioTheme.Values.themeControlBackgroundDisabled + __inactiveColor: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandleLabelBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandleLabelPointerPath + fillColor: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeControlBackgroundDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml new file mode 100644 index 0000000000..27e8185da3 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Popup { + id: sliderPopup + + property T.Control myControl + + dim: false + + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + } + + contentItem: T.Slider { + id: slider + anchors.fill: parent + + bottomPadding: 0 + topPadding: 0 + rightPadding: 3 + leftPadding: 3 + + from: myControl.from + value: myControl.value + to: myControl.to + + focusPolicy: Qt.NoFocus + + handle: Rectangle { + x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width) + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: StudioTheme.Values.sliderHandleWidth + height: StudioTheme.Values.sliderHandleHeight + radius: 0 + color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + } + + background: Rectangle { + x: slider.leftPadding + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + radius: 0 + color: StudioTheme.Values.themeSliderInactiveTrack + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: StudioTheme.Values.themeSliderActiveTrack + radius: 0 + } + } + + onMoved: { + myControl.value = value + myControl.valueModified() + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml new file mode 100644 index 0000000000..ef98c0f9ff --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.SpinBox { + id: mySpinBox + + property alias textColor: spinBoxInput.color + property alias actionIndicator: actionIndicator + + property int decimals: 0 + property int factor: Math.pow(10, decimals) + + property real defaultStepSize: 1 + property real minStepSize: 1 + property real maxStepSize: 10 + + property bool edit: false + property bool hover: false // This property is used to indicate the global hover state + property bool drag: false + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property bool spinBoxIndicatorVisible: true + property real __spinBoxIndicatorWidth: StudioTheme.Values.smallRectWidth - 2 + * StudioTheme.Values.border + property real __spinBoxIndicatorHeight: StudioTheme.Values.height / 2 + - StudioTheme.Values.border + + property alias sliderIndicatorVisible: sliderIndicator.visible + property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __sliderIndicatorHeight: StudioTheme.Values.height + + signal compressedValueModified + + // Use custom wheel handling due to bugs + property bool __wheelEnabled: false + wheelEnabled: false + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width + - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border) + rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0) + + font.pixelSize: StudioTheme.Values.myFontSize + editable: true + validator: mySpinBox.decimals ? doubleValidator : intValidator + + DoubleValidator { + id: doubleValidator + locale: mySpinBox.locale.name + notation: DoubleValidator.StandardNotation + decimals: mySpinBox.decimals + bottom: Math.min(mySpinBox.from, mySpinBox.to) / factor + top: Math.max(mySpinBox.from, mySpinBox.to) / factor + } + + IntValidator { + id: intValidator + locale: mySpinBox.locale.name + bottom: Math.min(mySpinBox.from, mySpinBox.to) + top: Math.max(mySpinBox.from, mySpinBox.to) + } + + Connections { + target: spinBoxInput + onActiveFocusChanged: mySpinBox.edit = spinBoxInput.activeFocus + } + + ActionIndicator { + id: actionIndicator + myControl: mySpinBox + + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + up.indicator: SpinBoxIndicator { + id: spinBoxIndicatorUp + myControl: mySpinBox + + visible: spinBoxIndicatorVisible + //hover: mySpinBox.up.hovered // TODO QTBUG-74688 + pressed: mySpinBox.up.pressed + iconFlip: -1 + + x: actionIndicator.width + (actionIndicator.visible ? 0 : StudioTheme.Values.border) + y: StudioTheme.Values.border + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + } + + down.indicator: SpinBoxIndicator { + id: spinBoxIndicatorDown + myControl: mySpinBox + + visible: spinBoxIndicatorVisible + //hover: mySpinBox.down.hovered // TODO QTBUG-74688 + pressed: mySpinBox.down.pressed + + x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + } + + contentItem: SpinBoxInput { + id: spinBoxInput + myControl: mySpinBox + } + + background: Rectangle { + id: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + width: mySpinBox.width + height: mySpinBox.height + } + + CheckIndicator { + id: sliderIndicator + myControl: mySpinBox + myPopup: sliderPopup + + x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border + width: sliderIndicator.visible ? __sliderIndicatorWidth : 0 + height: sliderIndicator.visible ? __sliderIndicatorHeight : 0 + visible: false // reasonable default + } + + SliderPopup { + id: sliderPopup + myControl: mySpinBox + + x: spinBoxInput.x + y: StudioTheme.Values.height - StudioTheme.Values.border + width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border + height: StudioTheme.Values.sliderHeight + + enter: Transition { + } + exit: Transition { + } + } + + textFromValue: function (value, locale) { + return Number(value / factor).toLocaleString(locale, 'f', + mySpinBox.decimals) + } + + valueFromText: function (text, locale) { + return Number.fromLocaleString(locale, text) * factor + } + + states: [ + State { + name: "default" + when: mySpinBox.enabled && !mySpinBox.hover + && !mySpinBox.activeFocus && !mySpinBox.drag + PropertyChanges { + target: mySpinBox + __wheelEnabled: false + } + PropertyChanges { + target: spinBoxInput + selectByMouse: false + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: spinBoxInput.activeFocus + PropertyChanges { + target: mySpinBox + __wheelEnabled: true + } + PropertyChanges { + target: spinBoxInput + selectByMouse: true + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: mySpinBox.drag + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !mySpinBox.enabled + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutlineDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + onActiveFocusChanged: { + if (mySpinBox.activeFocus) + // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + spinBoxInput.selectAll() + + if (sliderPopup.opened && !activeFocus) + sliderPopup.close() + } + + onFocusChanged: { + // FIX: This is a temporary fix for QTBUG-74239 + var currValue = mySpinBox.value + + if (!spinBoxInput.acceptableInput) + mySpinBox.value = clamp(valueFromText(spinBoxInput.text, + mySpinBox.locale), + mySpinBox.validator.bottom * factor, + mySpinBox.validator.top * factor) + else + mySpinBox.value = valueFromText(spinBoxInput.text, mySpinBox.locale) + + if (spinBoxInput.text !== mySpinBox.displayText) + spinBoxInput.text = mySpinBox.displayText + + if (mySpinBox.value !== currValue) + mySpinBox.valueModified() + } + + onDisplayTextChanged: { + spinBoxInput.text = mySpinBox.displayText + } + + Timer { + id: myTimer + repeat: false + running: false + interval: 100 + onTriggered: mySpinBox.compressedValueModified() + } + + onValueModified: myTimer.restart() + + Keys.onPressed: { + if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) { + event.accepted = true + + mySpinBox.stepSize = defaultStepSize + + if (event.modifiers & Qt.ControlModifier) + mySpinBox.stepSize = minStepSize + + if (event.modifiers & Qt.ShiftModifier) + mySpinBox.stepSize = maxStepSize + + var val = mySpinBox.valueFromText(spinBoxInput.text, + mySpinBox.locale) + if (mySpinBox.value !== val) + mySpinBox.value = val + + var curValue = mySpinBox.value + + if (event.key === Qt.Key_Up) + mySpinBox.increase() + else + mySpinBox.decrease() + + if (curValue !== mySpinBox.value) + mySpinBox.valueModified() + } + + if (event.key === Qt.Key_Escape) + mySpinBox.focus = false + + // FIX: This is a temporary fix for QTBUG-74239 + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + var currValue = mySpinBox.value + + if (!spinBoxInput.spinBoxInput) + mySpinBox.value = clamp(valueFromText(spinBoxInput.text, + mySpinBox.locale), + mySpinBox.validator.bottom * factor, + mySpinBox.validator.top * factor) + else + mySpinBox.value = valueFromText(spinBoxInput.text, + mySpinBox.locale) + + if (spinBoxInput.text !== mySpinBox.displayText) + spinBoxInput.text = mySpinBox.displayText + + if (mySpinBox.value !== currValue) + mySpinBox.valueModified() + } + } + + function clamp(v, lo, hi) { + if (v < lo || v > hi) + return Math.min(Math.max(lo, v), hi) + + return v + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml new file mode 100644 index 0000000000..ab1e90f386 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: spinBoxIndicator + + property T.Control myControl + + property bool hover: false + property bool pressed: false + + property alias iconFlip: spinBoxIndicatorIconScale.yScale + + color: StudioTheme.Values.themeControlBackground + border.width: 0 + + // This MouseArea is a workaround to avoid some hover state related bugs + // when using the actual signal 'up.hovered'. QTBUG-74688 + MouseArea { + id: spinBoxIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: spinBoxIndicator.hover = containsMouse + onPressed: mouse.accepted = false + } + + T.Label { + id: spinBoxIndicatorIcon + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + anchors.fill: parent + transform: Scale { + id: spinBoxIndicatorIconScale + origin.x: 0 + origin.y: spinBoxIndicatorIcon.height / 2 + yScale: 1 + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(spinBoxIndicator.hover + || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: (spinBoxIndicator.hover || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.edit + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusEdit + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusDrag + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml new file mode 100644 index 0000000000..599f6fd5b5 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: false + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignRight + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + // TextInput foucs needs to be set to activeFocus whenever it changes, + // otherwise TextInput will get activeFocus whenever the parent SpinBox gets + // activeFocus. This will lead to weird side effects. + onActiveFocusChanged: textInput.focus = activeFocus + + Rectangle { + id: textInputArea + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + } + + DragHandler { + id: dragHandler + target: null + acceptedDevices: PointerDevice.Mouse + enabled: true + + property int initialValue: 0 + + onActiveChanged: { + if (active) { + initialValue = myControl.value + mouseArea.cursorShape = Qt.ClosedHandCursor + myControl.drag = true + } else { + mouseArea.cursorShape = Qt.PointingHandCursor + myControl.drag = false + } + } + onTranslationChanged: { + var curValue = myControl.value + myControl.value = initialValue + translation.x + + if (curValue !== myControl.value) + myControl.valueModified() + } + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + textInput.forceActiveFocus() + textInput.deselect() // QTBUG-75862 + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + onWheel: { + if (!myControl.__wheelEnabled) + return + + var val = myControl.valueFromText(textInput.text, myControl.locale) + if (myControl.value !== val) + myControl.value = val + + var curValue = myControl.value + myControl.value += wheel.angleDelta.y / 120 + + if (curValue !== myControl.value) + myControl.valueModified() + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.activeFocus + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: dragHandler + enabled: true + } + PropertyChanges { + target: tapHandler + enabled: true + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.activeFocus && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: textInput.activeFocus + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: dragHandler + enabled: false + } + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml new file mode 100644 index 0000000000..7432d00bb0 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextField { + id: myTextField + + property real relativePopupX: 0 // TODO Maybe call it leftPadding + property real popupWidth: myTextField.width + property string txtStorage + + property int temp: 0 + + T.Popup { + id: popup + x: relativePopupX + y: myTextField.height - StudioTheme.Values.border + width: popupWidth + height: scrollView.height + background: Rectangle { + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + border.width: StudioTheme.Values.border + } + + contentItem: ScrollView { + id: scrollView + padding: 0 + height: Math.min(textAreaPopup.contentHeight + scrollView.topPadding + + scrollView.bottomPadding, + StudioTheme.Values.maxTextAreaPopupHeight) + ScrollBar.horizontal.policy: ScrollBar.AlwaysOn + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + + T.TextArea { + id: textAreaPopup + padding: 10 + width: textAreaPopup.contentWidth + textAreaPopup.leftPadding + + textAreaPopup.rightPadding + anchors.fill: parent + font.pixelSize: StudioTheme.Values.myFontSize + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + selectByMouse: true + persistentSelection: textAreaPopup.focus + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onPressed: contextMenu.popup(textAreaPopup) + } + } + } + + ContextMenu { + id: contextMenu + myTextEdit: textAreaPopup + } + + AbstractButton { + id: acceptButton + x: popup.width - acceptButton.width + y: popup.height - StudioTheme.Values.border + width: Math.round(StudioTheme.Values.smallRectWidth) + height: Math.round(StudioTheme.Values.smallRectWidth) + buttonIcon: StudioTheme.Constants.tickIcon + } + + AbstractButton { + id: discardButton + x: popup.width - acceptButton.width - discardButton.width + StudioTheme.Values.border + y: popup.height - StudioTheme.Values.border + width: Math.round(StudioTheme.Values.smallRectWidth) + height: Math.round(StudioTheme.Values.smallRectWidth) + buttonIcon: StudioTheme.Constants.closeCross + } + + Component.onCompleted: { + storeAndFormatTextInput(myTextField.text) + } + + onOpened: { + textAreaPopup.text = txtStorage + myTextField.clear() + } + + onClosed: { + storeAndFormatTextInput(textAreaPopup.text) + myTextField.forceActiveFocus() + textAreaPopup.deselect() + } + } + + function storeAndFormatTextInput(inputText) { + txtStorage = inputText + var pos = txtStorage.search(/\n/g) + var sliceAt = Math.min(pos, 15) + myTextField.text = txtStorage.slice(0, sliceAt).padEnd(sliceAt + 3, '.') + } + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) { + if (popup.opened) + popup.close() + else + myTextField.focus = false + } + + if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) + && !popup.opened) { + popup.open() + textAreaPopup.forceActiveFocus() + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml new file mode 100644 index 0000000000..3525bfa41b --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.TextField { + id: myTextField + + property alias actionIndicator: actionIndicator + + property alias translationIndicator: translationIndicator + + property bool edit: false + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property alias translationIndicatorVisible: translationIndicator.visible + property real __translationIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __translationIndicatorHeight: StudioTheme.Values.height + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + + font.pixelSize: StudioTheme.Values.myFontSize + + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + readOnly: false + selectByMouse: true + persistentSelection: focus // QTBUG-73807 + clip: true + + height: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + width: StudioTheme.Values.height * 5 + + leftPadding: StudioTheme.Values.inputHorizontalPadding + actionIndicator.width + - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: StudioTheme.Values.inputHorizontalPadding + translationIndicator.width + - (translationIndicatorVisible ? StudioTheme.Values.border : 0) + + onActiveFocusChanged: myTextField.edit = myTextField.activeFocus + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + cursorShape: Qt.PointingHandCursor + onContainsMouseChanged: myTextField.hover = containsMouse // Sets the global hover + onPressed: { + if (mouse.button === Qt.RightButton) + contextMenu.popup(myTextField) + + mouse.accepted = false + } + } + + onPersistentSelectionChanged: { + if (!persistentSelection) + myTextField.deselect() + } + + ContextMenu { + id: contextMenu + myTextEdit: myTextField + } + + ActionIndicator { + id: actionIndicator + myControl: myTextField + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + background: Rectangle { + id: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + anchors.fill: parent + } + + TranslationIndicator { + id: translationIndicator + myControl: myTextField + x: myTextField.width - translationIndicator.width + width: translationIndicator.visible ? __translationIndicatorWidth : 0 + height: translationIndicator.visible ? __translationIndicatorHeight : 0 + } + + states: [ + State { + name: "default" + when: myTextField.enabled && !myTextField.hover + && !myTextField.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myTextField.hover && !myTextField.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: myTextField.activeFocus + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "disabled" + when: !myTextField.enabled + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + myTextField.focus = false + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml new file mode 100644 index 0000000000..7b08347879 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** 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.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Item { + id: translationIndicator + + property Item myControl + + property bool hover: false + property bool pressed: false + property bool checked: false + + signal clicked + + state: "default" + + Rectangle { + id: translationIndicatorBackground + color: StudioTheme.Values.themeColumnBackground // TODO create extra variable, this one is used + border.color: StudioTheme.Values.themeTranslationIndicatorBorder + + anchors.centerIn: parent + + width: matchParity(translationIndicator.height, + StudioTheme.Values.smallRectWidth) + height: matchParity(translationIndicator.height, + StudioTheme.Values.smallRectWidth) + + function matchParity(root, value) { + // TODO maybe not necessary + var v = Math.round(value) + + if (root % 2 == 0) + // even + return (v % 2 == 0) ? v : v - 1 + else + // odd + return (v % 2 == 0) ? v - 1 : v + } + + MouseArea { + id: translationIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: translationIndicator.hover = containsMouse + onPressed: mouse.accepted = true // TODO + onClicked: { + translationIndicator.checked = !translationIndicator.checked + translationIndicator.clicked() + } + } + } + + T.Label { + id: translationIndicatorIcon + text: "tr" + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.font.family + font.pixelSize: StudioTheme.Values.myIconFontSize + font.italic: true + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + } + + states: [ + State { + name: "default" + when: myControl.enabled && !translationIndicator.hover + && !translationIndicator.pressed && !myControl.hover + && !myControl.edit && !myControl.drag + && !translationIndicator.checked + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeColumnBackground + border.color: StudioTheme.Values.themeTranslationIndicatorBorder + } + }, + State { + name: "checked" + when: translationIndicator.checked + + PropertyChanges { + target: translationIndicatorBackground + //color: StudioTheme.Values.themeFocusDrag // TODO + color: "red" + } + }, + State { + name: "hovered" + when: translationIndicator.hover && !translationIndicator.pressed + && !myControl.edit && !myControl.drag && !myControl.drag + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeFocusDrag // TODO + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir new file mode 100644 index 0000000000..02acf99dff --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir @@ -0,0 +1,29 @@ +AbstractButton 1.0 AbstractButton.qml +ActionIndicator 1.0 ActionIndicator.qml +Button 1.0 Button.qml +ButtonGroup 1.0 ButtonGroup.qml +ButtonRow 1.0 ButtonRow.qml +CheckBox 1.0 CheckBox.qml +CheckIndicator 1.0 CheckIndicator.qml +ComboBox 1.0 ComboBox.qml +ComboBoxInput 1.0 ComboBoxInput.qml +ContextMenu 1.0 ContextMenu.qml +ExpandingSpacer 1.0 ExpandingSpacer.qml +ItemDelegate 1.0 ItemDelegate.qml +Menu 1.0 Menu.qml +MenuItem 1.0 MenuItem.qml +MenuSeparator 1.0 MenuSeparator.qml +ScrollBar 1.0 ScrollBar.qml +ScrollView 1.0 ScrollView.qml +SecondColumnLayout 1.0 SecondColumnLayout.qml +Section 1.0 Section.qml +SectionLabel 1.0 SectionLabel.qml +SectionLayout 1.0 SectionLayout.qml +Slider 1.0 Slider.qml +SliderPopup 1.0 SliderPopup.qml +SpinBox 1.0 SpinBox.qml +SpinBoxIndicator 1.0 SpinBoxIndicator.qml +SpinBoxInput 1.0 SpinBoxInput.qml +TextArea 1.0 TextArea.qml +TextField 1.0 TextField.qml +TranslationIndicator 1.0 TranslationIndicator.qml diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml new file mode 100644 index 0000000000..b3b4c58041 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml @@ -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 Singleton +import QtQuick 2.10 + +QtObject { + readonly property int width: 1920 + readonly property int height: 1080 + readonly property FontLoader mySystemFont: FontLoader { + name: "Arial" + } + readonly property FontLoader controlIcons: FontLoader { + source: "icons.ttf" + } + + readonly property string actionIcon: "\u0021" + readonly property string anchorBottom: "\u0022" + readonly property string anchorFill: "\u0023" + readonly property string anchorLeft: "\u0024" + readonly property string anchorRight: "\u0025" + readonly property string anchorTop: "\u0026" + readonly property string centerHorizontal: "\u0027" + readonly property string centerVertical: "\u0028" + readonly property string closeCross: "\u0029" + readonly property string fontStyleBold: "\u002A" + readonly property string fontStyleItalic: "\u002B" + readonly property string fontStyleStrikethrough: "\u002C" + readonly property string fontStyleUnderline: "\u002D" + readonly property string textAlignCenter: "\u002E" + readonly property string textAlignLeft: "\u002F" + readonly property string textAlignRight: "\u0030" + readonly property string tickIcon: "\u0031" + readonly property string upDownIcon: "\u0032" + readonly property string upDownSquare2: "\u0033" + + readonly property font iconFont: Qt.font({ + "family": controlIcons.name, + "pixelSize": 12 + }) + + readonly property font font: Qt.font({ + "family": mySystemFont.name, + "pointSize": Qt.application.font.pixelSize + }) + + readonly property font largeFont: Qt.font({ + "family": mySystemFont.name, + "pointSize": Qt.application.font.pixelSize * 1.6 + }) + + readonly property color backgroundColor: "#c2c2c2" +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml new file mode 100644 index 0000000000..2055572e44 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** 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 Singleton +import QtQuick 2.12 + +QtObject { + id: values + + property real baseHeight: 20 + property real baseFont: 12 + property real baseIconFont: 10 + + property real scaleFactor: 1 + + property real height: Math.round(values.baseHeight * values.scaleFactor) + property real myFontSize: Math.round(values.baseFont * values.scaleFactor) + property real myIconFontSize: Math.round(values.baseIconFont * values.scaleFactor) + + property real squareComponentWidth: values.height + property real smallRectWidth: values.height / 2 * 1.5 + + property real inputWidth: values.height * 4 + + property real sliderHeight: values.height / 2 * 1.5 // TODO:Have a look at -> sliderAreaHeight: Data.Values.height/2*1.5 + + property real sliderControlSize: 12 + property real sliderControlSizeMulti: sliderControlSize * scaleFactor + + property real spinControlIconSize: 8 + property real spinControlIconSizeMulti: spinControlIconSize * scaleFactor + + property real sliderTrackHeight: values.height / 4 + property real sliderHandleHeight: values.sliderTrackHeight * 2 + property real sliderHandleWidth: values.sliderTrackHeight + property real sliderFontSize: Math.round(8 * values.scaleFactor) + property real sliderPadding: Math.round(6 * values.scaleFactor) + property real sliderMargin: Math.round(3 * values.scaleFactor) + + property real sliderPointerWidth: Math.round(7 * values.scaleFactor) + property real sliderPointerHeight: Math.round(2 * values.scaleFactor) + + property real checkBoxSpacing: 6 // TODO Does look strange with scale factor applied + + property real columnWidth: 225 + (175 * (values.scaleFactor * 2)) + + property real marginTopBottom: 4 + property real border: 1 + + property real maxComboBoxPopupHeight: 300 + property real maxTextAreaPopupHeight: 150 + + property real contextMenuLabelSpacing: 30 + property real contextMenuHorizontalPadding: 6 + + property real inputHorizontalPadding: Math.round(4 * values.scaleFactor) + + // Theme Colors + + // Dark Theme Defaults + property string themeControlBackground: "#242424" + property string themeControlOutline: "#404040" + property string themeTextColor: "#ffffff" + + property string themePanelBackground: "#2a2a2a" + property string themeHoverHighlight: "#313131" + property string themeColumnBackground: "#363636" + property string themeFocusEdit: "#606060" + property string themeFocusDrag: "#565656" + + property string themeControlBackgroundPressed: "#606060" + property string themeControlBackgroundChecked: "#565656" + + property string themeInteraction: "#029de0" + + property string themeSliderActiveTrack: "#606060" + property string themeSliderInactiveTrack: "#404040" + property string themeSliderHandle: "#505050" + + property string themeSliderActiveTrackHover: "#7f7f7f" + property string themeSliderInactiveTrackHover: "#505050" + property string themeSliderHandleHover: "#606060" + + property string themeSliderActiveTrackFocus: "#aaaaaa" + property string themeSliderInactiveTrackFocus: "#606060" + property string themeSliderHandleFocus: values.themeInteraction + + // NEW NEW NEW NEW NEW + property string themeControlBackgroundDisabled: "#363636" + property string themeControlOutlineDisabled: "#404040" + property string themeTextColorDisabled: "#606060" + + property string themeTextSelectionColor: "#029de0" + property string themeTextSelectedTextColor: "#ffffff" + + property string themeScrollBarTrack: "#404040" + property string themeScrollBarHandle: "#505050" + + property string themeControlBackgroundInteraction: "#404040" // TODO Name. Right now themeFocusEdit is used for all 'edit' states. Is that correct? Different color! + + property string themeTranslationIndicatorBorder: "#7f7f7f" +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf Binary files differnew file mode 100644 index 0000000000..d2bd44ad4a --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir new file mode 100644 index 0000000000..b768fe63a2 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir @@ -0,0 +1,2 @@ +singleton Values 1.0 Values.qml +singleton Constants 1.0 Constants.qml diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index c029c60dca..73cc06f26a 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -228,8 +228,7 @@ public: if (fileName != doc->fileName()) return; - QString message; - message.vsprintf(format, ap); + const QString message = QString::vasprintf(format, ap); #ifndef DO_NOT_DUMP_ALL_PARSER_ERRORS { diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp index 011a5f546f..88509d5b62 100644 --- a/src/libs/ssh/sshconnection.cpp +++ b/src/libs/ssh/sshconnection.cpp @@ -348,8 +348,10 @@ void SshConnection::doConnectToHost() .arg(sshBinary.toUserOutput())); return; } - if (!d->sharingEnabled) + if (!d->sharingEnabled) { emitConnected(); + return; + } d->masterSocketDir.reset(new QTemporaryDir); if (!d->masterSocketDir->isValid()) { emitError(tr("Cannot establish SSH connection: Failed to create temporary " diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp index c174fe3b59..03699e92df 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.cpp +++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp @@ -117,9 +117,6 @@ void BoostTestOutputReader::sendCompleteInformation() void BoostTestOutputReader::handleMessageMatch(const QRegularExpressionMatch &match) { - if (m_result != ResultType::Invalid) - sendCompleteInformation(); - m_fileName = constructSourceFilePath(m_buildDir, match.captured(1)); m_lineNumber = match.captured(2).toInt(); @@ -176,6 +173,9 @@ void BoostTestOutputReader::handleMessageMatch(const QRegularExpressionMatch &ma m_result = ResultType::Skip; m_description = content; } + + if (m_result != ResultType::Invalid) // we got a new result + sendCompleteInformation(); } void BoostTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLine) diff --git a/src/plugins/coreplugin/ioutputpane.h b/src/plugins/coreplugin/ioutputpane.h index 506ecddf5f..d219e2aeff 100644 --- a/src/plugins/coreplugin/ioutputpane.h +++ b/src/plugins/coreplugin/ioutputpane.h @@ -99,7 +99,10 @@ signals: protected: void setupFilterUi(const QString &historyKey); QString filterText() const; + bool filterUsesRegexp() const { return m_filterRegexp; } + Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; } void setFilteringEnabled(bool enable); + QWidget *filterWidget() const { return m_filterOutputLineEdit; } void setZoomButtonsEnabled(bool enabled); @@ -118,7 +121,7 @@ private: QAction *m_filterActionCaseSensitive = nullptr; Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr; bool m_filterRegexp = false; - bool m_filterCaseSensitive = false; + Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; }; } // namespace Core diff --git a/src/plugins/coreplugin/messageoutputwindow.cpp b/src/plugins/coreplugin/messageoutputwindow.cpp index 70bef5dc11..6009282953 100644 --- a/src/plugins/coreplugin/messageoutputwindow.cpp +++ b/src/plugins/coreplugin/messageoutputwindow.cpp @@ -146,7 +146,7 @@ bool MessageOutputWindow::canNavigate() const void MessageOutputWindow::updateFilter() { - m_widget->setFilterText(filterText()); + m_widget->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp()); } } // namespace Internal diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp index 5bee2fb5f7..951fed419b 100644 --- a/src/plugins/coreplugin/outputpanemanager.cpp +++ b/src/plugins/coreplugin/outputpanemanager.cpp @@ -195,6 +195,7 @@ void IOutputPane::filterOutputButtonClicked() void IOutputPane::setRegularExpressions(bool regularExpressions) { m_filterRegexp = regularExpressions; + updateFilter(); } Id IOutputPane::filterRegexpActionId() const @@ -209,7 +210,8 @@ Id IOutputPane::filterCaseSensitivityActionId() const void IOutputPane::setCaseSensitive(bool caseSensitive) { - m_filterCaseSensitive = caseSensitive; + m_filterCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; + updateFilter(); } namespace Internal { diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 2759777863..2b5de1b2b6 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -284,15 +284,16 @@ void OutputWindow::setHighlightTextColor(const QColor &textColor) d->highlightTextColor = textColor; } -QString OutputWindow::filterText() const -{ - return d->filterText; -} - -void OutputWindow::setFilterText(const QString &filterText) +void OutputWindow::updateFilterProperties(const QString &filterText, + Qt::CaseSensitivity caseSensitivity, bool isRegexp) { + FilterModeFlags flags; + flags.setFlag(FilterModeFlag::CaseSensitive, caseSensitivity == Qt::CaseSensitive) + .setFlag(FilterModeFlag::RegExp, isRegexp); + if (d->filterMode == flags && d->filterText == filterText) + return; + d->lastFilteredBlock = {}; if (d->filterText != filterText) { - d->lastFilteredBlock = {}; const bool filterTextWasEmpty = d->filterText.isEmpty(); d->filterText = filterText; @@ -313,23 +314,9 @@ void OutputWindow::setFilterText(const QString &filterText) setPalette(pal); setReadOnly(true); } - - filterNewContent(); - } -} - -OutputWindow::FilterModeFlags OutputWindow::filterMode() const -{ - return d->filterMode; -} - -void OutputWindow::setFilterMode(OutputWindow::FilterModeFlag filterMode, bool enabled) -{ - if (d->filterMode.testFlag(filterMode) != enabled) { - d->filterMode.setFlag(filterMode, enabled); - d->lastFilteredBlock = {}; - filterNewContent(); } + d->filterMode = flags; + filterNewContent(); } void OutputWindow::filterNewContent() diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h index 99c49a4cc1..03760cbce3 100644 --- a/src/plugins/coreplugin/outputwindow.h +++ b/src/plugins/coreplugin/outputwindow.h @@ -79,11 +79,7 @@ public: void setHighlightBgColor(const QColor &bgColor); void setHighlightTextColor(const QColor &textColor); - QString filterText() const; - void setFilterText(const QString &filterText); - - FilterModeFlags filterMode() const; - void setFilterMode(FilterModeFlag filterMode, bool enabled); + void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, bool regexp); signals: void wheelZoom(); diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 9fe1a7e546..ca206d6e17 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -161,6 +161,9 @@ public: QList<QPointer<Perspective>> m_perspectives; QSet<QString> m_persistentChangedDocks; + + QHash<QString, QByteArray> m_lastPerspectiveStates; + QHash<QString, QByteArray> m_lastTypePerspectiveStates; }; DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent) @@ -431,10 +434,11 @@ void DebuggerMainWindow::restorePersistentSettings() qCDebug(perspectivesLog) << "RESTORE PERSISTENT"; QSettings *settings = ICore::settings(); settings->beginGroup(MAINWINDOW_KEY); - const bool res = theMainWindow->restoreState(settings->value(STATE_KEY).toByteArray(), - SettingsVersion); - if (!res) - qCDebug(perspectivesLog) << "NO READABLE PERSISTENT SETTINGS FOUND, ASSUMING NEW CLEAN SETTINGS"; + + const QHash<QString, QVariant> states = settings->value(STATE_KEY).toHash(); + theMainWindow->d->m_lastTypePerspectiveStates.clear(); + for (const QString &type : states.keys()) + theMainWindow->d->m_lastTypePerspectiveStates.insert(type, states.value(type).toByteArray()); theMainWindow->setAutoHideTitleBars(settings->value(AUTOHIDE_TITLEBARS_KEY, true).toBool()); theMainWindow->showCentralWidget(settings->value(SHOW_CENTRALWIDGET_KEY, true).toBool()); @@ -497,10 +501,14 @@ void DebuggerMainWindow::savePersistentSettings() theMainWindow->d->m_persistentChangedDocks = changedDocks; qCDebug(perspectivesLog) << "CHANGED DOCKS:" << changedDocks; + QVariantHash states; + for (const QString &type : theMainWindow->d->m_lastTypePerspectiveStates.keys()) + states.insert(type, QVariant::fromValue(theMainWindow->d->m_lastTypePerspectiveStates.value(type))); + QSettings *settings = ICore::settings(); settings->beginGroup(MAINWINDOW_KEY); settings->setValue(CHANGED_DOCK_KEY, QStringList(changedDocks.toList())); - settings->setValue(STATE_KEY, theMainWindow->saveState(SettingsVersion)); + settings->setValue(STATE_KEY, states); settings->setValue(AUTOHIDE_TITLEBARS_KEY, theMainWindow->autoHideTitleBars()); settings->setValue(SHOW_CENTRALWIDGET_KEY, theMainWindow->isCentralWidgetShown()); settings->endGroup(); @@ -941,6 +949,13 @@ void PerspectivePrivate::restoreLayout() << (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER"); } } + + QByteArray state; + if (theMainWindow->d->m_lastTypePerspectiveStates.contains(settingsId())) + state = theMainWindow->d->m_lastTypePerspectiveStates.value(settingsId()); + if (theMainWindow->d->m_lastPerspectiveStates.contains(m_id)) + state = theMainWindow->d->m_lastPerspectiveStates.value(m_id); + theMainWindow->restoreState(state); } void PerspectivePrivate::saveLayout() @@ -960,6 +975,8 @@ void PerspectivePrivate::saveLayout() << (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER"); } } + theMainWindow->d->m_lastPerspectiveStates.insert(m_id, theMainWindow->saveState()); + theMainWindow->d->m_lastTypePerspectiveStates.insert(settingsId(), theMainWindow->saveState()); } QString PerspectivePrivate::settingsId() const diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index c9d88ec513..948780aabc 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -372,8 +372,10 @@ void AppOutputPane::setFocus() void AppOutputPane::updateFilter() { const int index = currentIndex(); - if (index != -1) - m_runControlTabs.at(index).window->setFilterText(filterText()); + if (index != -1) { + m_runControlTabs.at(index).window->updateFilterProperties( + filterText(), filterCaseSensitivity(), filterUsesRegexp()); + } } void AppOutputPane::createNewOutputWindow(RunControl *rc) @@ -703,7 +705,8 @@ void AppOutputPane::tabChanged(int i) const int index = indexOf(m_tabWidget->widget(i)); if (i != -1 && index != -1) { const RunControlTab &controlTab = m_runControlTabs[index]; - controlTab.window->setFilterText(filterText()); + controlTab.window->updateFilterProperties(filterText(), filterCaseSensitivity(), + filterUsesRegexp()); enableButtons(controlTab.runControl); } else { enableDefaultButtons(); diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp index c1f1d86ca7..3d19bd9514 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.cpp +++ b/src/plugins/projectexplorer/compileoutputwindow.cpp @@ -356,7 +356,8 @@ void CompileOutputWindow::setSettings(const CompileOutputSettings &settings) void CompileOutputWindow::updateFilter() { - m_outputWindow->setFilterText(filterText()); + m_outputWindow->updateFilterProperties(filterText(), filterCaseSensitivity(), + filterUsesRegexp()); } void CompileOutputWindow::loadSettings() diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index 697b456758..fe890b3a29 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -141,11 +141,6 @@ WorkingDirectoryAspect::WorkingDirectoryAspect() void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout) { QTC_CHECK(!m_chooser); - m_resetButton = new QToolButton(layout->parentWidget()); - m_resetButton->setToolTip(tr("Reset to Default")); - m_resetButton->setIcon(Utils::Icons::RESET.icon()); - connect(m_resetButton.data(), &QAbstractButton::clicked, this, &WorkingDirectoryAspect::resetPath); - m_chooser = new PathChooser(layout->parentWidget()); m_chooser->setHistoryCompleter(settingsKey()); m_chooser->setExpectedKind(Utils::PathChooser::Directory); @@ -158,6 +153,10 @@ void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout) m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory); }); + m_resetButton = new QToolButton(layout->parentWidget()); + m_resetButton->setToolTip(tr("Reset to Default")); + m_resetButton->setIcon(Utils::Icons::RESET.icon()); + connect(m_resetButton.data(), &QAbstractButton::clicked, this, &WorkingDirectoryAspect::resetPath); m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory); if (m_envAspect) { diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp index 3baac2c841..8fcc48e737 100644 --- a/src/plugins/projectexplorer/taskmodel.cpp +++ b/src/plugins/projectexplorer/taskmodel.cpp @@ -341,6 +341,25 @@ void TaskFilterModel::setFilterIncludesWarnings(bool b) invalidateFilter(); } +void TaskFilterModel::updateFilterProperties(const QString &filterText, + Qt::CaseSensitivity caseSensitivity, bool isRegexp) +{ + if (filterText == m_filterText && m_filterCaseSensitivity == caseSensitivity + && m_filterStringIsRegexp == isRegexp) { + return; + } + m_filterText = filterText; + m_filterCaseSensitivity = caseSensitivity; + m_filterStringIsRegexp = isRegexp; + if (m_filterStringIsRegexp) { + m_filterRegexp.setPattern(m_filterText); + m_filterRegexp.setPatternOptions(m_filterCaseSensitivity == Qt::CaseInsensitive + ? QRegularExpression::CaseInsensitiveOption + : QRegularExpression::NoPatternOption); + } + invalidateFilter(); +} + bool TaskFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_UNUSED(source_parent); @@ -362,9 +381,18 @@ bool TaskFilterModel::filterAcceptsTask(const Task &task) const break; } - if (m_categoryIds.contains(task.category)) + if (accept && m_categoryIds.contains(task.category)) accept = false; + if (accept && !m_filterText.isEmpty()) { + const auto accepts = [this](const QString &s) { + return m_filterStringIsRegexp ? m_filterRegexp.isValid() && s.contains(m_filterRegexp) + : s.contains(m_filterText, m_filterCaseSensitivity); + }; + if (!accepts(task.file.toString()) && !accepts(task.description)) + accept = false; + } + return accept; } diff --git a/src/plugins/projectexplorer/taskmodel.h b/src/plugins/projectexplorer/taskmodel.h index f48e66d5d3..b1044a3234 100644 --- a/src/plugins/projectexplorer/taskmodel.h +++ b/src/plugins/projectexplorer/taskmodel.h @@ -28,6 +28,7 @@ #include <QSortFilterProxyModel> #include <QIcon> +#include <QRegularExpression> #include "task.h" @@ -143,6 +144,9 @@ public: bool hasFile(const QModelIndex &index) const { return taskModel()->hasFile(mapToSource(index)); } + void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, + bool isRegex); + private: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool filterAcceptsTask(const Task &task) const; @@ -151,7 +155,11 @@ private: bool m_includeUnknowns; bool m_includeWarnings; bool m_includeErrors; + bool m_filterStringIsRegexp = false; + Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; QList<Core::Id> m_categoryIds; + QString m_filterText; + QRegularExpression m_filterRegexp; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 0ae486a695..7a98d0fd33 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -289,6 +289,9 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>()) d->m_categoriesButton->setMenu(d->m_categoriesMenu); + setupFilterUi("IssuesPane.Filter"); + setFilteringEnabled(true); + TaskHub *hub = TaskHub::instance(); connect(hub, &TaskHub::categoryAdded, this, &TaskWindow::addCategory); connect(hub, &TaskHub::taskAdded, this, &TaskWindow::addTask); @@ -355,7 +358,7 @@ void TaskWindow::delayedInitialization() QList<QWidget*> TaskWindow::toolBarWidgets() const { - return {d->m_filterWarningsButton, d->m_categoriesButton}; + return {d->m_filterWarningsButton, d->m_categoriesButton, filterWidget()}; } QWidget *TaskWindow::outputWidget(QWidget *) @@ -664,6 +667,11 @@ void TaskWindow::goToPrev() triggerDefaultHandler(currentIndex); } +void TaskWindow::updateFilter() +{ + d->m_filter->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp()); +} + bool TaskWindow::canNavigate() const { return true; diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h index 290927b47b..efefb72658 100644 --- a/src/plugins/projectexplorer/taskwindow.h +++ b/src/plugins/projectexplorer/taskwindow.h @@ -82,6 +82,8 @@ signals: void tasksCleared(); private: + void updateFilter() override; + void addCategory(Core::Id categoryId, const QString &displayName, bool visible); void addTask(const ProjectExplorer::Task &task); void removeTask(const ProjectExplorer::Task &task); diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp index 5aadf8dad5..471ec2abd4 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 */ + resetPuppet(); /*Unfortunately required */ emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -437,6 +437,11 @@ QmlDesigner::AbstractView *GradientModel::view() const return m_itemNode.view(); } +void GradientModel::resetPuppet() +{ + QTimer::singleShot(1000, [this]() { view()->resetPuppet(); }); +} + QmlDesigner::ModelNode GradientModel::createGradientNode() { QByteArray fullTypeName = m_gradientTypeName.toUtf8(); @@ -534,19 +539,20 @@ void GradientModel::setPresetByStops(const QList<qreal> &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 +566,9 @@ void GradientModel::setPresetByStops(const QList<qreal> &stopsPositions, } setupModel(); + if (m_gradientTypeName != "Gradient") + resetPuppet(); /*Unfortunately required */ + emit hasGradientChanged(); emit gradientTypeChanged(); } @@ -586,3 +595,16 @@ void GradientModel::savePreset() items.append(item); GradientPresetCustomListModel::storePresets(filename, items); } + +void GradientModel::updateGradient() +{ + QList<qreal> stops; + QList<QString> 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 d5fb3aea2a..c54526838e 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(); @@ -106,6 +108,7 @@ private: void setupGradientProperties(const QmlDesigner::ModelNode &gradient); QmlDesigner::Model *model() const; QmlDesigner::AbstractView *view() const; + void resetPuppet(); }; QML_DECLARE_TYPE(GradientModel) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri index 9d53bda311..b32a744016 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/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 284b6948ee..40c5cfda6e 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -40,6 +40,7 @@ #include <coreplugin/icore.h> #include <qmljs/qmljssimplereader.h> +#include <utils/qtcassert.h> #include <utils/algorithm.h> #include <utils/fileutils.h> @@ -281,13 +282,17 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q setupLayoutAttachedProperties(qmlObjectNode, propertyEditor); + // model node + m_backendModelNode.setup(qmlObjectNode.modelNode()); + context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode); + // className auto valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("className")))); if (!valueObject) valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); valueObject->setName("className"); valueObject->setModelNode(qmlObjectNode.modelNode()); - valueObject->setValue(qmlObjectNode.modelNode().simplifiedTypeName()); + valueObject->setValue(m_backendModelNode.simplifiedTypeName()); QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); m_backendValuesPropertyMap.insert(QLatin1String("className"), QVariant::fromValue(valueObject)); @@ -296,7 +301,7 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q if (!valueObject) valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); valueObject->setName("id"); - valueObject->setValue(qmlObjectNode.id()); + valueObject->setValue(m_backendModelNode.nodeId()); QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); m_backendValuesPropertyMap.insert(QLatin1String("id"), QVariant::fromValue(valueObject)); @@ -310,10 +315,6 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed(); - // model node - m_backendModelNode.setup(qmlObjectNode.modelNode()); - context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode); - qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed(); contextObject()->setSpecificsUrl(qmlSpecificsFile); @@ -402,7 +403,7 @@ QString PropertyEditorQmlBackend::propertyEditorResourcesPath() { QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, - const QmlObjectNode &objectNode) + const QmlObjectNode &node) { if (!templateConfiguration() || !templateConfiguration()->isValid()) return QString(); @@ -411,7 +412,7 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n'); qmlTemplate += QStringLiteral("Section {\n"); - qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(objectNode.modelNode().simplifiedTypeName()); + qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(QString::fromUtf8(type.simplifiedTypeName())); qmlTemplate += QStringLiteral("SectionLayout {\n"); QList<PropertyName> orderedList = type.propertyNames(); @@ -429,8 +430,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, TypeName typeName = type.propertyTypeName(name); //alias resolution only possible with instance - if (typeName == "alias" && objectNode.isValid()) - typeName = objectNode.instanceType(name); + if (typeName == "alias" && node.isValid()) + typeName = node.instanceType(name); if (!superType.hasProperty(name) && type.propertyIsWritable(name) && !name.contains(".")) { foreach (const QmlJS::SimpleReaderNode::Ptr &node, templateConfiguration()->children()) @@ -469,6 +470,34 @@ TypeName PropertyEditorQmlBackend::fixTypeNameForPanes(const TypeName &typeName) return fixedTypeName; } +static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second) +{ + for (const NodeMetaInfo &info : first.superClasses()) { + if (second.isSubclassOf(info.typeName())) + return info; + } + return first; +} + +NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node) +{ + QTC_ASSERT(node.isValid(), return {}); + QTC_ASSERT(node.metaInfo().isValid(), return {}); + + AbstractView *view = node.view(); + + if (view->selectedModelNodes().count() > 1) { + NodeMetaInfo commonClass = node.metaInfo(); + for (const ModelNode ¤tNode : view->selectedModelNodes()) { + if (currentNode.metaInfo().isValid() && !currentNode.isSubclassOf(commonClass.typeName(), -1, -1)) + commonClass = findCommonSuperClass(currentNode.metaInfo(), commonClass); + } + return commonClass; + } + + return node.metaInfo(); +} + TypeName PropertyEditorQmlBackend::qmlFileName(const NodeMetaInfo &nodeInfo) { const TypeName fixedTypeName = fixTypeNameForPanes(nodeInfo.typeName()); @@ -526,10 +555,10 @@ void PropertyEditorQmlBackend::setValueforLayoutAttachedProperties(const QmlObje setValue(qmlObjectNode, name, properDefaultLayoutAttachedProperties(qmlObjectNode, propertyName)); } -QUrl PropertyEditorQmlBackend::getQmlUrlForModelNode(const ModelNode &modelNode, TypeName &className) +QUrl PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo, TypeName &className) { - if (modelNode.isValid()) { - foreach (const NodeMetaInfo &info, modelNode.metaInfo().classHierarchy()) { + if (metaInfo.isValid()) { + foreach (const NodeMetaInfo &info, metaInfo.classHierarchy()) { QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info)))); if (fileUrl.isValid()) { className = info.typeName(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h index a0012a1cc1..51279a1fc6 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h @@ -68,11 +68,10 @@ public: PropertyEditorValue *propertyValueForName(const QString &propertyName); static QString propertyEditorResourcesPath(); - static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, - const QmlObjectNode &objectNode); + static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, const QmlObjectNode &node); static QUrl getQmlFileUrl(const TypeName &relativeTypeName, const NodeMetaInfo &info = NodeMetaInfo()); - static QUrl getQmlUrlForModelNode(const ModelNode &modelNode, TypeName &className); + static QUrl getQmlUrlForMetaInfo(const NodeMetaInfo &modelNode, TypeName &className); static bool checkIfUrlExists(const QUrl &url); @@ -83,6 +82,8 @@ public: void setupLayoutAttachedProperties(const QmlObjectNode &qmlObjectNode, PropertyEditorView *propertyEditor); + static NodeMetaInfo findCommonAncestor(const ModelNode &node); + private: void createPropertyEditorValue(const QmlObjectNode &qmlObjectNode, const PropertyName &name, const QVariant &value, diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index 0467355bf4..d0c98c896f 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -213,20 +213,13 @@ void PropertyEditorView::changeValue(const QString &name) castedValue = QVariant(newColor); } - try { - if (!value->value().isValid()) { //reset - qmlObjectNode.removeProperty(propertyName); - } else { - if (castedValue.isValid() && !castedValue.isNull()) { - m_locked = true; - qmlObjectNode.setVariantProperty(propertyName, castedValue); - m_locked = false; - } + if (!value->value().isValid()) { //reset + removePropertyFromModel(propertyName); + } else { + if (castedValue.isValid() && !castedValue.isNull()) { + commitVariantValueToModel(propertyName, castedValue); } } - catch (const RewritingException &e) { - e.showException(); - } } void PropertyEditorView::changeExpression(const QString &propertyName) @@ -446,13 +439,16 @@ void PropertyEditorView::resetView() void PropertyEditorView::setupQmlBackend() { TypeName specificsClassName; - QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForModelNode(m_selectedNode, specificsClassName)); + + const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode); + + const QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForMetaInfo(commonAncestor, specificsClassName)); QUrl qmlSpecificsFile; TypeName diffClassName; - if (m_selectedNode.isValid()) { - diffClassName = m_selectedNode.metaInfo().typeName(); - foreach (const NodeMetaInfo &metaInfo, m_selectedNode.metaInfo().classHierarchy()) { + if (commonAncestor.isValid()) { + diffClassName = commonAncestor.typeName(); + foreach (const NodeMetaInfo &metaInfo, commonAncestor.classHierarchy()) { if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile)) break; qmlSpecificsFile = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", metaInfo); @@ -465,8 +461,8 @@ void PropertyEditorView::setupQmlBackend() QString specificQmlData; - if (m_selectedNode.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type()) - specificQmlData = PropertyEditorQmlBackend::templateGeneration(m_selectedNode.metaInfo(), model()->metaInfo(diffClassName), m_selectedNode); + if (commonAncestor.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type()) + specificQmlData = PropertyEditorQmlBackend::templateGeneration(commonAncestor, model()->metaInfo(diffClassName), m_selectedNode); PropertyEditorQmlBackend *currentQmlBackend = m_qmlBackendHash.value(qmlFile.toString()); @@ -515,14 +511,51 @@ void PropertyEditorView::setupQmlBackend() } +void PropertyEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value) +{ + m_locked = true; + try { + RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::commitVariantValueToMode"); + + for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { + if (QmlObjectNode::isValidQmlObjectNode(node)) + QmlObjectNode(node).setVariantProperty(propertyName, value); + } + transaction.commit(); + } + catch (const RewritingException &e) { + e.showException(); + } + m_locked = false; +} + +void PropertyEditorView::removePropertyFromModel(const PropertyName &propertyName) +{ + m_locked = true; + try { + RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::removePropertyFromModel"); + + for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { + if (QmlObjectNode::isValidQmlObjectNode(node)) + QmlObjectNode(node).removeProperty(propertyName); + } + + transaction.commit(); + } + catch (const RewritingException &e) { + e.showException(); + } + m_locked = false; +} + void PropertyEditorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList) { Q_UNUSED(lastSelectedNodeList); - if (selectedNodeList.isEmpty() || selectedNodeList.count() > 1) + if (selectedNodeList.isEmpty()) select(ModelNode()); - else if (m_selectedNode != selectedNodeList.constFirst()) + else select(selectedNodeList.constFirst()); } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h index 85bd8286f5..e7f57cf186 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h @@ -110,6 +110,9 @@ private: //functions void delayedResetView(); void setupQmlBackend(); + void commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value); + void removePropertyFromModel(const PropertyName &propertyName); + private: //variables ModelNode m_selectedNode; QWidget *m_parent; diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp index 6f56b055c8..934c284691 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp @@ -23,6 +23,7 @@ ** ****************************************************************************/ +#include "abstractview.h" #include "qmlmodelnodeproxy.h" #include <QtQml> @@ -66,4 +67,34 @@ ModelNode QmlModelNodeProxy::modelNode() const return m_qmlItemNode.modelNode(); } +bool QmlModelNodeProxy::multiSelection() const +{ + if (!m_qmlItemNode.isValid()) + return false; + + return m_qmlItemNode.view()->selectedModelNodes().count() > 1; +} + +QString QmlModelNodeProxy::nodeId() const +{ + if (!m_qmlItemNode.isValid()) + return {}; + + if (multiSelection()) + return tr("multiselection"); + + return m_qmlItemNode.id(); +} + +QString QmlModelNodeProxy::simplifiedTypeName() const +{ + if (!m_qmlItemNode.isValid()) + return {}; + + if (multiSelection()) + return tr("multiselection"); + + return m_qmlItemNode.simplifiedTypeName(); +} + } diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h index 0a73583355..6037f32752 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h @@ -35,7 +35,8 @@ class QmlModelNodeProxy : public QObject { Q_OBJECT - Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged) + Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged) + Q_PROPERTY(bool multiSelection READ multiSelection NOTIFY modelNodeChanged) public: explicit QmlModelNodeProxy(QObject *parent = nullptr); @@ -51,6 +52,12 @@ public: ModelNode modelNode() const; + bool multiSelection() const; + + QString nodeId() const; + + QString simplifiedTypeName() const; + signals: void modelNodeChanged(); void selectionToBeChanged(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp index f9b42cf8eb..862d16ba22 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 0000000000..c88d83aa0a --- /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 <QDebug> + +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 &color) + : 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 0000000000..342c9832e7 --- /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 <QObject> +#include <QtQml/qqml.h> +#include <QColor> + +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 0000000000..b3207f0006 --- /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 <QHash> +#include <QByteArray> +#include <QDebug> +#include <QSettings> + +namespace QmlDesigner { + +SimpleColorPaletteModel::SimpleColorPaletteModel(QObject *parent) + : QAbstractListModel(parent) +{ + connect(&SimpleColorPaletteSingleton::getInstance(), + &SimpleColorPaletteSingleton::paletteChanged, + this, + &SimpleColorPaletteModel::setPalette); + m_roleNames = {{static_cast<int>(PaletteColor::Property::objectNameRole), "objectName"}, + {static_cast<int>(PaletteColor::Property::colorRole), "color"}, + {static_cast<int>(PaletteColor::Property::colorCodeRole), "colorCode"}, + {static_cast<int>(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<PaletteColor::Property>(role)); + if (auto model = qobject_cast<SimpleColorPaletteModel *>(value.value<QObject *>())) + 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<int, QByteArray> 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<PaletteColor> &SimpleColorPaletteModel::items() const +{ + return m_items; +} + +void SimpleColorPaletteModel::sortItems() +{ + SimpleColorPaletteSingleton::getInstance().sortItems(); +} + +void SimpleColorPaletteModel::registerDeclarativeType() +{ + qmlRegisterType<SimpleColorPaletteModel>("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 0000000000..3ed2cc8a31 --- /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 <QAbstractListModel> +#include <QtQml/qqml.h> +#include <QList> + +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<int, QByteArray> roleNames() const override; + + void clearItems(); + Q_INVOKABLE void addItem(const QString &item); + void addItem(const PaletteColor &item); + + const QList<PaletteColor> &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<PaletteColor> m_items; + QHash<int, QByteArray> 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 0000000000..ccea50bbf2 --- /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 <QDebug> +#include <QSettings> + +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<PaletteColor> 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<int>(first.isFavorite()) < static_cast<int>(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<PaletteColor> 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<bool>(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<int>(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 0000000000..77ad2b0732 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <QObject> +#include <QAbstractListModel> +#include <QtQml/qqml.h> +#include <QList> +#include <QColor> +#include <simplecolorpalette.h> + +namespace QmlDesigner { + +class SimpleColorPaletteSingleton : public QObject +{ + Q_OBJECT +public: + static SimpleColorPaletteSingleton &getInstance(); + + bool readPalette(); + void writePalette(); + + void addItem(const PaletteColor &item); + QList<PaletteColor> 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<PaletteColor> 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 c86336d550..b9b82f5714 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<QColor>().rgba() == value2.value<QColor>().rgba(); + return false; +} + bool equals(const QVariant &a, const QVariant &b) { if (a.canConvert<QmlDesigner::Enumeration>() && b.canConvert<QmlDesigner::Enumeration>()) @@ -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 7df99bd59b..5870927d52 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 bdaa22bb4b..410abc267e 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<QByteArray, QVariant> diff --git a/src/plugins/qmldesigner/qmldesigner.pro b/src/plugins/qmldesigner/qmldesigner.pro index 039c228fe5..1986677fac 100644 --- a/src/plugins/qmldesigner/qmldesigner.pro +++ b/src/plugins/qmldesigner/qmldesigner.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = qmldesignerplugin.pro qtquickplugin componentsplugin +SUBDIRS = qmldesignerplugin.pro qtquickplugin componentsplugin qmlpreviewplugin diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 6a2379ea05..600fcab3fe 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", diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png Binary files differnew file mode 100644 index 0000000000..b56467d4ea --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png Binary files differnew file mode 100644 index 0000000000..93c49a04eb --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo new file mode 100644 index 0000000000..5bfe70cffd --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo @@ -0,0 +1,2 @@ +MetaInfo { +} diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp new file mode 100644 index 0000000000..1fe99825c3 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** +** +** 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 "qmlpreviewplugin.h" +#include "qmlpreviewactions.h" + +#include <zoomaction.h> + +#include <utils/utilsicons.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/session.h> +#include <projectexplorer/project.h> + +#include <QLabel> +#include <QComboBox> +#include <QPointer> + +namespace QmlDesigner { + +using namespace ProjectExplorer; + +const Utils::Icon previewIcon({ + {":/qmlpreviewplugin/images/live_preview.png", Utils::Theme::IconsBaseColor}}); + +static void handleAction(const SelectionContext &context) +{ + if (context.view()->isAttached()) { + if (context.toggled()) { + ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE); + QmlPreviewPlugin::setQmlFile(); + } else { + QmlPreviewPlugin::stopAllRunControls(); + } + } +} + +QmlPreviewAction::QmlPreviewAction() : ModelNodeAction("LivePreview", + "Live Preview", + previewIcon.icon(), + QmlPreviewPlugin::tr("Show Live Preview"), + ComponentCoreConstants::qmlPreviewCategory, + QKeySequence("Alt+p"), + 20, + &handleAction, + &SelectionContextFunctors::always) +{ + if (!QmlPreviewPlugin::getPreviewPlugin()) + defaultAction()->setVisible(false); + + defaultAction()->setCheckable(true); +} + +void QmlPreviewAction::updateContext() +{ + if (selectionContext().view()->isAttached()) + QmlPreviewPlugin::setQmlFile(); + + defaultAction()->setSelectionContext(selectionContext()); +} + +ActionInterface::Type QmlPreviewAction::type() const +{ + return ToolBarAction; +} + +ZoomPreviewAction::ZoomPreviewAction() + : m_zoomAction(new ZoomAction(nullptr)) +{ + QObject::connect(m_zoomAction.get(), &ZoomAction::zoomLevelChanged, [=](float d) { + QmlPreviewPlugin::setZoomFactor(d); + }); + if (!QmlPreviewPlugin::getPreviewPlugin()) + m_zoomAction->setVisible(false); +} + +ZoomPreviewAction::~ZoomPreviewAction() += default; + +QAction *ZoomPreviewAction::action() const +{ + return m_zoomAction.get(); +} + +QByteArray ZoomPreviewAction::category() const +{ + return ComponentCoreConstants::qmlPreviewCategory; +} + +QByteArray ZoomPreviewAction::menuId() const +{ + return QByteArray(); +} + +int ZoomPreviewAction::priority() const +{ + return 19; +} + +ActionInterface::Type ZoomPreviewAction::type() const +{ + return ToolBarAction; +} + +void ZoomPreviewAction::currentContextChanged(const SelectionContext &) +{} + +quint16 FpsLabelAction::lastValidFrames = 0; +QList<QPointer<QLabel>> FpsLabelAction::fpsHandlerLabelList; + +FpsLabelAction::FpsLabelAction(QObject *parent) + : QWidgetAction(parent) +{ +} + +void FpsLabelAction::fpsHandler(quint16 fpsValues[8]) +{ + quint16 frames = fpsValues[0]; + if (frames != 0) + lastValidFrames = frames; + QString fpsText("%1 FPS"); + if (lastValidFrames == 0 || (frames == 0 && lastValidFrames < 2)) + fpsText = fpsText.arg("--"); + else + fpsText = fpsText.arg(lastValidFrames); + for (QPointer<QLabel> label : fpsHandlerLabelList) { + if (label) + label->setText(fpsText); + } +} + +void FpsLabelAction::cleanFpsCounter() +{ + lastValidFrames = 0; + quint16 nullInitialized[8] = {0}; + fpsHandler(nullInitialized); +} + +QWidget *FpsLabelAction::createWidget(QWidget *parent) +{ + auto label = new QLabel(parent); + auto originList = fpsHandlerLabelList; + fpsHandlerLabelList.clear(); + fpsHandlerLabelList.append(label); + for (const auto &labelPointer : originList) { + if (labelPointer) + fpsHandlerLabelList.append(labelPointer); + } + + return label; +} + +void FpsLabelAction::refreshFpsLabel(quint16 frames) +{ + for (const auto &labelPointer : fpsHandlerLabelList) { + if (labelPointer) + labelPointer->setText(QString("%1 FPS").arg(frames)); + } +} + +FpsAction::FpsAction() : m_fpsLabelAction(new FpsLabelAction(nullptr)) +{} + +QAction *FpsAction::action() const +{ + return m_fpsLabelAction.get(); +} + +QByteArray FpsAction::category() const +{ + return ComponentCoreConstants::qmlPreviewCategory; +} + +QByteArray FpsAction::menuId() const +{ + return QByteArray(); +} + +int FpsAction::priority() const +{ + return 19; +} + +ActionInterface::Type FpsAction::type() const +{ + return ToolBarAction; +} + +void FpsAction::currentContextChanged(const SelectionContext &) +{} + +SwitchLanguageComboboxAction::SwitchLanguageComboboxAction(QObject *parent) + : QWidgetAction(parent) +{ + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, + this, + &SwitchLanguageComboboxAction::refreshProjectLocales); +} + +QWidget *SwitchLanguageComboboxAction::createWidget(QWidget *parent) +{ + QPointer<QComboBox> comboBox = new QComboBox(parent); + comboBox->setToolTip(tr("Switch the language used by preview.")); + connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, comboBox](int index) { + if (index == 0) + emit currentLocaleChanged(""); + else + emit currentLocaleChanged(comboBox->currentText()); + }); + + auto refreshComboBoxFunction = [this, comboBox] (ProjectExplorer::Project *project) { + if (comboBox) { + refreshProjectLocales(project); + comboBox->clear(); + comboBox->addItem(tr("Default")); + comboBox->addItems(m_localeStrings); + } + }; + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, + refreshComboBoxFunction); + + if (auto project = SessionManager::startupProject()) + refreshComboBoxFunction(project); + + return comboBox; +} + +void SwitchLanguageComboboxAction::refreshProjectLocales(Project *project) +{ + if (!project) + return; + m_localeStrings.clear(); + const auto projectDirectory = project->rootProjectDirectory().toFileInfo().absoluteFilePath(); + const QDir languageDirectory(projectDirectory + "/i18n"); + const auto qmFiles = languageDirectory.entryList({"qml_*.qm"}); + m_localeStrings = Utils::transform(qmFiles, [](const QString &qmFile) { + const int localeStartPosition = qmFile.lastIndexOf("_") + 1; + const int localeEndPosition = qmFile.size() - QString(".qm").size(); + const QString locale = qmFile.left(localeEndPosition).mid(localeStartPosition); + return locale; + }); +} + +SwitchLanguageAction::SwitchLanguageAction() + : m_switchLanguageAction(new SwitchLanguageComboboxAction(nullptr)) +{ + QObject::connect(m_switchLanguageAction.get(), &SwitchLanguageComboboxAction::currentLocaleChanged, + &QmlPreviewPlugin::setLanguageLocale); +} + +QAction *SwitchLanguageAction::action() const +{ + return m_switchLanguageAction.get(); +} + +QByteArray SwitchLanguageAction::category() const +{ + return ComponentCoreConstants::qmlPreviewCategory; +} + +QByteArray SwitchLanguageAction::menuId() const +{ + return QByteArray(); +} + +int SwitchLanguageAction::priority() const +{ + return 10; +} + +ActionInterface::Type SwitchLanguageAction::type() const +{ + return ToolBarAction; +} + +void SwitchLanguageAction::currentContextChanged(const SelectionContext &) +{} + + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h new file mode 100644 index 0000000000..8a71ee07c2 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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 <actioninterface.h> +#include <modelnodecontextmenu_helper.h> + +#include <QByteArray> + +#include <QWidgetAction> +#include <memory> + +QT_FORWARD_DECLARE_CLASS(QAction) +QT_FORWARD_DECLARE_CLASS(QLabel) + + +namespace QmlPreview { +using QmlPreviewFpsHandler = void (*)(quint16 *); +} + +namespace ProjectExplorer { +class Project; +} + +namespace QmlDesigner { +class ZoomAction; + +class QmlPreviewAction : public ModelNodeAction +{ +public: + QmlPreviewAction(); + + void updateContext() override; + + Type type() const override; +}; + +class ZoomPreviewAction : public ActionInterface +{ +public: + ZoomPreviewAction(); + ~ZoomPreviewAction() override; + QAction *action() const override; + QByteArray category() const override; + QByteArray menuId() const override; + int priority() const override; + Type type() const override; + void currentContextChanged(const SelectionContext &) override; + +private: + std::unique_ptr<ZoomAction> m_zoomAction; +}; + +class FpsLabelAction : public QWidgetAction +{ +public: + explicit FpsLabelAction(QObject *parent = nullptr); + static void fpsHandler(quint16 fpsValues[8]); + static void cleanFpsCounter(); +protected: + QWidget *createWidget(QWidget *parent) override; +private: + static void refreshFpsLabel(quint16 frames); + static QPointer<QLabel> m_labelInstance; + static QList<QPointer<QLabel>> fpsHandlerLabelList; + static quint16 lastValidFrames; +}; + +class FpsAction : public ActionInterface +{ +public: + FpsAction(); + QAction *action() const override; + QByteArray category() const override; + QByteArray menuId() const override; + int priority() const override; + Type type() const override; + void currentContextChanged(const SelectionContext &) override; +private: + std::unique_ptr<FpsLabelAction> m_fpsLabelAction; +}; + +class SwitchLanguageComboboxAction : public QWidgetAction +{ + Q_OBJECT +public: + explicit SwitchLanguageComboboxAction(QObject *parent = nullptr); +signals: + void currentLocaleChanged(const QString& string); +protected: + QWidget *createWidget(QWidget *parent) override; +private: + void refreshProjectLocales(ProjectExplorer::Project *project); + QStringList m_localeStrings; +}; + +class SwitchLanguageAction : public ActionInterface +{ +public: + SwitchLanguageAction(); + QAction *action() const override; + QByteArray category() const override; + QByteArray menuId() const override; + int priority() const override; + Type type() const override; + void currentContextChanged(const SelectionContext &) override; +private: + std::unique_ptr<SwitchLanguageComboboxAction> m_switchLanguageAction; +}; + +} // namespace QmlDesigner +Q_DECLARE_METATYPE(QmlPreview::QmlPreviewFpsHandler); diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp new file mode 100644 index 0000000000..5a3c1c4e09 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** 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 "qmlpreviewplugin.h" +#include "qmlpreviewactions.h" + +#include <modelnodecontextmenu_helper.h> +#include <componentcore_constants.h> +#include <qmldesignerplugin.h> +#include <viewmanager.h> +#include <actioninterface.h> +#include <zoomaction.h> + +#include <extensionsystem/pluginmanager.h> +#include <extensionsystem/pluginspec.h> + +#include <utils/algorithm.h> +#include <utils/qtcassert.h> +#include <utils/utilsicons.h> + +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/runconfiguration.h> +#include <projectexplorer/runcontrol.h> + +namespace QmlPreview { +using QmlPreviewRunControlList = QList<ProjectExplorer::RunControl *>; +} + +Q_DECLARE_METATYPE(QmlPreview::QmlPreviewRunControlList) + +namespace QmlDesigner { +static QObject *s_previewPlugin = nullptr; + +QmlPreviewPlugin::QmlPreviewPlugin() +{ + DesignerActionManager &designerActionManager = + QmlDesignerPlugin::instance()->designerActionManager(); + auto previewAction = new QmlPreviewAction(); + designerActionManager.addDesignerAction(new ActionGroup( + QString(), + ComponentCoreConstants::qmlPreviewCategory, + ComponentCoreConstants::priorityQmlPreviewCategory, + &SelectionContextFunctors::always)); + s_previewPlugin = getPreviewPlugin(); + + if (s_previewPlugin) { + bool connected = connect(s_previewPlugin, SIGNAL(runningPreviewsChanged(const QmlPreviewRunControlList &)), + this, SLOT(handleRunningPreviews())); + QTC_ASSERT(connected, qWarning() << "something wrong with the runningPreviewsChanged signal"); + } + + designerActionManager.addDesignerAction(previewAction); + + auto zoomAction = new ZoomPreviewAction; + designerActionManager.addDesignerAction(zoomAction); + + auto separator = new SeperatorDesignerAction(ComponentCoreConstants::qmlPreviewCategory, 0); + designerActionManager.addDesignerAction(separator); + + m_previewToggleAction = previewAction->defaultAction(); + + if (s_previewPlugin) { + auto fpsAction = new FpsAction; + designerActionManager.addDesignerAction(fpsAction); + s_previewPlugin->setProperty("fpsHandler", QVariant::fromValue<QmlPreview::QmlPreviewFpsHandler>(FpsLabelAction::fpsHandler)); + auto switchLanguageAction = new SwitchLanguageAction; + designerActionManager.addDesignerAction(switchLanguageAction); + } +} + +QString QmlPreviewPlugin::pluginName() const +{ + return QLatin1String("QmlPreviewPlugin"); +} + +void QmlPreviewPlugin::stopAllRunControls() +{ + QTC_ASSERT(s_previewPlugin, return); + + const QVariant variant = s_previewPlugin->property("runningPreviews"); + auto runControls = variant.value<QmlPreview::QmlPreviewRunControlList>(); + + for (ProjectExplorer::RunControl *runControl : runControls) + runControl->initiateStop(); + +} + +void QmlPreviewPlugin::handleRunningPreviews() +{ + QTC_ASSERT(s_previewPlugin, return); + + const QVariant variant = s_previewPlugin->property("runningPreviews"); + if (variant.isValid()) { + // the QmlPreview::QmlPreviewRunControlList type have to be available and used in the qmlpreview plugin + QTC_ASSERT(variant.canConvert<QmlPreview::QmlPreviewRunControlList>(), return); + auto runControls = variant.value<QmlPreview::QmlPreviewRunControlList>(); + m_previewToggleAction->setChecked(!runControls.isEmpty()); + if (runControls.isEmpty()) + FpsLabelAction::cleanFpsCounter(); + } +} + +QString QmlPreviewPlugin::metaInfo() const +{ + return QLatin1String(":/qmlpreviewplugin/qmlpreview.metainfo"); +} + +void QmlPreviewPlugin::setQmlFile() +{ + if (s_previewPlugin) { + const Utils::FileName qmlFileName = + QmlDesignerPlugin::instance()->currentDesignDocument()->fileName(); + s_previewPlugin->setProperty("previewedFile", qmlFileName.toString()); + } +} + +float QmlPreviewPlugin::zoomFactor() +{ + QVariant zoomFactorVariant = 1.0; + if (s_previewPlugin && !s_previewPlugin->property("zoomFactor").isNull()) + zoomFactorVariant = s_previewPlugin->property("zoomFactor"); + return zoomFactorVariant.toFloat(); +} + +void QmlPreviewPlugin::setZoomFactor(float zoomFactor) +{ + if (s_previewPlugin) + s_previewPlugin->setProperty("zoomFactor", zoomFactor); +} + +void QmlPreviewPlugin::setLanguageLocale(const QString &locale) +{ + if (s_previewPlugin) + s_previewPlugin->setProperty("locale", locale); +} + +QObject *QmlPreviewPlugin::getPreviewPlugin() +{ + auto pluginIt = std::find_if(ExtensionSystem::PluginManager::plugins().begin(), + ExtensionSystem::PluginManager::plugins().end(), + [](const ExtensionSystem::PluginSpec *p) { + return p->name() == "QmlPreview"; + }); + + if (pluginIt != ExtensionSystem::PluginManager::plugins().constEnd()) + return (*pluginIt)->plugin(); + + return nullptr; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h new file mode 100644 index 0000000000..7f50d76696 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 <iwidgetplugin.h> + +#include <QMetaType> + +QT_FORWARD_DECLARE_CLASS(QAction) + +namespace QmlDesigner { + +class QmlPreviewPlugin : public QObject, QmlDesigner::IWidgetPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QmlDesignerPlugin" FILE "qmlpreviewplugin.json") + + Q_DISABLE_COPY(QmlPreviewPlugin) + Q_INTERFACES(QmlDesigner::IWidgetPlugin) + +public: + QmlPreviewPlugin(); + ~QmlPreviewPlugin() override = default; + + QString metaInfo() const override; + QString pluginName() const override; + + static void stopAllRunControls(); + static void setQmlFile(); + static QObject *getPreviewPlugin(); + + static float zoomFactor(); + static void setZoomFactor(float zoomFactor); + static void setLanguageLocale(const QString &locale); +signals: + void fpsChanged(quint16 frames); + +private slots: + void handleRunningPreviews(); + +private: + QAction *m_previewToggleAction = nullptr; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json new file mode 100644 index 0000000000..72a2c27087 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json @@ -0,0 +1,6 @@ +{ + "Vendor" : "The Qt Company Ltd", + "Category" : "Qt Quick", + "Description" : "Plugin for integrating QmlPreview into QmlDesigner", + "Url" : "http://www.qt.io" +} diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri new file mode 100644 index 0000000000..1808b69266 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri @@ -0,0 +1,10 @@ +QT *= qml quick core + +VPATH += $$PWD + +SOURCES += qmlpreviewplugin.cpp +HEADERS += qmlpreviewplugin.h +SOURCES += qmlpreviewactions.cpp +HEADERS += qmlpreviewactions.h + +RESOURCES += qmlpreviewplugin.qrc diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro new file mode 100644 index 0000000000..ec8c9b1d63 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro @@ -0,0 +1,18 @@ +TARGET = qmlpreviewplugin +TEMPLATE = lib +CONFIG += plugin + +include(../../../../qtcreator.pri)\ + +include (../designercore/iwidgetplugin.pri) +include (../qmldesigner_dependencies.pri) + +LIBS += -L$$IDE_PLUGIN_PATH +LIBS += -l$$qtLibraryName(QmlDesigner) +LIBS += -l$$qtLibraryName(ExtensionSystem) +LIBS += -l$$qtLibraryName(Core) +LIBS += -l$$qtLibraryName(ProjectExplorer) +LIBS += -l$$qtLibraryName(Utils) + +include(qmlpreviewplugin.pri) +include(../plugindestdir.pri) diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc new file mode 100644 index 0000000000..3f8cc2a077 --- /dev/null +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/qmlpreviewplugin"> + <file>qmlpreview.metainfo</file> + <file>images/live_preview.png</file> + <file>images/live_preview@2x.png</file> + </qresource> +</RCC> diff --git a/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml b/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml new file mode 100644 index 0000000000..d2f7454f09 --- /dev/null +++ b/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** 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.7 +import QtQuick.Timeline 1.0 +import QtQuick.Controls 2.12 +import welcome 1.0 + +CheckBox { + id: do_not_show_checkBox + width: 268 + height: 40 + text: qsTr("Don't show this again") + spacing: 12 + + + contentItem: Text { + text:do_not_show_checkBox.text + font.family: "titillium web" + color: "#ffffff" + font.pointSize: 24 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + leftPadding: do_not_show_checkBox.indicator.width + do_not_show_checkBox.spacing + } +} diff --git a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml index 2ef36045f2..09c2e7757e 100644 --- a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml +++ b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml @@ -42,8 +42,8 @@ Image { Image { id: logo - x: 16 - y: 18 + x: 14 + y: 8 width: 76 height: 66 fillMode: Image.PreserveAspectFit @@ -52,8 +52,10 @@ Image { Text { id: qt_design_studio - x: 14 + x: 13 y: 93 + width: 250 + height: 55 color: "#4cd265" text: qsTr("Qt Design Studio") font.pixelSize: 36 @@ -180,31 +182,15 @@ Image { } } - Text { - id: do_not_show_text - x: 42 - y: 432 - width: 143 - height: 31 - color: "#ffffff" - text: qsTr("Don't show this again") - font.wordSpacing: 0 - font.pixelSize: 12 - font.family: StudioFonts.titilliumWeb_light - wrapMode: Text.WordWrap - } - - CheckBox { + NoShowCheckbox { id: do_not_show_checkBox - x: 7 - y: 421 - width: 34 - height: 40 - text: qsTr("") + x: -47 + y: 430 + padding: 0 scale: 0.5 - font.pointSize: 9 } + RowLayout { x: 16 y: 254 diff --git a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml index 823d9407e6..e160a1f70e 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml @@ -66,6 +66,7 @@ Item { x: 17 y: 12 height: 125 + anchors.bottomMargin: -label.height anchors.fill: parent hoverEnabled: true onHoveredChanged: { diff --git a/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml index d0524f3b46..bca1783d42 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml @@ -26,6 +26,8 @@ import QtQuick 2.0 ListModel { + + property bool communityVersion: true ListElement { displayName: "Project 01" prettyFilePath: "my_file_1" diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 99520c558d..864acf4e83 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -27,6 +27,7 @@ #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/helpmanager.h> #include <coreplugin/icore.h> #include <coreplugin/imode.h> #include <coreplugin/modemanager.h> @@ -44,6 +45,7 @@ #include <QApplication> #include <QDesktopServices> #include <QFontDatabase> +#include <QFileInfo> #include <QPointer> #include <QQmlContext> #include <QQmlEngine> @@ -65,6 +67,8 @@ class ProjectModel : public QAbstractListModel public: enum { FilePathRole = Qt::UserRole+1, PrettyFilePathRole }; + Q_PROPERTY(bool communityVersion MEMBER m_communityVersion NOTIFY communityVersionChanged) + explicit ProjectModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent) const override; @@ -102,6 +106,12 @@ public: } public slots: void resetProjects(); + +signals: + void communityVersionChanged(); + +private: + bool m_communityVersion = false; }; ProjectModel::ProjectModel(QObject *parent) @@ -111,6 +121,12 @@ ProjectModel::ProjectModel(QObject *parent) &ProjectExplorer::ProjectExplorerPlugin::recentProjectsChanged, this, &ProjectModel::resetProjects); + +#ifdef LICENSECHECKER + if (!Utils::findOrDefault(ExtensionSystem::PluginManager::plugins(), + Utils::equal(&ExtensionSystem::PluginSpec::name, QString("LicenseChecker")))) + m_communityVersion = true; +#endif } int ProjectModel::rowCount(const QModelIndex &) const @@ -281,6 +297,16 @@ WelcomeMode::WelcomeMode() #endif setWidget(m_modeWidget); + + QStringList designStudioQchPathes = {Core::HelpManager::documentationPath() + + "/qtdesignstudio.qch", + Core::HelpManager::documentationPath() + "/qtquick.qch", + Core::HelpManager::documentationPath() + + "/qtquickcontrols.qch"}; + + Core::HelpManager::registerDocumentation( + Utils::filtered(designStudioQchPathes, + [](const QString &path) { return QFileInfo::exists(path); })); } WelcomeMode::~WelcomeMode() diff --git a/src/shared/proparser/registry.cpp b/src/shared/proparser/registry.cpp index 960b6f8e58..12c268ae2b 100644 --- a/src/shared/proparser/registry.cpp +++ b/src/shared/proparser/registry.cpp @@ -29,6 +29,8 @@ #include <QtCore/qstringlist.h> #include "registry_p.h" +QT_BEGIN_NAMESPACE + namespace QMakeInternal { #ifdef Q_OS_WIN32 @@ -156,3 +158,4 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned l } // namespace QMakeInternal +QT_END_NAMESPACE diff --git a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp index 59aab237ec..ad69adae56 100644 --- a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp +++ b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp @@ -423,12 +423,11 @@ public: static const char *const pretty[] = {"warning", "error", "fatal"}; - QString str; - str.sprintf("%s:%d:%d: When parsing as %s: %s: ", fileName->chars(), line, column, + QString str = QString::asprintf("%s:%d:%d: When parsing as %s: %s: ", fileName->chars(), line, column, parseModeToString(m_parseMode).toUtf8().constData(), pretty[level]); m_errorString->append(str.toUtf8()); - str.vsprintf(format, ap); + str += QString::vasprintf(format, ap); m_errorString->append(str.toUtf8()); m_errorString->append('\n'); } diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 0cf9c7a560..e444a4b8e5 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -97,7 +97,7 @@ public: { ++errorCount; - qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' '<<QString().vsprintf(format, ap); + qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' ' << QString::vasprintf(format, ap); } }; diff --git a/tests/auto/cplusplus/c99/tst_c99.cpp b/tests/auto/cplusplus/c99/tst_c99.cpp index df33671907..edcb5f955f 100644 --- a/tests/auto/cplusplus/c99/tst_c99.cpp +++ b/tests/auto/cplusplus/c99/tst_c99.cpp @@ -83,11 +83,10 @@ class tst_c99: public QObject static const char *const pretty[] = {"warning", "error", "fatal"}; - QString str; - str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); + QString str = QString::asprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); errors->append(str.toUtf8()); - str.vsprintf(format, ap); + str += QString::vasprintf(format, ap); errors->append(str.toUtf8()); errors->append('\n'); diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index 108d93f18f..abef7cc1e1 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -85,11 +85,10 @@ class tst_cxx11: public QObject static const char *const pretty[] = {"warning", "error", "fatal"}; - QString str; - str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); + QString str = QString::asprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); errors->append(str.toUtf8()); - str.vsprintf(format, ap); + str += QString::vasprintf(format, ap); errors->append(str.toUtf8()); errors->append('\n'); diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 3904558efc..e13795154b 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -120,7 +120,7 @@ public: ++errorCount; #ifndef NO_PARSER_OR_SEMANTIC_ERROR_MESSAGES - qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' '<<QString().vsprintf(format, ap); + qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' ' << QString::vasprintf(format, ap); #else Q_UNUSED(fileName); Q_UNUSED(line); diff --git a/tests/auto/cplusplus/translationunit/tst_translationunit.cpp b/tests/auto/cplusplus/translationunit/tst_translationunit.cpp index 4a2159bf04..2c651676bc 100644 --- a/tests/auto/cplusplus/translationunit/tst_translationunit.cpp +++ b/tests/auto/cplusplus/translationunit/tst_translationunit.cpp @@ -133,7 +133,7 @@ private: { ++errorCount; qDebug() << fileName->chars() << ':' << line << ':' << column - << ' ' << QString().vsprintf(format, ap); + << ' ' << QString::vasprintf(format, ap); } } m_diagnosticClient; }; |