diff --git a/src/imports/mvvmquick/DialogPresenter.qml b/src/imports/mvvmquick/DialogPresenter.qml
index 924b1bf..93629e9 100644
--- a/src/imports/mvvmquick/DialogPresenter.qml
+++ b/src/imports/mvvmquick/DialogPresenter.qml
@@ -11,6 +11,9 @@ QtObject {
if(config.type == "msgbox") {
createMsgBox(config, result)
return true;
+ } else if(config.type == "input") {
+ createInput(config, result)
+ return true;
} else
return false;
}
@@ -43,6 +46,25 @@ QtObject {
}
}
+ property Component _inputComponent: Component {
+ InputDialog {
+ id: __input
+
+ onClosed: {
+ var index = _popups.indexOf(__input);
+ if(index > -1) {
+ __input.destroy();
+ _dialogPresenter._popups.splice(index, 1);
+ }
+ }
+
+ Component.onCompleted: {
+ _popups.push(__input)
+ __input.open()
+ }
+ }
+ }
+
function createMsgBox(config, result) {
var props = config.viewProperties;
props["msgConfig"] = config;
@@ -50,4 +72,12 @@ QtObject {
var incubator = _msgBoxComponent.incubateObject(rootItem, props);
return incubator.status !== Component.Error;
}
+
+ function createInput(config, result) {
+ var props = config.viewProperties;
+ props["msgConfig"] = config;
+ props["msgResult"] = result;
+ var incubator = _inputComponent.incubateObject(rootItem, props);
+ return incubator.status !== Component.Error;
+ }
}
diff --git a/src/imports/mvvmquick/InputDialog.qml b/src/imports/mvvmquick/InputDialog.qml
new file mode 100644
index 0000000..ab42077
--- /dev/null
+++ b/src/imports/mvvmquick/InputDialog.qml
@@ -0,0 +1,59 @@
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+import de.skycoder42.QtMvvm.Quick 1.0
+
+MsgBoxBase {
+ id: _inputDialog
+
+ readonly property url inputUrl: QuickPresenter.inputViewFactory.getInputUrl(msgConfig.subType, msgConfig.viewProperties)
+
+ ColumnLayout {
+ anchors.fill: parent
+ spacing: 14
+
+ Label {
+ id: _contentLabel
+ text: msgConfig.text.replace(/<\/p>/g, "
") //needed because qml does not put space between paragraphs...
+ visible: text != ""
+ Layout.fillWidth: true
+ wrapMode: Text.Wrap
+ onLinkActivated: Qt.openUrlExternally(link)
+ }
+
+ ProgressBar {
+ id: _loadProgress
+ visible: _inputViewLoad.status == Loader.Loading
+ Layout.fillWidth: true
+ value: _inputViewLoad.progress
+ }
+
+ Label {
+ id: _errorLabel
+ visible: _inputViewLoad.status == Loader.Error
+ Layout.fillWidth: true
+ text: qsTr("Failed to load input view for type: %1").arg(msgConfig.subType)
+ }
+
+ Loader {
+ id: _inputViewLoad
+ asynchronous: true
+ clip: true
+ visible: _inputViewLoad.item
+
+ Layout.preferredWidth: _inputViewLoad.item ? _inputViewLoad.item.implicitWidth : 0
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ onLoaded: msgResult.result = Qt.binding(function() {
+ return item.inputValue;
+ })
+ }
+ }
+
+ Component.onCompleted: {
+ var props = msgConfig.viewProperties;
+ props["inputValue"] = msgConfig.defaultValue;
+ _inputViewLoad.setSource(inputUrl, props);
+ }
+}
diff --git a/src/imports/mvvmquick/MsgBox.qml b/src/imports/mvvmquick/MsgBox.qml
index 3a8a318..1f000cd 100644
--- a/src/imports/mvvmquick/MsgBox.qml
+++ b/src/imports/mvvmquick/MsgBox.qml
@@ -1,79 +1,30 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
-import QtQuick.Window 2.2
-import QtQuick.Layouts 1.3
-import de.skycoder42.QtMvvm.Core 1.0
-Dialog {
+MsgBoxBase {
id: _msgBox
- property var msgConfig
- property MessageResult msgResult
-
- property real extraHeight: 0
- property real baseWidth: 300
-
- x: parent ? (parent.width - width) / 2 : 0
- y: parent ? deltaY() : 0
- width: parent ? Math.min(Math.max(implicitWidth, baseWidth), parent.width - 28) : implicitWidth
- height: parent ? Math.min(implicitHeight, parent.height - 28) : implicitWidth
- modal: true
- focus: true
-
- function deltaY() {
- var unscaled = Qt.inputMethod.keyboardRectangle.height / Screen.devicePixelRatio;
- var availHeight = (parent.height + extraHeight) - unscaled - 28;//spacing
- var rawDelta = (Math.max(0, availHeight - height) / 2);
- return rawDelta + 14 - extraHeight;//spacing
- }
-
- header: RowLayout {
- spacing: 14
-
- TintIcon {
- id: icon
- property int iconType
-
- Layout.preferredWidth: 24
- Layout.preferredHeight: 24
- Layout.margins: 24
- Layout.bottomMargin: 0
- Layout.rightMargin: 0
- visible: msgConfig.subType != "about"
- source: {
- var base = "image://svg/de/skycoder42/qtmvvm/quick/icons/ic_%1";
- switch(String(msgConfig.subType)) {
- case "information":
- base = base.arg("info");
- break;
- case "question":
- base = base.arg("help");
- break;
- case "warning":
- base = base.arg("warning");
- break;
- case "critical":
- base = base.arg("error");
- break;
- case "about":
- default:
- return "";
- }
- return base;
- }
- }
-
- Label {
- text: msgConfig.title
- visible: msgConfig.title
- elide: Label.ElideRight
- font.bold: true
- font.pixelSize: 16
- Layout.fillWidth: true
- Layout.margins: 24
- Layout.bottomMargin: 0
- Layout.leftMargin: icon.visible ? 0 : 24
+ iconVisible: msgConfig.subType != "about"
+ iconSource: {
+ var base = "image://svg/de/skycoder42/qtmvvm/quick/icons/ic_%1";
+ switch(String(msgConfig.subType)) {
+ case "information":
+ base = base.arg("info");
+ break;
+ case "question":
+ base = base.arg("help");
+ break;
+ case "warning":
+ base = base.arg("warning");
+ break;
+ case "critical":
+ base = base.arg("error");
+ break;
+ case "about":
+ default:
+ return "";
}
+ return base;
}
Label {
@@ -84,45 +35,4 @@ Dialog {
wrapMode: Text.Wrap
onLinkActivated: Qt.openUrlExternally(link)
}
-
- footer: DialogButtonBox {
- id: _btnBox
-
- readonly property var _allBtns: [
- DialogButtonBox.NoButton,
- DialogButtonBox.Ok,
- DialogButtonBox.Save,
- DialogButtonBox.SaveAll,
- DialogButtonBox.Open,
- DialogButtonBox.Yes,
- DialogButtonBox.YesToAll,
- DialogButtonBox.No,
- DialogButtonBox.NoToAll,
- DialogButtonBox.Abort,
- DialogButtonBox.Retry,
- DialogButtonBox.Ignore,
- DialogButtonBox.Close,
- DialogButtonBox.Cancel,
- DialogButtonBox.Discard,
- DialogButtonBox.Help,
- DialogButtonBox.Apply,
- DialogButtonBox.Reset,
- DialogButtonBox.RestoreDefaults,
- ]
-
- standardButtons: msgConfig.buttons
- onStandardButtonsChanged: {
- for(var key in msgConfig.buttonTexts)
- standardButton(DialogButtonBox.Ok).text = msgConfig.buttonTexts[key]
- }
-
- onClicked: {
- if(msgResult) {
- _allBtns.forEach(function(sBtn) {
- if(button === standardButton(sBtn))
- msgResult.complete(sBtn)
- })
- }
- }
- }
}
diff --git a/src/imports/mvvmquick/MsgBoxBase.qml b/src/imports/mvvmquick/MsgBoxBase.qml
new file mode 100644
index 0000000..c0b4b42
--- /dev/null
+++ b/src/imports/mvvmquick/MsgBoxBase.qml
@@ -0,0 +1,110 @@
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Window 2.2
+import QtQuick.Layouts 1.3
+import de.skycoder42.QtMvvm.Core 1.0
+
+Dialog {
+ id: _msgBoxBase
+
+ property var msgConfig
+ property MessageResult msgResult
+
+ property real extraHeight: 0
+ property real baseWidth: 300
+
+ property alias iconVisible: _icon.visible
+ property alias iconSource: _icon.source
+
+ x: parent ? (parent.width - width) / 2 : 0
+ y: parent ? deltaY() : 0
+ width: parent ? Math.min(Math.max(implicitWidth, baseWidth), parent.width - 28) : implicitWidth
+ height: parent ? Math.min(implicitHeight, parent.height - 28) : implicitWidth
+ modal: true
+ focus: true
+
+ function deltaY() {
+ var unscaled = Qt.inputMethod.keyboardRectangle.height / Screen.devicePixelRatio;
+ var availHeight = (parent.height + extraHeight) - unscaled - 28;//spacing
+ var rawDelta = (Math.max(0, availHeight - height) / 2);
+ return rawDelta + 14 - extraHeight;//spacing
+ }
+
+ header: RowLayout {
+ spacing: 14
+
+ TintIcon {
+ id: _icon
+ visible: false
+
+ Layout.preferredWidth: 24
+ Layout.preferredHeight: 24
+ Layout.margins: 24
+ Layout.bottomMargin: 0
+ Layout.rightMargin: 0
+ }
+
+ Label {
+ id: _title
+ text: msgConfig.title
+ visible: msgConfig.title
+ elide: Label.ElideRight
+ font.bold: true
+ font.pixelSize: 16
+ Layout.fillWidth: true
+ Layout.margins: 24
+ Layout.bottomMargin: 0
+ Layout.leftMargin: _icon.visible ? 0 : 24
+ }
+ }
+
+ footer: DialogButtonBox {
+ id: _btnBox
+
+ readonly property var _allBtns: [
+ DialogButtonBox.NoButton,
+ DialogButtonBox.Ok,
+ DialogButtonBox.Save,
+ DialogButtonBox.SaveAll,
+ DialogButtonBox.Open,
+ DialogButtonBox.Yes,
+ DialogButtonBox.YesToAll,
+ DialogButtonBox.No,
+ DialogButtonBox.NoToAll,
+ DialogButtonBox.Abort,
+ DialogButtonBox.Retry,
+ DialogButtonBox.Ignore,
+ DialogButtonBox.Close,
+ DialogButtonBox.Cancel,
+ DialogButtonBox.Discard,
+ DialogButtonBox.Help,
+ DialogButtonBox.Apply,
+ DialogButtonBox.Reset,
+ DialogButtonBox.RestoreDefaults,
+ ]
+
+ standardButtons: msgConfig.buttons
+ onStandardButtonsChanged: {
+ for(var key in msgConfig.buttonTexts)
+ standardButton(DialogButtonBox.Ok).text = msgConfig.buttonTexts[key]
+ }
+
+ onClicked: {
+ if(msgResult) {
+ _allBtns.forEach(function(sBtn) {
+ if(button === standardButton(sBtn)) {
+ msgResult.complete(sBtn);
+ msgResult = null;
+ }
+ })
+ }
+ }
+ }
+
+ onClosed: {
+ if(msgResult) {
+ msgResult.complete(MessageConfig.NoButton);
+ msgResult = null;
+ }
+ }
+}
diff --git a/src/imports/mvvmquick/mvvmquick.pro b/src/imports/mvvmquick/mvvmquick.pro
index 0056c17..7b1ef5d 100644
--- a/src/imports/mvvmquick/mvvmquick.pro
+++ b/src/imports/mvvmquick/mvvmquick.pro
@@ -23,7 +23,9 @@ QML_FILES += \
PopupPresenter.qml \
DialogPresenter.qml \
TintIcon.qml \
- MsgBox.qml
+ MsgBoxBase.qml \
+ MsgBox.qml \
+ InputDialog.qml
OTHER_FILES += qmldir
diff --git a/src/imports/mvvmquick/plugins.qmltypes b/src/imports/mvvmquick/plugins.qmltypes
index 5c4f600..be8da63 100644
--- a/src/imports/mvvmquick/plugins.qmltypes
+++ b/src/imports/mvvmquick/plugins.qmltypes
@@ -8,6 +8,17 @@ import QtQuick.tooling 1.2
Module {
dependencies: ["QtQuick 2.8"]
+ Component {
+ name: "QUrlValidator"
+ prototype: "QValidator"
+ exports: ["de.skycoder42.QtMvvm.Quick.Private/UrlValidator 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "allowedSchemes"; type: "QStringList" }
+ Method {
+ name: "setAllowedSchemes"
+ Parameter { name: "allowedSchemes"; type: "QStringList" }
+ }
+ }
Component {
name: "QtMvvm::InputViewFactory"
prototype: "QObject"
diff --git a/src/imports/mvvmquick/qmldir b/src/imports/mvvmquick/qmldir
index a56f8a0..6238a4a 100644
--- a/src/imports/mvvmquick/qmldir
+++ b/src/imports/mvvmquick/qmldir
@@ -4,7 +4,9 @@ classname QtMvvmQuickDeclarativeModule
typeinfo plugins.qmltypes
internal TintIcon TintIcon.qml
+internal MsgBoxBase MsgBoxBase.qml
internal MsgBox MsgBox.qml
+internal InputDialog InputDialog.qml
PresenterProgress 1.0 PresenterProgress.qml
PresentingStackView 1.0 PresentingStackView.qml
diff --git a/src/mvvmquick/UrlField.qml b/src/mvvmquick/UrlField.qml
new file mode 100644
index 0000000..0a4058a
--- /dev/null
+++ b/src/mvvmquick/UrlField.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import de.skycoder42.QtMvvm.Quick.Private 1.0
+
+TextField {
+ id: _edit
+ property alias inputValue: _edit.text
+ property alias allowedSchemes: _validator.allowedSchemes
+
+ selectByMouse: true
+ validator: UrlValidator {
+ id: _validator
+ }
+}
diff --git a/src/mvvmquick/inputviewfactory.cpp b/src/mvvmquick/inputviewfactory.cpp
index 079d3cd..2cb74ad 100644
--- a/src/mvvmquick/inputviewfactory.cpp
+++ b/src/mvvmquick/inputviewfactory.cpp
@@ -1,18 +1,34 @@
#include "inputviewfactory.h"
#include "inputviewfactory_p.h"
+#include
#include
+#include
+
#include
+
+#include
using namespace QtMvvm;
-static void initResources()
+namespace {
+
+void initPrivateQml()
+{
+ qmlRegisterType("de.skycoder42.QtMvvm.Quick.Private", 1, 0, "UrlValidator");
+}
+
+void initResources()
{
#ifdef QT_STATIC
+ initPrivateQml();
Q_INIT_RESOURCE(qtmvvmquick_module);
#endif
}
+}
+Q_COREAPP_STARTUP_FUNCTION(initPrivateQml)
+
InputViewFactory::InputViewFactory() :
QObject(nullptr),
d(new InputViewFactoryPrivate())
@@ -53,8 +69,8 @@ QUrl InputViewFactory::getInputUrl(const QByteArray &type, const QVariantMap &vi
// return QUrl();
else if(type == QMetaType::typeName(QMetaType::QFont))
return QStringLiteral("qrc:/de/skycoder42/qtmvvm/quick/inputs/FontEdit.qml");
-// else if(type == QMetaType::typeName(QMetaType::QUrl) || type == "url")
-// return QStringLiteral("qrc:/de/skycoder42/qtmvvm/quick/inputs/UrlField.qml");
+ else if(type == QMetaType::typeName(QMetaType::QUrl) || type == "url")
+ return QStringLiteral("qrc:/de/skycoder42/qtmvvm/quick/inputs/UrlField.qml");
else if(type == "selection" || type == "list")
return QStringLiteral("qrc:/de/skycoder42/qtmvvm/quick/inputs/ListEdit.qml");
else {
diff --git a/src/mvvmquick/mvvmquick.pro b/src/mvvmquick/mvvmquick.pro
index 33f4365..da87d72 100644
--- a/src/mvvmquick/mvvmquick.pro
+++ b/src/mvvmquick/mvvmquick.pro
@@ -1,17 +1,20 @@
TARGET = QtMvvmQuick
-QT = core gui widgets mvvmcore mvvmcore-private
+QT = core gui qml quick mvvmcore mvvmcore-private
HEADERS += \
qtmvvmquick_global.h \
quickpresenter.h \
quickpresenter_p.h \
- inputviewfactory.h \
- inputviewfactory_p.h
+ inputviewfactory.h \
+ inputviewfactory_p.h
SOURCES += \
quickpresenter.cpp \
- inputviewfactory.cpp
+ inputviewfactory.cpp
+
+RESOURCES += \
+ qtmvvmquick_module.qrc
TRANSLATIONS += \
translations/qtmvvmquick_de.ts \
@@ -39,5 +42,4 @@ else: include($$OUT_PWD/qpmx_generated.pri)
qpmx_ts_target.files -= $$OUT_PWD/$$QPMX_WORKINGDIR/qtmvvmquick_template.qm
qpmx_ts_target.files += translations/qtmvvmquick_template.ts
-RESOURCES += \
- qtmvvmquick_module.qrc
+mingw: LIBS_PRIVATE += -lQt5Gui -lQt5Core
diff --git a/src/mvvmquick/qpmx.json b/src/mvvmquick/qpmx.json
index 461fe91..7fa89ac 100644
--- a/src/mvvmquick/qpmx.json
+++ b/src/mvvmquick/qpmx.json
@@ -1,5 +1,11 @@
{
- "dependencies": [],
+ "dependencies": [
+ {
+ "package": "de.skycoder42.qurlvalidator",
+ "provider": "qpm",
+ "version": "1.1.0"
+ }
+ ],
"license": {
"file": "",
"name": ""
diff --git a/src/mvvmquick/qtmvvmquick_module.qrc b/src/mvvmquick/qtmvvmquick_module.qrc
index d574450..21a3618 100644
--- a/src/mvvmquick/qtmvvmquick_module.qrc
+++ b/src/mvvmquick/qtmvvmquick_module.qrc
@@ -6,5 +6,6 @@
CheckBox.qml
DoubleSpinBox.qml
FontEdit.qml
+ UrlField.qml
diff --git a/src/mvvmwidgets/widgetspresenter.cpp b/src/mvvmwidgets/widgetspresenter.cpp
index f3c361a..aca17c5 100644
--- a/src/mvvmwidgets/widgetspresenter.cpp
+++ b/src/mvvmwidgets/widgetspresenter.cpp
@@ -221,6 +221,7 @@ void WidgetsPresenter::presentMessageBox(const MessageConfig &config, QPointer(static_cast(config.buttons())); //is ok, as the buttons are the same