From 5127882cc83221fb97577a252e32cab8d0a1e7e1 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Wed, 27 Jun 2018 01:12:57 +0200 Subject: [PATCH] added qml color edit/dialog/delegate impl --- .../mvvmcore/SampleCore/sampleviewmodel.cpp | 3 +- examples/mvvmquick/SampleQuick/SampleView.qml | 4 + src/imports/mvvmquick/ColorEdit.qml | 321 ++++++++++++++++++ src/imports/mvvmquick/DialogPresenter11.qml | 12 +- src/imports/mvvmquick/MsgDelegate.qml | 4 +- src/imports/mvvmquick/mvvmquick.pro | 3 +- src/imports/mvvmquick/qmldir | 1 + src/mvvmcore/message.cpp | 3 +- src/mvvmquick/ColorDelegate.qml | 15 + src/mvvmquick/ColorEdit.qml | 6 + src/mvvmquick/DateEdit.qml | 2 - src/mvvmquick/TimeEdit.qml | 2 - src/mvvmquick/inputviewfactory.cpp | 5 +- src/mvvmquick/qtmvvmquick_module.qrc | 2 + 14 files changed, 372 insertions(+), 11 deletions(-) create mode 100644 src/imports/mvvmquick/ColorEdit.qml create mode 100644 src/mvvmquick/ColorDelegate.qml create mode 100644 src/mvvmquick/ColorEdit.qml diff --git a/examples/mvvmcore/SampleCore/sampleviewmodel.cpp b/examples/mvvmcore/SampleCore/sampleviewmodel.cpp index 149c642..c0a4128 100644 --- a/examples/mvvmcore/SampleCore/sampleviewmodel.cpp +++ b/examples/mvvmcore/SampleCore/sampleviewmodel.cpp @@ -99,7 +99,8 @@ void SampleViewModel::getFiles() void SampleViewModel::getColor() { QtMvvm::getColor(this, [this](const QColor &color) { - addEvent(color.name(QColor::HexArgb)); + if(color.isValid()) + addEvent(color.name(QColor::HexArgb)); }, tr("Select a color:"), true); } diff --git a/examples/mvvmquick/SampleQuick/SampleView.qml b/examples/mvvmquick/SampleQuick/SampleView.qml index 561d6ee..6da9f84 100644 --- a/examples/mvvmquick/SampleQuick/SampleView.qml +++ b/examples/mvvmquick/SampleQuick/SampleView.qml @@ -35,6 +35,10 @@ Page { text: qsTr("Add Files") onTriggered: viewModel.getFiles() } + MenuItem { + text: qsTr("Add Color") + onTriggered: viewModel.getColor() + } MenuSeparator {} diff --git a/src/imports/mvvmquick/ColorEdit.qml b/src/imports/mvvmquick/ColorEdit.qml new file mode 100644 index 0000000..fed1943 --- /dev/null +++ b/src/imports/mvvmquick/ColorEdit.qml @@ -0,0 +1,321 @@ +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.0 +import de.skycoder42.QtMvvm.Quick 1.1 + +GridLayout { + id: _colorPicker + columns: 2 + rowSpacing: 16 + + ColorHelper { + id: helper + } + + property bool alpha: false + property color color + onColorChanged: { + if(!_p.changing){ + var hsvColor = _p.rgbToHsv(color); + _p.changing = true; + hueSlider.value = hsvColor.h; + saturationSlider.value = 1 - hsvColor.s; + valueSlider.value = hsvColor.v; + _colorEdit.setColor(color); + _p.changing = false; + } + } + + QtObject { + id: _p + + property bool changing: false + readonly property color color: Qt.hsva(hueSlider.position, 1 - saturationSlider.position, valueSlider.position) + readonly property color hueColor: Qt.hsva(hueSlider.position, 1, 1); + + onColorChanged: { + if(!_p.changing) { + _p.changing = true; + _colorPicker.color = _p.color + _colorEdit.setColor(color); + _p.changing = false; + } + } + + function rgbToHsv(rgbColor) { + var rr, gg, bb, + r = rgbColor.r, + g = rgbColor.g, + b = rgbColor.b, + h, s, + v = Math.max(r, g, b), + diff = v - Math.min(r, g, b), + diffc = function(c){ + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff == 0) { + h = s = 0; + } else { + s = diff / v; + rr = diffc(r); + gg = diffc(g); + bb = diffc(b); + + if (r === v) { + h = bb - gg; + } else if (g === v) { + h = (1 / 3) + rr - bb; + } else if (b === v) { + h = (2 / 3) + gg - rr; + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return { + h: h, + s: s, + v: v + }; + } + } + + Rectangle { + id: colorPreview + color: _colorPicker.color + Layout.rowSpan: 3 + Layout.preferredWidth: hueSlider.height + saturationSlider.height + valueSlider.height + 2 * _colorPicker.rowSpacing + Layout.maximumWidth: _colorPicker.width/3 + Layout.fillHeight: true + + border.color: helper.text + border.width: 1 + } + + Slider { + id: hueSlider + Layout.fillWidth: true + Material.accent: "#FF0000" + from: 0 + to: 1 + + readonly property real handleWidth: 25 + readonly property real handleHeight: ((handleWidth-1)/2)*3 + 1 + leftPadding: (handleWidth-1)/2 + 1 + rightPadding: (handleWidth-1)/2 + 1 + + background: LinearGradient { + x: hueSlider.leftPadding + y: 0 + implicitWidth: 200 + implicitHeight: hueSlider.handleHeight + width: hueSlider.availableWidth + height: implicitHeight + start: Qt.point(0, 0) + end: Qt.point(width, 0) + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: helper.text + } + + gradient: Gradient { + GradientStop { + position: 0.000 + color: Qt.rgba(1, 0, 0, 1) + } + GradientStop { + position: 0.167 + color: Qt.rgba(1, 1, 0, 1) + } + GradientStop { + position: 0.333 + color: Qt.rgba(0, 1, 0, 1) + } + GradientStop { + position: 0.500 + color: Qt.rgba(0, 1, 1, 1) + } + GradientStop { + position: 0.667 + color: Qt.rgba(0, 0, 1, 1) + } + GradientStop { + position: 0.833 + color: Qt.rgba(1, 0, 1, 1) + } + GradientStop { + position: 1.000 + color: Qt.rgba(1, 0, 0, 1) + } + } + } + + handle: Item { + x: 1 + hueSlider.visualPosition * (hueSlider.availableWidth - 1) + width: hueSlider.handleWidth + height: hueSlider.handleHeight + + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + anchors.bottom: circle.top + width: 1 + color: helper.text + } + + Rectangle { + id: circle + anchors.centerIn: parent + implicitWidth: parent.width + implicitHeight: parent.width + radius: parent.width / 2 + color: Qt.hsva(hueSlider.position, 1, 1) + border.color: helper.text + } + + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: circle.bottom + anchors.bottom: parent.bottom + width: 1 + color: helper.text + } + } + } + + Slider { + id: saturationSlider + Layout.fillWidth: true + from: 0 + to: 1 + + readonly property real handleSize: 24 + leftPadding: handleSize/2 + 1 + rightPadding: handleSize/2 + 1 + + background: Item { + x: saturationSlider.leftPadding + y: saturationSlider.topPadding + (saturationSlider.availableHeight - height) / 2 + implicitWidth: 200 + implicitHeight: 6 + width: saturationSlider.availableWidth + height: implicitHeight + + Rectangle { + rotation: -90 + anchors.centerIn: parent + width: parent.height + height: parent.width + radius: 3 + border.color: helper.text + + gradient: Gradient { + GradientStop { + position: 0.000 + color: Qt.hsva(hueSlider.position, 1, 1) + } + GradientStop { + position: 1.000 + color: Qt.hsva(hueSlider.position, 0, 1) + } + } + } + } + + handle: Rectangle { + x: 1 + saturationSlider.visualPosition * saturationSlider.availableWidth + y: saturationSlider.topPadding + (saturationSlider.availableHeight - height)/2 + width: saturationSlider.handleSize + height: saturationSlider.handleSize + radius: saturationSlider.handleSize/2 + color: Qt.hsva(hueSlider.position, 1 - saturationSlider.position, 1) + border.color: helper.text + } + } + + Slider { + id: valueSlider + Layout.fillWidth: true + from: 0 + to: 1 + + readonly property real handleSize: 24 + leftPadding: handleSize/2 + 1 + rightPadding: handleSize/2 + 1 + + background: Item { + x: valueSlider.leftPadding + y: valueSlider.topPadding + (valueSlider.availableHeight - height) / 2 + implicitWidth: 200 + implicitHeight: 6 + width: valueSlider.availableWidth + height: implicitHeight + + Rectangle { + rotation: -90 + anchors.centerIn: parent + width: parent.height + height: parent.width + radius: 3 + border.color: helper.text + + gradient: Gradient { + GradientStop { + position: 0.000 + color: Qt.hsva(hueSlider.position, 1, 0) + } + GradientStop { + position: 1.000 + color: Qt.hsva(hueSlider.position, 1, 1) + } + } + } + } + + handle: Rectangle { + x: 1 + valueSlider.visualPosition * valueSlider.availableWidth + y: valueSlider.topPadding + (valueSlider.availableHeight - height)/2 + width: valueSlider.handleSize + height: valueSlider.handleSize + radius: valueSlider.handleSize/2 + color: Qt.hsva(hueSlider.position, 1, valueSlider.position) + border.color: helper.text + } + } + + TextField { + id: _colorEdit + Layout.columnSpan: 2 + Layout.fillWidth: true + selectByMouse: true + + validator: RegExpValidator { + regExp: _colorPicker.alpha ? /^#(?:[0-9a-f]{4}){1,2}$/ : /^#(?:[0-9a-f]{3}){1,2}$/ + } + + property bool _skipSet: false + function setColor(color) { + if(_skipSet) + _skipSet = false; + else + text = color; + } + + text: _colorPicker.color + onTextEdited: { + if(_colorEdit.acceptableInput) { + _skipSet = true; + _colorPicker.color = text; + } + } + } +} diff --git a/src/imports/mvvmquick/DialogPresenter11.qml b/src/imports/mvvmquick/DialogPresenter11.qml index 522f1ef..ac18a05 100644 --- a/src/imports/mvvmquick/DialogPresenter11.qml +++ b/src/imports/mvvmquick/DialogPresenter11.qml @@ -76,7 +76,9 @@ QtObject { return createInput(config, result) else if(config.type == "file") return createFile(config, result) - else + else if(config.type == "color") { + return createColor(config, result) + } else return false; } @@ -207,6 +209,7 @@ QtObject { var props = config.viewProperties; props["msgConfig"] = config; props["msgResult"] = result; + console.log(config.buttons); var incubator = _inputComponent.incubateObject(rootItem, props, Qt.Synchronous); return incubator.status !== Component.Error; } @@ -234,4 +237,11 @@ QtObject { incubator = _fileComponent.incubateObject(rootItem, props, Qt.Synchronous); return incubator.status !== Component.Error; } + + function createColor(config, result) { + config.viewProperties["alpha"] = (config.subType == "argb"); + config.type = "input"; + config.subType = "QColor"; + return createInput(config, result); + } } diff --git a/src/imports/mvvmquick/MsgDelegate.qml b/src/imports/mvvmquick/MsgDelegate.qml index ab634ac..b4fd3e9 100644 --- a/src/imports/mvvmquick/MsgDelegate.qml +++ b/src/imports/mvvmquick/MsgDelegate.qml @@ -6,8 +6,8 @@ import de.skycoder42.QtMvvm.Quick 1.1 ItemDelegate { id: _msgDelegate - property alias sourceComponent: _indicator.sourceComponent - property alias source: _indicator.source + property alias indicatorComponent: _indicator.sourceComponent + property alias indicatorSource: _indicator.source property string editDialogType: type diff --git a/src/imports/mvvmquick/mvvmquick.pro b/src/imports/mvvmquick/mvvmquick.pro index 0836209..029bc47 100644 --- a/src/imports/mvvmquick/mvvmquick.pro +++ b/src/imports/mvvmquick/mvvmquick.pro @@ -58,7 +58,8 @@ QML_FILES += \ TimeTumbler.qml \ TimeEdit.qml \ DateEdit.qml \ - ColorHelper.qml + ColorHelper.qml \ + ColorEdit.qml RESOURCES += \ qtmvvmquick_plugin.qrc diff --git a/src/imports/mvvmquick/qmldir b/src/imports/mvvmquick/qmldir index eeb267a..1d6c826 100644 --- a/src/imports/mvvmquick/qmldir +++ b/src/imports/mvvmquick/qmldir @@ -34,6 +34,7 @@ DecorLabel 1.1 DecorLabel.qml MsgDelegate 1.1 MsgDelegate.qml TimeEdit 1.1 TimeEdit.qml DateEdit 1.1 DateEdit.qml +ColorEdit 1.1 ColorEdit.qml PresenterProgress 1.0 PresenterProgress.qml PresentingStackView 1.0 PresentingStackView.qml diff --git a/src/mvvmcore/message.cpp b/src/mvvmcore/message.cpp index 92999dd..8a20942 100644 --- a/src/mvvmcore/message.cpp +++ b/src/mvvmcore/message.cpp @@ -164,7 +164,8 @@ MessageConfig &MessageConfig::resetButtons() d->buttons = Close; else d->buttons = Ok; - } else if(d->type == TypeInputDialog) + } else if(d->type == TypeInputDialog || + d->type == TypeColorDialog) d->buttons = Ok | Cancel; else d->buttons = Ok; diff --git a/src/mvvmquick/ColorDelegate.qml b/src/mvvmquick/ColorDelegate.qml new file mode 100644 index 0000000..cac712f --- /dev/null +++ b/src/mvvmquick/ColorDelegate.qml @@ -0,0 +1,15 @@ +import QtQuick 2.10 +import de.skycoder42.QtMvvm.Quick 1.1 as QtMvvm + +QtMvvm.MsgDelegate { + id: _colorDelegate + + editDialogType: "QColor" + indicatorComponent: Rectangle { + id: colorCircle + width: 24 + height: 24 + radius: height / 2 + color: inputValue + } +} diff --git a/src/mvvmquick/ColorEdit.qml b/src/mvvmquick/ColorEdit.qml new file mode 100644 index 0000000..5f5f073 --- /dev/null +++ b/src/mvvmquick/ColorEdit.qml @@ -0,0 +1,6 @@ +import de.skycoder42.QtMvvm.Quick 1.1 as QtMvvm + +QtMvvm.ColorEdit { + id: _edit + property alias inputValue: _edit.color +} diff --git a/src/mvvmquick/DateEdit.qml b/src/mvvmquick/DateEdit.qml index 054132e..4041015 100644 --- a/src/mvvmquick/DateEdit.qml +++ b/src/mvvmquick/DateEdit.qml @@ -1,6 +1,4 @@ import QtQuick 2.10 -import QtQuick.Controls 2.3 -import QtQuick.Layouts 1.3 import de.skycoder42.QtMvvm.Quick 1.1 as QtMvvm QtMvvm.DateEdit { diff --git a/src/mvvmquick/TimeEdit.qml b/src/mvvmquick/TimeEdit.qml index 4ff09f2..9eb6768 100644 --- a/src/mvvmquick/TimeEdit.qml +++ b/src/mvvmquick/TimeEdit.qml @@ -1,6 +1,4 @@ import QtQuick 2.10 -import QtQuick.Controls 2.3 -import QtQuick.Layouts 1.3 import de.skycoder42.QtMvvm.Quick 1.1 as QtMvvm QtMvvm.TimeEdit { diff --git a/src/mvvmquick/inputviewfactory.cpp b/src/mvvmquick/inputviewfactory.cpp index 015516e..4c5de3d 100644 --- a/src/mvvmquick/inputviewfactory.cpp +++ b/src/mvvmquick/inputviewfactory.cpp @@ -119,6 +119,8 @@ InputViewFactoryPrivate::InputViewFactoryPrivate() : {QMetaType::typeName(QMetaType::QDate), QStringLiteral("qrc:/qtmvvm/inputs/DateEdit.qml")}, {QMetaType::typeName(QMetaType::QDateTime), QStringLiteral("qrc:/qtmvvm/inputs/DateTimeEdit.qml")}, {"date", QStringLiteral("qrc:/qtmvvm/inputs/DateTimeEdit.qml")}, + {QMetaType::typeName(QMetaType::QColor), QStringLiteral("qrc:/qtmvvm/inputs/ColorEdit.qml")}, + {"color", QStringLiteral("qrc:/qtmvvm/inputs/ColorEdit.qml")}, {QMetaType::typeName(QMetaType::QFont), QStringLiteral("qrc:/qtmvvm/inputs/FontEdit.qml")}, {QMetaType::typeName(QMetaType::QUrl), QStringLiteral("qrc:/qtmvvm/inputs/UrlField.qml")}, {"selection", QStringLiteral("qrc:/qtmvvm/inputs/ListEdit.qml")}, @@ -128,7 +130,8 @@ InputViewFactoryPrivate::InputViewFactoryPrivate() : simpleDelegates{ {QMetaType::typeName(QMetaType::Bool), QStringLiteral("qrc:/qtmvvm/delegates/BoolDelegate.qml")}, {"switch", QStringLiteral("qrc:/qtmvvm/delegates/SwitchDelegate.qml")}, - {"range", QStringLiteral("qrc:/qtmvvm/delegates/RangeDelegate.qml")} + {"range", QStringLiteral("qrc:/qtmvvm/delegates/RangeDelegate.qml")}, + {QMetaType::typeName(QMetaType::QColor), QStringLiteral("qrc:/qtmvvm/delegates/ColorDelegate.qml")} }, formatters{ {QMetaType::typeName(QMetaType::Int), QSharedPointer::create()}, diff --git a/src/mvvmquick/qtmvvmquick_module.qrc b/src/mvvmquick/qtmvvmquick_module.qrc index eb986eb..5104ae7 100644 --- a/src/mvvmquick/qtmvvmquick_module.qrc +++ b/src/mvvmquick/qtmvvmquick_module.qrc @@ -13,6 +13,7 @@ TimeEdit.qml DateEdit.qml DateTimeEdit.qml + ColorEdit.qml BoolDelegate.qml @@ -20,6 +21,7 @@ SwitchDelegate.qml ListDelegate.qml RangeDelegate.qml + ColorDelegate.qml SettingsView.qml