Browse Source

added basic message box

pull/2/head
Skycoder42 7 years ago
parent
commit
52ac17864b
  1. 78
      src/imports/mvvmcore/plugins.qmltypes
  2. 7
      src/imports/mvvmcore/qtmvvmcore_plugin.cpp
  3. 32
      src/imports/mvvmquick/DialogPresenter.qml
  4. 128
      src/imports/mvvmquick/MsgBox.qml
  5. 15
      src/imports/mvvmquick/QtMvvmApp.qml
  6. 39
      src/imports/mvvmquick/TintIcon.qml
  7. 5
      src/imports/mvvmquick/mvvmquick.pro
  8. 4
      src/imports/mvvmquick/qmldir
  9. 27
      src/imports/mvvmquick/qqmlquickpresenter.cpp
  10. 2
      src/imports/mvvmquick/qqmlquickpresenter.h
  11. 16
      src/mvvmcore/message.cpp
  12. 5
      src/mvvmcore/message.h
  13. 7
      src/mvvmquick/quickpresenter.cpp

78
src/imports/mvvmcore/plugins.qmltypes

@ -8,6 +8,84 @@ import QtQuick.tooling 1.2
Module {
dependencies: ["QtQuick 2.8"]
Component {
name: "QtMvvm::MessageConfig"
exports: ["de.skycoder42.QtMvvm.Core/MessageConfig 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Enum {
name: "StandardButtons"
values: {
"NoButton": 0,
"Ok": 1024,
"Save": 2048,
"SaveAll": 4096,
"Open": 8192,
"Yes": 16384,
"YesToAll": 32768,
"No": 65536,
"NoToAll": 131072,
"Abort": 262144,
"Retry": 524288,
"Ignore": 1048576,
"Close": 2097152,
"Cancel": 4194304,
"Discard": 8388608,
"Help": 16777216,
"Apply": 33554432,
"Reset": 67108864,
"RestoreDefaults": 134217728
}
}
Property { name: "type"; type: "QByteArray" }
Property { name: "subType"; type: "QByteArray" }
Property { name: "title"; type: "string" }
Property { name: "text"; type: "string" }
Property { name: "buttons"; type: "StandardButtons" }
Property { name: "buttonTexts"; type: "QVariantMap" }
Property { name: "defaultValue"; type: "QVariant" }
Property { name: "viewProperties"; type: "QVariantMap" }
}
Component {
name: "QtMvvm::MessageResult"
prototype: "QObject"
exports: ["de.skycoder42.QtMvvm.Core/MessageResult 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Property { name: "result"; type: "QVariant" }
Property { name: "autoDelete"; type: "bool" }
Signal {
name: "dialogDone"
Parameter { name: "result"; type: "QtMvvm::MessageConfig::StandardButton" }
}
Signal {
name: "autoDeleteChanged"
Parameter { name: "autoDelete"; type: "bool" }
}
Method { name: "discardMessage" }
Method {
name: "setResult"
Parameter { name: "result"; type: "QVariant" }
}
Method {
name: "setAutoDelete"
Parameter { name: "autoDelete"; type: "bool" }
}
Method {
name: "setCloseTarget"
Parameter { name: "closeObject"; type: "QObject"; isPointer: true }
Parameter { name: "closeMethod"; type: "QMetaMethod" }
}
Method {
name: "complete"
Parameter { name: "result"; type: "QtMvvm::MessageConfig::StandardButton" }
}
Method {
name: "complete"
Parameter { name: "result"; type: "QtMvvm::MessageConfig::StandardButton" }
Parameter { name: "resultValue"; type: "QVariant" }
}
}
Component {
name: "QtMvvm::QQmlMvvmBinding"
prototype: "QObject"

7
src/imports/mvvmcore/qtmvvmcore_plugin.cpp

@ -3,6 +3,7 @@
#include <QtQml>
#include <QtMvvmCore/ViewModel>
#include <QtMvvmCore/Messages>
#include "qqmlmvvmbinding.h"
#include "qqmlmvvmmessage.h"
@ -21,8 +22,12 @@ void QtMvvmCoreDeclarativeModule::registerTypes(const char *uri)
Q_ASSERT(qstrcmp(uri, "de.skycoder42.QtMvvm.Core") == 0);
//Version 1.0
qmlRegisterUncreatableType<QtMvvm::ViewModel>(uri, 1, 0, "ViewModel", tr("ViewModels cannot be created from QML"));
qmlRegisterUncreatableType<QtMvvm::MessageConfig>(uri, 1, 0, "MessageConfig", QStringLiteral("Q_GADGETS cannot be created from QML"));
qmlRegisterUncreatableType<QtMvvm::MessageResult>(uri, 1, 0, "MessageResult", QStringLiteral("Message results must be passed from C++"));
qmlRegisterUncreatableType<QtMvvm::ViewModel>(uri, 1, 0, "ViewModel", QStringLiteral("ViewModels cannot be created from QML"));
qmlRegisterType<QtMvvm::QQmlMvvmBinding>(uri, 1, 0, "MvvmBinding");
qmlRegisterSingletonType<QtMvvm::QQmlMvvmMessage>(uri, 1, 0, "Message", createMessageSingleton);
// Check to make shure no module update is forgotten

32
src/imports/mvvmquick/DialogPresenter.qml

@ -0,0 +1,32 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import de.skycoder42.QtMvvm.Core 1.0
QtObject {
id: _dialogPresenter
property Item rootItem: null
function showDialog(config, result) {
if(config.type == "msgbox") {
createMsgBox(config, result)
return true;
} else
return false;
}
property Component _msgBoxComponent: Component {
MsgBox {
id: __msgBox
Component.onCompleted: __msgBox.open()
}
}
function createMsgBox(config, result) {
var props = config.viewProperties;
props["msgConfig"] = config;
props["msgResult"] = result;
var incubator = _msgBoxComponent.incubateObject(rootItem, props);
return incubator.status !== Component.Error;
}
}

128
src/imports/mvvmquick/MsgBox.qml

@ -0,0 +1,128 @@
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: _msgBox
property var msgConfig
property MessageResult msgResult
property real extraHeight: 0
x: parent ? (parent.width - width) / 2 : 0
y: parent ? deltaY() : 0
width: parent ? Math.min(Math.max(implicitWidth, 300), parent.width - 28) : implicitWidth
height: parent ? Math.min(implicitHeight, parent.height - 28) : implicitWidth
modal: true
focus: true
closePolicy: Popup.CloseOnEscape
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(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
}
}
Label {
id: _contentLabel
text: msgConfig.text.replace(/<\/p>/g, "</p><br/>") //needed because qml does not put space between paragraphs...
visible: text != ""
anchors.fill: parent
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)
})
}
}
}
}

15
src/imports/mvvmquick/QtMvvmApp.qml

@ -13,13 +13,18 @@ ApplicationWindow {
z: _rootStack.empty ? 10 : -10
}
PresentingStackView {
id: _rootStack
anchors.fill: parent
}
PopupPresenter {
id: _rootPopup
}
PresentingStackView {
id: _rootStack
anchors.fill: parent
DialogPresenter {
id: _dialogs
rootItem: _root.contentItem
}
function presentDrawerContent(item) {
@ -34,6 +39,10 @@ ApplicationWindow {
return _rootPopup.presentPopup(contentItem, popup);
}
function showDialog(config, result) {
return _dialogs.showDialog(config, result);
}
Component.onCompleted: QuickPresenter.qmlPresenter = _root
onClosing: {

39
src/imports/mvvmquick/TintIcon.qml

@ -0,0 +1,39 @@
import QtQuick 2.10
import QtQuick.Controls.Material 2.3
import QtQuick.Controls.Universal 2.3
import QtGraphicalEffects 1.0
import de.skycoder42.QtMvvm.Quick 1.0
Item {
id: _tintIcon
property size iconSize: Qt.size(24, 24)
property alias tintColor: _overlay.color
property alias source: _image.source
Image {
id: _image
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
width: iconSize.width
height: iconSize.height
sourceSize: iconSize
visible: false
}
ColorOverlay {
id: _overlay
anchors.fill: _image
source: _image
color: {
if(QuickPresenter.currentStyle === "Material")
return Material.foreground;
else if(QuickPresenter.currentStyle === "Universal")
return Universal.foreground;
else
return "black";
}
}
}

5
src/imports/mvvmquick/mvvmquick.pro

@ -18,7 +18,10 @@ QML_FILES += \
QtMvvmApp.qml \
PresentingStackView.qml \
PresenterProgress.qml \
PopupPresenter.qml
PopupPresenter.qml \
DialogPresenter.qml \
TintIcon.qml \
MsgBox.qml
OTHER_FILES += qmldir

4
src/imports/mvvmquick/qmldir

@ -3,8 +3,12 @@ plugin declarative_mvvmquick
classname QtMvvmQuickDeclarativeModule
typeinfo plugins.qmltypes
internal TintIcon TintIcon.qml
internal MsgBox MsgBox.qml
PresenterProgress 1.0 PresenterProgress.qml
PresentingStackView 1.0 PresentingStackView.qml
PopupPresenter 1.0 PopupPresenter.qml
DialogPresenter 1.0 DialogPresenter.qml
QtMvvmApp 1.0 QtMvvmApp.qml

27
src/imports/mvvmquick/qqmlquickpresenter.cpp

@ -60,6 +60,25 @@ void QQmlQuickPresenter::present(ViewModel *viewModel, const QVariantHash &param
}
}
void QQmlQuickPresenter::showDialog(const MessageConfig &config, MessageResult *result)
{
if(!_qmlPresenter) {
qmlWarning(this).space() << "No QML-Presenter registered! Unable to present dialog of type" //TODO use via define EVERYWHERE!!!
<< config.type();
return;
}
QVariant res = false;
QMetaObject::invokeMethod(_qmlPresenter, "showDialog", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, res),
Q_ARG(QVariant, QVariant::fromValue(config)),
Q_ARG(QVariant, QVariant::fromValue(result)));
if(!res.toBool()) {
qmlWarning(this).space() << "Failed to present dialog of type"
<< config.type();
}
}
void QQmlQuickPresenter::statusChanged(QQmlComponent::Status status)
{
auto component = qobject_cast<QQmlComponent*>(sender());
@ -94,15 +113,15 @@ void QQmlQuickPresenter::statusChanged(QQmlComponent::Status status)
void QQmlQuickPresenter::addObject(QQmlComponent *component, ViewModel *viewModel, const QVariantHash &params, QPointer<ViewModel> parent)
{
if(!_qmlPresenter) {
qCritical() << "No QML-Presenter registered! Unable to present control of type"
<< viewModel->metaObject()->className();
qmlWarning(this).space() << "No QML-Presenter registered! Unable to present viewModel of type"
<< viewModel->metaObject()->className();
return;
}
//create the view item, set initial stuff and them complete creation
auto item = component->beginCreate(_engine->rootContext());
if(!item) {
qmlWarning(this) << "Unable to create quick view from the loaded component"
qmlWarning(this).space() << "Unable to create quick view from the loaded component"
<< component->url();
return;
}
@ -122,7 +141,7 @@ void QQmlQuickPresenter::addObject(QQmlComponent *component, ViewModel *viewMode
if(!item->parent())
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
} else {
qmlWarning(this) << "Failed to present item for viewModel of type"
qmlWarning(this).space() << "Failed to present item for viewModel of type"
<< viewModel->metaObject()->className();
item->deleteLater();
}

2
src/imports/mvvmquick/qqmlquickpresenter.h

@ -12,6 +12,7 @@
#include <QtQml/QQmlComponent>
#include <QtMvvmCore/ViewModel>
#include <QtMvvmCore/Messages>
namespace QtMvvm {
@ -40,6 +41,7 @@ Q_SIGNALS:
private Q_SLOTS:
void present(QtMvvm::ViewModel *viewModel, const QVariantHash &params, const QUrl &viewUrl, QPointer<QtMvvm::ViewModel> parent);
void showDialog(const QtMvvm::MessageConfig &config, QtMvvm::MessageResult *result);
void statusChanged(QQmlComponent::Status status);
private:

16
src/mvvmcore/message.cpp

@ -158,6 +158,22 @@ void MessageConfig::resetButtons()
d->buttonTexts.clear();
}
QVariantMap MessageConfig::buttonTextsMap() const
{
QVariantMap map;
for(auto it = d->buttonTexts.constBegin(); it != d->buttonTexts.constEnd(); it++)
map.insert(QString::number(it.key()), it.value());
return map;
}
void MessageConfig::setButtonTextsMap(const QVariantMap &buttonTexts)
{
QHash<StandardButton, QString> map;
for(auto it = buttonTexts.constBegin(); it != buttonTexts.constEnd(); it++)
map.insert(static_cast<StandardButton>(it.key().toInt()), it.value().toString());
d->buttonTexts = map;
}
MessageResult::MessageResult() :

5
src/mvvmcore/message.h

@ -25,7 +25,7 @@ class Q_MVVMCORE_EXPORT MessageConfig
Q_PROPERTY(QString title READ title WRITE setTitle)
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(StandardButtons buttons READ buttons WRITE setButtons RESET resetButtons)
Q_PROPERTY(QHash<StandardButton, QString> buttonTexts READ buttonTexts WRITE setButtonTexts RESET resetButtons)
Q_PROPERTY(QVariantMap buttonTexts READ buttonTextsMap WRITE setButtonTextsMap RESET resetButtons)
Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue)
Q_PROPERTY(QVariantMap viewProperties READ viewProperties WRITE setViewProperties)
@ -103,6 +103,9 @@ public:
private:
QSharedDataPointer<MessageConfigPrivate> d;
QVariantMap buttonTextsMap() const;
void setButtonTextsMap(const QVariantMap &buttonTexts);
};
class MessageResultPrivate;

7
src/mvvmquick/quickpresenter.cpp

@ -46,7 +46,12 @@ void QuickPresenter::present(QtMvvm::ViewModel *viewModel, const QVariantHash &p
void QuickPresenter::showDialog(const QtMvvm::MessageConfig &config, QtMvvm::MessageResult *result)
{
qDebug(Q_FUNC_INFO);
if(d->qmlPresenter) {
QMetaObject::invokeMethod(d->qmlPresenter, "showDialog",
Q_ARG(QtMvvm::MessageConfig, config),
Q_ARG(QtMvvm::MessageResult*, result));
} else
throw PresenterException("QML presenter not ready - cannot present yet");
}
bool QuickPresenter::presentToQml(QObject *qmlPresenter, QObject *viewObject)

Loading…
Cancel
Save