Browse Source

added input dialog and url edit

pull/2/head
Skycoder42 7 years ago
parent
commit
0f670f94ec
  1. 30
      src/imports/mvvmquick/DialogPresenter.qml
  2. 59
      src/imports/mvvmquick/InputDialog.qml
  3. 96
      src/imports/mvvmquick/MsgBox.qml
  4. 110
      src/imports/mvvmquick/MsgBoxBase.qml
  5. 4
      src/imports/mvvmquick/mvvmquick.pro
  6. 11
      src/imports/mvvmquick/plugins.qmltypes
  7. 2
      src/imports/mvvmquick/qmldir
  8. 14
      src/mvvmquick/UrlField.qml
  9. 22
      src/mvvmquick/inputviewfactory.cpp
  10. 8
      src/mvvmquick/mvvmquick.pro
  11. 8
      src/mvvmquick/qpmx.json
  12. 1
      src/mvvmquick/qtmvvmquick_module.qrc
  13. 1
      src/mvvmwidgets/widgetspresenter.cpp

30
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;
}
}

59
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, "</p><br/>") //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("<i>Failed to load input view for type: <b>%1</b></i>").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);
}
}

96
src/imports/mvvmquick/MsgBox.qml

@ -1,46 +1,11 @@
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: {
iconVisible: msgConfig.subType != "about"
iconSource: {
var base = "image://svg/de/skycoder42/qtmvvm/quick/icons/ic_%1";
switch(String(msgConfig.subType)) {
case "information":
@ -61,20 +26,6 @@ Dialog {
}
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
}
}
Label {
id: _contentLabel
@ -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)
})
}
}
}
}

110
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;
}
}
}

4
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

11
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"

2
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

14
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
}
}

22
src/mvvmquick/inputviewfactory.cpp

@ -1,18 +1,34 @@
#include "inputviewfactory.h"
#include "inputviewfactory_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QMetaType>
#include <QtQml/qqml.h>
#include <QtMvvmCore/private/qtmvvm_logging_p.h>
#include <qurlvalidator.h>
using namespace QtMvvm;
static void initResources()
namespace {
void initPrivateQml()
{
qmlRegisterType<QUrlValidator>("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 {

8
src/mvvmquick/mvvmquick.pro

@ -1,6 +1,6 @@
TARGET = QtMvvmQuick
QT = core gui widgets mvvmcore mvvmcore-private
QT = core gui qml quick mvvmcore mvvmcore-private
HEADERS += \
qtmvvmquick_global.h \
@ -13,6 +13,9 @@ SOURCES += \
quickpresenter.cpp \
inputviewfactory.cpp
RESOURCES += \
qtmvvmquick_module.qrc
TRANSLATIONS += \
translations/qtmvvmquick_de.ts \
translations/qtmvvmquick_template.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

8
src/mvvmquick/qpmx.json

@ -1,5 +1,11 @@
{
"dependencies": [],
"dependencies": [
{
"package": "de.skycoder42.qurlvalidator",
"provider": "qpm",
"version": "1.1.0"
}
],
"license": {
"file": "",
"name": ""

1
src/mvvmquick/qtmvvmquick_module.qrc

@ -6,5 +6,6 @@
<file>CheckBox.qml</file>
<file>DoubleSpinBox.qml</file>
<file>FontEdit.qml</file>
<file>UrlField.qml</file>
</qresource>
</RCC>

1
src/mvvmwidgets/widgetspresenter.cpp

@ -221,6 +221,7 @@ void WidgetsPresenter::presentMessageBox(const MessageConfig &config, QPointer<M
qtHelp = config.viewProperties().value(QStringLiteral("showQtHelp"), qtHelp).toBool();//TODO document too
}
info.escapeButton = QMessageBox::NoButton; //use no button for non button closes
info.title = config.title();
info.text = config.text();
info.buttons = static_cast<QMessageBox::StandardButtons>(static_cast<int>(config.buttons())); //is ok, as the buttons are the same

Loading…
Cancel
Save