Browse Source

added public message api

pull/2/head
Skycoder42 7 years ago
parent
commit
7dfa1d49aa
  1. 2
      examples/mvvmwidgets/SampleWidgets/widgetseventservice.cpp
  2. 76
      src/mvvmcore/coreapp.cpp
  3. 16
      src/mvvmcore/coreapp.h
  4. 13
      src/mvvmcore/coreapp_p.h
  5. 2
      src/mvvmcore/ipresenter.h
  6. 540
      src/mvvmcore/message.cpp
  7. 326
      src/mvvmcore/message.h
  8. 23
      src/mvvmcore/message_p.h
  9. 4
      src/mvvmcore/serviceregistry.cpp
  10. 16
      src/mvvmcore/viewmodel.cpp
  11. 5
      src/mvvmcore/viewmodel.h
  12. 24
      src/mvvmwidgets/widgetspresenter.cpp
  13. 1
      src/mvvmwidgets/widgetspresenter.h

2
examples/mvvmwidgets/SampleWidgets/widgetseventservice.cpp

@ -27,7 +27,7 @@ int WidgetsEventService::addEvent(const QString &name)
_events.insert(_cnt, timer);
connect(timer.data(), &QTimer::timeout, this, [this, name]() {
_echoService->ping(name);//TODO event triggered signal
_echoService->ping(name);
});
timer->start(1000);

76
src/mvvmcore/coreapp.cpp

@ -53,6 +53,35 @@ IPresenter *CoreApp::presenter() const
return d->presenter.data();
}
void CoreApp::show(const char *viewModelName, const QVariantHash &params)
{
auto metaId = QMetaType::type(viewModelName);
auto metaObject = QMetaType::metaObjectForType(metaId);
if(!metaObject) {
throw PresenterException(QByteArrayLiteral("Given name (") +
viewModelName +
QByteArrayLiteral(") does not name a type with meta data"));
}
show(metaObject, params);
}
void CoreApp::show(const QMetaObject *viewMetaObject, const QVariantHash &params)
{
if(!viewMetaObject->inherits(&ViewModel::staticMetaObject)) {
throw PresenterException(QByteArrayLiteral("Given type (") +
viewMetaObject->className() +
QByteArrayLiteral(") is not a class that extends QtMvvm::ViewModel"));
}
showImp(viewMetaObject, params);
}
MessageResult *CoreApp::showDialog(const MessageConfig &config)
{
auto result = new MessageResult();
CoreAppPrivate::dInstance()->showDialog(config, result);
return result;
}
void CoreApp::bootApp()
{
if(!d->presenter)
@ -89,26 +118,13 @@ bool CoreApp::autoParse(QCommandLineParser &parser, const QStringList &arguments
}
}
void CoreApp::show(const char *viewModelName, const QVariantHash &params) const
{
auto metaId = QMetaType::type(viewModelName);
auto metaObject = QMetaType::metaObjectForType(metaId);
if(!metaObject) {
throw PresenterException(QByteArrayLiteral("Given name (") +
viewModelName +
QByteArrayLiteral(") does not name a type with meta data"));
}
show(metaObject, params);
}
void CoreApp::show(const QMetaObject *viewMetaObject, const QVariantHash &params) const
void CoreApp::showImp(const QMetaObject *metaObject, const QVariantHash &params)
{
if(!viewMetaObject->inherits(&ViewModel::staticMetaObject)) {
throw PresenterException(QByteArrayLiteral("Given type (") +
viewMetaObject->className() +
QByteArrayLiteral(") is not a class that extends QtMvvm::ViewModel"));
}
ViewModel::showImp(viewMetaObject, params, nullptr);
QMetaObject::invokeMethod(CoreAppPrivate::dInstance().data(), "showViewModel", Qt::QueuedConnection,
Q_ARG(const QMetaObject*, metaObject),
Q_ARG(const QVariantHash&, params),
Q_ARG(QPointer<ViewModel>, nullptr),
Q_ARG(quint32, 0));
}
// ------------- Private Implementation -------------
@ -125,21 +141,12 @@ QScopedPointer<CoreAppPrivate> &CoreAppPrivate::dInstance()
return instance->d;
}
void CoreAppPrivate::showViewModel(const QMetaObject *metaObject, const QVariantHash &params, QPointer<ViewModel> parent, quint32 requestCode)
{
QMetaObject::invokeMethod(this, "showViewModelPrivate", Qt::QueuedConnection,
Q_ARG(const QMetaObject*, metaObject),
Q_ARG(const QVariantHash&, params),
Q_ARG(QPointer<ViewModel>, parent),
Q_ARG(quint32, requestCode));
}
IPresenter *CoreAppPrivate::currentPresenter() const
{
return presenter.data();
}
void CoreAppPrivate::showViewModelPrivate(const QMetaObject *metaObject, const QVariantHash &params, QPointer<ViewModel> parent, quint32 requestCode)
void CoreAppPrivate::showViewModel(const QMetaObject *metaObject, const QVariantHash &params, QPointer<ViewModel> parent, quint32 requestCode)
{
if(presenter) {
QPointer<ViewModel> vm;
@ -172,3 +179,14 @@ void CoreAppPrivate::showViewModelPrivate(const QMetaObject *metaObject, const Q
<< "- no presenter was set";
}
}
void CoreAppPrivate::showDialog(const MessageConfig &config, MessageResult *result)
{
if(presenter)
presenter->showDialog(config, result);
else {
logCritical() << "Failed to show dialog ff type"
<< config.type() << ":" << config.subType()
<< "- no presenter was set";
}
}

16
src/mvvmcore/coreapp.h

@ -9,6 +9,7 @@ class QCommandLineParser;
#include "QtMvvmCore/qtmvvmcore_global.h"
#include "QtMvvmCore/viewmodel.h"
#include "QtMvvmCore/ipresenter.h"
#include "QtMvvmCore/message.h"
namespace QtMvvm {
@ -28,6 +29,13 @@ public:
void registerApp();
IPresenter *presenter() const;
template <typename TViewModel>
static inline void show(const QVariantHash &params = {});
static void show(const char *viewModelName, const QVariantHash &params = {});
static void show(const QMetaObject *viewMetaObject, const QVariantHash &params = {});
static MessageResult *showDialog(const MessageConfig &config);
public Q_SLOTS:
void bootApp();
@ -37,18 +45,16 @@ protected:
virtual void closeApp();
bool autoParse(QCommandLineParser &parser, const QStringList &arguments);
template <typename TViewModel>
inline void show(const QVariantHash &params = {}) const;
void show(const char *viewModelName, const QVariantHash &params = {}) const;
void show(const QMetaObject *viewMetaObject, const QVariantHash &params = {}) const;
private:
friend class QtMvvm::CoreAppPrivate;
QScopedPointer<CoreAppPrivate> d;
static void showImp(const QMetaObject *metaObject, const QVariantHash &params);
};
template<typename TViewModel>
inline void CoreApp::show(const QVariantHash &params) const
inline void CoreApp::show(const QVariantHash &params)
{
static_assert(std::is_base_of<ViewModel, TViewModel>::value, "TViewModel must extend QtMvvm::ViewModel");
ViewModel::showImp(&TViewModel::staticMetaObject, params, nullptr);

13
src/mvvmcore/coreapp_p.h

@ -15,18 +15,15 @@ class Q_MVVMCORE_EXPORT CoreAppPrivate : public QObject
public:
static QScopedPointer<CoreAppPrivate> &dInstance();
IPresenter *currentPresenter() const;
public Q_SLOTS:
void showViewModel(const QMetaObject *metaObject,
const QVariantHash &params,
QPointer<ViewModel> parent,
quint32 requestCode);
IPresenter *currentPresenter() const;
private Q_SLOTS:
void showViewModelPrivate(const QMetaObject *metaObject,
const QVariantHash &params,
QPointer<ViewModel> parent,
quint32 requestCode);
void showDialog(const MessageConfig &config, MessageResult *result);
private:
CoreAppPrivate();

2
src/mvvmcore/ipresenter.h

@ -5,6 +5,7 @@
#include "QtMvvmCore/qtmvvmcore_global.h"
#include "QtMvvmCore/viewmodel.h"
#include "QtMvvmCore/message.h"
namespace QtMvvm {
@ -30,6 +31,7 @@ public:
inline virtual ~IPresenter() = default;
virtual void present(ViewModel *viewModel, const QVariantHash &params, QPointer<ViewModel> parent = nullptr) = 0;
virtual void showDialog(const MessageConfig &config, MessageResult *result) = 0;
};
}

540
src/mvvmcore/message.cpp

@ -1,13 +1,32 @@
#include "message.h"
#include "message_p.h"
#include "coreapp.h"
#include <QtGui/QGuiApplication>
using namespace QtMvvm;
MessageConfig::MessageConfig(MessageType type) :
d(new MessageConfigPrivate(type))
const QByteArray MessageConfig::TypeMessageBox = "msgbox";
const QByteArray MessageConfig::TypeInputDialog = "input";
const QByteArray MessageConfig::TypeFileDialog = "file";
const QByteArray MessageConfig::SubTypeInformation = "information";
const QByteArray MessageConfig::SubTypeWarning = "warning";
const QByteArray MessageConfig::SubTypeCritical = "critical";
const QByteArray MessageConfig::SubTypeQuestion = "question";
const QByteArray MessageConfig::SubTypeAbout = "about";
const QByteArray MessageConfig::SubTypeDir = "dir";
const QByteArray MessageConfig::SubTypeOpenFile = "open";
const QByteArray MessageConfig::SubTypeOpenFiles = "files";
const QByteArray MessageConfig::SubTypeSaveFile = "save";
MessageConfig::MessageConfig(const QByteArray &type, const QByteArray &subType) :
d(new MessageConfigPrivate(type, subType))
{
resetPositiveAction();
resetNegativeAction();
resetNeutralAction();
if(subType.isEmpty())
resetSubType();
resetButtons();
}
MessageConfig::MessageConfig(const MessageConfig &other) :
@ -22,11 +41,16 @@ MessageConfig &MessageConfig::operator=(const MessageConfig &other)
return (*this);
}
MessageConfig::MessageType MessageConfig::type() const
QByteArray MessageConfig::type() const
{
return d->type;
}
QByteArray MessageConfig::subType() const
{
return d->subType;
}
QString MessageConfig::title() const
{
return d->title;
@ -37,24 +61,14 @@ QString MessageConfig::text() const
return d->text;
}
QString MessageConfig::positiveAction() const
{
return d->positiveAction;
}
QString MessageConfig::negativeAction() const
MessageConfig::StandardButtons MessageConfig::buttons() const
{
return d->negativeAction;
return d->buttons;
}
QString MessageConfig::neutralAction() const
QHash<MessageConfig::StandardButton, QString> MessageConfig::buttonTexts() const
{
return d->neutralAction;
}
QByteArray MessageConfig::inputType() const
{
return d->inputType;
return d->buttonTexts;
}
QVariant MessageConfig::defaultValue() const
@ -62,113 +76,174 @@ QVariant MessageConfig::defaultValue() const
return d->defaultValue;
}
QVariantMap MessageConfig::editProperties() const
QVariantMap MessageConfig::viewProperties() const
{
return d->editProperties;
}
void MessageConfig::setType(MessageConfig::MessageType type)
void MessageConfig::setType(const QByteArray &type)
{
d->type = type;
resetPositiveAction();
resetNegativeAction();
resetNeutralAction();
}
void MessageConfig::setTitle(QString title)
void MessageConfig::setSubType(const QByteArray &subType)
{
d->title = title;
d->subType = subType;
}
void MessageConfig::setText(QString text)
void MessageConfig::setTitle(const QString &title)
{
d->text = text;
d->title = title;
}
void MessageConfig::setPositiveAction(QString positiveAction)
void MessageConfig::setText(const QString &text)
{
d->positiveAction = positiveAction;
d->text = text;
}
void MessageConfig::setNegativeAction(QString negativeAction)
void MessageConfig::setButtons(StandardButtons buttons)
{
d->negativeAction = negativeAction;
d->buttons = buttons;
}
void MessageConfig::setNeutralAction(QString neutralAction)
void MessageConfig::setButtonTexts(const QHash<StandardButton, QString> &buttonTexts)
{
d->neutralAction = neutralAction;
d->buttonTexts = buttonTexts;
}
void MessageConfig::setInputType(QByteArray inputType)
void MessageConfig::setButtonText(MessageConfig::StandardButton button, const QString &text)
{
d->inputType = inputType;
d->buttonTexts.insert(button, text);
}
void MessageConfig::setDefaultValue(QVariant defaultValue)
void MessageConfig::setDefaultValue(const QVariant &defaultValue)
{
d->defaultValue = defaultValue;
}
void MessageConfig::setEditProperties(QVariantMap editProperties)
void MessageConfig::setViewProperties(const QVariantMap &editProperties)
{
d->editProperties = editProperties;
}
void MessageConfig::resetPositiveAction()
void MessageConfig::setViewProperty(const QString &key, const QVariant &value)
{
switch (d->type) {
case Information:
case Warning:
case Critical:
case Input:
d->positiveAction = tr("Ok");
break;
case Question:
d->positiveAction = tr("Yes");
break;
default:
Q_UNREACHABLE();
break;
}
d->editProperties.insert(key, value);
}
void MessageConfig::resetSubType()
{
if(d->type == TypeMessageBox)
d->subType = SubTypeInformation;
else if(d->type == TypeInputDialog)
d->subType = QMetaType::typeName(QMetaType::QString);
else
d->subType.clear();
}
void MessageConfig::resetButtons()
{
if(d->type == TypeMessageBox) {
if(d->subType == SubTypeQuestion)
d->buttons = Yes | No;
else if(d->subType == SubTypeAbout)
d->buttons = Close;
else
d->buttons = Ok;
} else if(d->type == TypeInputDialog)
d->buttons = Ok | Cancel;
else
d->buttons = Ok;
d->buttonTexts.clear();
}
MessageResult::MessageResult() :
QObject(nullptr),
d(new MessageResultPrivate())
{}
MessageResult::~MessageResult() {}
bool MessageResult::hasResult() const
{
return d->result.isValid();
}
QVariant MessageResult::result() const
{
return d->result;
}
bool MessageResult::autoDelete() const
{
return d->autoDelete;
}
void MessageConfig::resetNegativeAction()
void MessageResult::setCloseTarget(QObject *closeObject, const QMetaMethod &closeMethod)
{
switch (d->type) {
case Input:
d->negativeAction = tr("Cancel");
Q_ASSERT_X(closeObject, Q_FUNC_INFO, "closeObject must not be null");
d->closeObject = closeObject;
d->closeMethod = closeMethod;
if(d->closeRequested)
d->closeMethod.invoke(d->closeObject, Qt::QueuedConnection);
}
void MessageResult::complete(MessageResult::ResultType result)
{
switch (result) {
case PositiveResult:
emit positiveAction();
break;
case Question:
d->negativeAction = tr("No");
case NegativeResult:
emit negativeAction();
break;
case Information:
case Warning:
case Critical:
d->negativeAction.clear();
case NeutralResult:
emit neutralAction();
break;
default:
Q_UNREACHABLE();
break;
}
emit anyAction(result);
if(d->autoDelete)
deleteLater();
}
void MessageConfig::resetNeutralAction()
void MessageResult::discardMessage()
{
d->neutralAction.clear();
if(d->closeObject && !d->closeRequested)
d->closeMethod.invoke(d->closeObject, Qt::QueuedConnection);
d->closeRequested = true;
}
void MessageResult::setResult(QVariant result)
{
d->result = result;
}
void MessageResult::setAutoDelete(bool autoDelete)
{
if (d->autoDelete == autoDelete)
return;
d->autoDelete = autoDelete;
emit autoDeleteChanged(autoDelete);
}
// ------------- Private Implementation -------------
QtMvvm::MessageConfigPrivate::MessageConfigPrivate(MessageConfig::MessageType type) :
QtMvvm::MessageConfigPrivate::MessageConfigPrivate(const QByteArray &type, const QByteArray &subType) :
QSharedData(),
type(type),
subType(subType),
title(),
text(),
positiveAction(),
negativeAction(),
neutralAction(),
inputType(),
buttons(MessageConfig::Ok),
buttonTexts(),
defaultValue(),
editProperties()
{}
@ -176,12 +251,325 @@ QtMvvm::MessageConfigPrivate::MessageConfigPrivate(MessageConfig::MessageType ty
QtMvvm::MessageConfigPrivate::MessageConfigPrivate(const QtMvvm::MessageConfigPrivate &other) :
QSharedData(other),
type(other.type),
subType(other.subType),
title(other.title),
text(other.text),
positiveAction(other.positiveAction),
negativeAction(other.negativeAction),
neutralAction(other.neutralAction),
inputType(other.inputType),
buttons(other.buttons),
buttonTexts(other.buttonTexts),
defaultValue(other.defaultValue),
editProperties(other.editProperties)
{}
MessageResultPrivate::MessageResultPrivate() :
closeObject(nullptr),
closeMethod(),
closeRequested(false),
result(),
autoDelete(true)
{}
// ------------- Namespace methods implementation -------------
MessageResult *QtMvvm::information(const QString &title, const QString &text, const QString &okText)
{
MessageConfig config(MessageConfig::TypeMessageBox, MessageConfig::SubTypeInformation);
config.setTitle(title);
config.setText(text);
if(!okText.isNull())
config.setButtonText(MessageConfig::Ok, okText);
return CoreApp::showDialog(config);
}
void QtMvvm::information(const QString &title, const QString &text, QObject *scope, std::function<void ()> onResult, const QString &okText)
{
auto result = information(title, text, okText);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, onResult,
Qt::QueuedConnection);
}
}
void QtMvvm::information(const QString &title, const QString &text, std::function<void ()> onResult, const QString &okText)
{
information(title, text, CoreApp::instance(), onResult, okText);
}
MessageResult *QtMvvm::question(const QString &title, const QString &text, const QString &yesText, const QString &noText)
{
MessageConfig config(MessageConfig::TypeMessageBox, MessageConfig::SubTypeQuestion);
config.setTitle(title);
config.setText(text);
if(!yesText.isNull())
config.setButtonText(MessageConfig::Yes, yesText);
if(!noText.isNull())
config.setButtonText(MessageConfig::No, noText);
return CoreApp::showDialog(config);
}
void QtMvvm::question(const QString &title, const QString &text, QObject *scope, std::function<void (bool)> onResult, const QString &yesText, const QString &noText)
{
auto result = question(title, text, yesText, noText);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, [onResult](MessageResult::ResultType type) {
onResult(type == MessageResult::PositiveResult);
}, Qt::QueuedConnection);
}
}
void QtMvvm::question(const QString &title, const QString &text, std::function<void (bool)> onResult, const QString &yesText, const QString &noText)
{
question(title, text, CoreApp::instance(), onResult, yesText, noText);
}
MessageResult *QtMvvm::warning(const QString &title, const QString &text, const QString &okText)
{
MessageConfig config(MessageConfig::TypeMessageBox, MessageConfig::SubTypeWarning);
config.setTitle(title);
config.setText(text);
if(!okText.isNull())
config.setButtonText(MessageConfig::Ok, okText);
return CoreApp::showDialog(config);
}
void QtMvvm::warning(const QString &title, const QString &text, QObject *scope, std::function<void ()> onResult, const QString &okText)
{
auto result = warning(title, text, okText);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, onResult,
Qt::QueuedConnection);
}
}
void QtMvvm::warning(const QString &title, const QString &text, std::function<void ()> onResult, const QString &okText)
{
warning(title, text, CoreApp::instance(), onResult, okText);
}
MessageResult *QtMvvm::critical(const QString &title, const QString &text, const QString &okText)
{
MessageConfig config(MessageConfig::TypeMessageBox, MessageConfig::SubTypeCritical);
config.setTitle(title);
config.setText(text);
if(!okText.isNull())
config.setButtonText(MessageConfig::Ok, okText);
return CoreApp::showDialog(config);
}
void QtMvvm::critical(const QString &title, const QString &text, QObject *scope, std::function<void ()> onResult, const QString &okText)
{
auto result = critical(title, text, okText);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, onResult,
Qt::QueuedConnection);
}
}
void QtMvvm::critical(const QString &title, const QString &text, std::function<void ()> onResult, const QString &okText)
{
critical(title, text, CoreApp::instance(), onResult, okText);
}
MessageResult *QtMvvm::about(const QString &description, const QUrl &websiteUrl, const QString &licenseName, const QUrl &licenseUrl, const QString &companyName, bool addQtVersion, const QStringList &extraTopInfos, const QString &extraBottomInfos)
{
static const QString pBegin = QStringLiteral("<p>");
static const QString pEnd = QStringLiteral("</p>");
static const QString br = QStringLiteral("<br/>");
MessageConfig config(MessageConfig::TypeMessageBox, MessageConfig::SubTypeAbout);
config.setViewProperty(QStringLiteral("addQtVersion"), addQtVersion);
config.setTitle(MessageConfig::tr("%1 — Version %2")
.arg(QGuiApplication::applicationDisplayName())
.arg(QCoreApplication::applicationVersion()));
//create the content string:
//basic text
QString text = pBegin + description + pEnd;
//qt version info + extra infos
if(addQtVersion || !extraTopInfos.isEmpty()) {
text += pBegin;
if(addQtVersion) {
auto runtimeVers = qVersion();
auto compileVers = QT_VERSION_STR;
QString qtVersion;
if(qstrcmp(runtimeVers, compileVers) == 0)
qtVersion = QString::fromUtf8(runtimeVers);
else {
qtVersion = MessageConfig::tr("%1 (Built with %2)")
.arg(QString::fromUtf8(runtimeVers))
.arg(QString::fromUtf8(runtimeVers));
}
text += MessageConfig::tr("Qt-Version: <a href=\"https://www.qt.io/\">%2</a>")
.arg(qtVersion);
}
if(!extraTopInfos.isEmpty()) {
auto withBr = addQtVersion;
foreach(auto info, extraTopInfos){
text += info + (withBr ? br : QString());
withBr = true;
}
}
text += pEnd;
}
//Developer info
text += pBegin + MessageConfig::tr("Developed by: %1")
.arg(companyName.isEmpty() ? QCoreApplication::organizationName() : companyName);
if(websiteUrl.isValid()) {
text += br + MessageConfig::tr("Project Website: <a href=\"%1\">%2</a>")
.arg(QString::fromUtf8(websiteUrl.toEncoded()))
.arg(websiteUrl.toString());
}
if(!licenseName.isEmpty()) {
if(licenseUrl.isValid()) {
text += br + MessageConfig::tr("License: <a href=\"%1\">%2</a>")
.arg(QString::fromUtf8(licenseUrl.toEncoded()))
.arg(licenseName);
} else {
text += br + MessageConfig::tr("License: %1")
.arg(licenseName);
}
}
text += pEnd;
//extra bottom infos
if(!extraBottomInfos.isEmpty())
text += pBegin + extraBottomInfos + pEnd;
//set in the config
config.setText(text);
return CoreApp::showDialog(config);
}
MessageResult *QtMvvm::getInput(const QString &title, const QString &text, const char *inputType, const QVariant &defaultValue, const QVariantMap &viewProperties, const QString &okText, const QString &cancelText)
{
MessageConfig config(MessageConfig::TypeInputDialog, inputType);
config.setTitle(title);
config.setText(text);
config.setDefaultValue(defaultValue);
config.setViewProperties(viewProperties);
if(!okText.isNull())
config.setButtonText(MessageConfig::Ok, okText);
if(!cancelText.isNull())
config.setButtonText(MessageConfig::Cancel, cancelText);
return CoreApp::showDialog(config);
}
void QtMvvm::getInput(const QString &title, const QString &text, const char *inputType, QObject *scope, std::function<void (QVariant)> onResult, const QVariant &defaultValue, const QVariantMap &viewProperties, const QString &okText, const QString &cancelText)
{
auto result = getInput(title, text, inputType, defaultValue, viewProperties, okText, cancelText);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, [onResult, result](MessageResult::ResultType type) {
onResult(type == MessageResult::PositiveResult ? result->result() : QVariant());
}, Qt::QueuedConnection);
}
}
void QtMvvm::getInput(const QString &title, const QString &text, const char *inputType, std::function<void (QVariant)> onResult, const QVariant &defaultValue, const QVariantMap &viewProperties, const QString &okText, const QString &cancelText)
{
getInput(title, text, inputType, CoreApp::instance(), onResult, defaultValue, viewProperties, okText, cancelText);
}
MessageResult *QtMvvm::getExistingDirectory(const QString &title, const QUrl &dir)
{
MessageConfig config(MessageConfig::TypeFileDialog, MessageConfig::SubTypeDir);
config.setTitle(title);
config.setDefaultValue(dir);
return CoreApp::showDialog(config);
}
void QtMvvm::getExistingDirectory(QObject *scope, std::function<void (QUrl)> onResult, const QString &title, const QUrl &dir)
{
auto result = getExistingDirectory(title, dir);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, [onResult, result](MessageResult::ResultType type) {
onResult(type == MessageResult::PositiveResult ? result->result().toUrl() : QUrl());
}, Qt::QueuedConnection);
}
}
void QtMvvm::getExistingDirectory(std::function<void (QUrl)> onResult, const QString &title, const QUrl &dir)
{
getExistingDirectory(CoreApp::instance(), onResult, title, dir);
}
MessageResult *QtMvvm::getOpenFile(const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
MessageConfig config(MessageConfig::TypeFileDialog, MessageConfig::SubTypeOpenFile);
config.setTitle(title);
config.setDefaultValue(dir);
config.setViewProperty(QStringLiteral("mimeTypes"), supportedMimeTypes);
return CoreApp::showDialog(config);
}
void QtMvvm::getOpenFile(QObject *scope, std::function<void (QUrl)> onResult, const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
auto result = getOpenFile(title, supportedMimeTypes, dir);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, [onResult, result](MessageResult::ResultType type) {
onResult(type == MessageResult::PositiveResult ? result->result().toUrl() : QUrl());
}, Qt::QueuedConnection);
}
}
void QtMvvm::getOpenFile(std::function<void (QUrl)> onResult, const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
getOpenFile(CoreApp::instance(), onResult, title, supportedMimeTypes, dir);
}
MessageResult *QtMvvm::getOpenFiles(const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
MessageConfig config(MessageConfig::TypeFileDialog, MessageConfig::SubTypeOpenFiles);
config.setTitle(title);
config.setDefaultValue(dir);
config.setViewProperty(QStringLiteral("mimeTypes"), supportedMimeTypes);
return CoreApp::showDialog(config);
}
void QtMvvm::getOpenFiles(QObject *scope, std::function<void (QList<QUrl>)> onResult, const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
auto result = getOpenFiles(title, supportedMimeTypes, dir);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, [onResult, result](MessageResult::ResultType type) {
onResult(type == MessageResult::PositiveResult ? result->result().value<QList<QUrl>>() : QList<QUrl>());
}, Qt::QueuedConnection);
}
}
void QtMvvm::getOpenFiles(std::function<void (QList<QUrl>)> onResult, const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
getOpenFiles(CoreApp::instance(), onResult, title, supportedMimeTypes, dir);
}
MessageResult *QtMvvm::getSaveFile(const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
MessageConfig config(MessageConfig::TypeFileDialog, MessageConfig::SubTypeOpenFile);
config.setTitle(title);
config.setDefaultValue(dir);
config.setViewProperty(QStringLiteral("mimeTypes"), supportedMimeTypes);
return CoreApp::showDialog(config);
}
void QtMvvm::getSaveFile(QObject *scope, std::function<void (QUrl)> onResult, const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
auto result = getSaveFile(title, supportedMimeTypes, dir);
if(result) {
QObject::connect(result, &MessageResult::anyAction,
scope, [onResult, result](MessageResult::ResultType type) {
onResult(type == MessageResult::PositiveResult ? result->result().toUrl() : QUrl());
}, Qt::QueuedConnection);
}
}
void QtMvvm::getSaveFile(std::function<void (QUrl)> onResult, const QString &title, const QStringList &supportedMimeTypes, const QUrl &dir)
{
getSaveFile(CoreApp::instance(), onResult, title, supportedMimeTypes, dir);
}

326
src/mvvmcore/message.h

@ -1,8 +1,13 @@
#ifndef QTMVVM_MESSAGE_H
#define QTMVVM_MESSAGE_H
#include <functional>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
#include "QtMvvmCore/qtmvvmcore_global.h"
@ -14,65 +19,320 @@ class Q_MVVMCORE_EXPORT MessageConfig
Q_GADGET
Q_DECLARE_TR_FUNCTIONS(MessageConfig)
Q_PROPERTY(MessageType type READ type WRITE setType)
Q_PROPERTY(QByteArray type READ type WRITE setType)
Q_PROPERTY(QByteArray subType READ subType WRITE setSubType RESET resetSubType)
Q_PROPERTY(QString title READ title WRITE setTitle)
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(QString positiveAction READ positiveAction WRITE setPositiveAction RESET resetPositiveAction)
Q_PROPERTY(QString negativeAction READ negativeAction WRITE setNegativeAction RESET resetNegativeAction)
Q_PROPERTY(QString neutralAction READ neutralAction WRITE setNeutralAction RESET resetNeutralAction)
Q_PROPERTY(QByteArray inputType READ inputType WRITE setInputType)
Q_PROPERTY(StandardButtons buttons READ buttons WRITE setButtons RESET resetButtons)
Q_PROPERTY(QHash<StandardButton, QString> buttonTexts READ buttonTexts WRITE setButtonTexts RESET resetButtons)
Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue)
Q_PROPERTY(QVariantMap editProperties READ editProperties WRITE setEditProperties)
Q_PROPERTY(QVariantMap viewProperties READ viewProperties WRITE setViewProperties)
public:
enum MessageType {
Information,
Question,
Warning,
Critical,
Input
enum StandardButton {
// keep this in sync with QPlatformDialogHelper::StandardButton
NoButton = 0x00000000,
Ok = 0x00000400,
Save = 0x00000800,
SaveAll = 0x00001000,
Open = 0x00002000,
Yes = 0x00004000,
YesToAll = 0x00008000,
No = 0x00010000,
NoToAll = 0x00020000,
Abort = 0x00040000,
Retry = 0x00080000,
Ignore = 0x00100000,
Close = 0x00200000,
Cancel = 0x00400000,
Discard = 0x00800000,
Help = 0x01000000,
Apply = 0x02000000,
Reset = 0x04000000,
RestoreDefaults = 0x08000000
};
Q_ENUM(MessageType)
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
Q_FLAG(StandardButtons)
static const QByteArray TypeMessageBox;
static const QByteArray TypeInputDialog;
static const QByteArray TypeFileDialog;
static const QByteArray SubTypeInformation;
static const QByteArray SubTypeWarning;
static const QByteArray SubTypeCritical;
static const QByteArray SubTypeQuestion;
static const QByteArray SubTypeAbout;
MessageConfig(MessageType type = Information);
static const QByteArray SubTypeDir;
static const QByteArray SubTypeOpenFile;
static const QByteArray SubTypeOpenFiles;
static const QByteArray SubTypeSaveFile;
MessageConfig(const QByteArray &type = TypeMessageBox, const QByteArray &subType = {});
MessageConfig(const MessageConfig &other);
~MessageConfig();
MessageConfig &operator=(const MessageConfig &other);
MessageType type() const;
QByteArray type() const;
QByteArray subType() const;
QString title() const;
QString text() const;
QString positiveAction() const;
QString negativeAction() const;
QString neutralAction() const;
StandardButtons buttons() const;
QHash<StandardButton, QString> buttonTexts() const;
QByteArray inputType() const;
QVariant defaultValue() const;
QVariantMap editProperties() const;
void setType(MessageType type);
void setTitle(QString title);
void setText(QString text);
void setPositiveAction(QString positiveAction);
void setNegativeAction(QString negativeAction);
void setNeutralAction(QString neutralAction);
void setInputType(QByteArray inputType);
void setDefaultValue(QVariant defaultValue);
void setEditProperties(QVariantMap editProperties);
void resetPositiveAction();
void resetNegativeAction();
void resetNeutralAction();
QVariantMap viewProperties() const;
void setType(const QByteArray &type);
void setSubType(const QByteArray &subType);
void setTitle(const QString &title);
void setText(const QString &text);
void setButtons(StandardButtons buttons);
void setButtonTexts(const QHash<StandardButton, QString> &buttonTexts);
void setButtonText(StandardButton button, const QString &text);
void setDefaultValue(const QVariant &defaultValue);
void setViewProperties(const QVariantMap &viewProperties);
void setViewProperty(const QString &key, const QVariant &value);
void resetSubType();
void resetButtons();
private:
QSharedDataPointer<MessageConfigPrivate> d;
};
class MessageResultPrivate;
class Q_MVVMCORE_EXPORT MessageResult : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant result READ result WRITE setResult)
Q_PROPERTY(bool autoDelete READ autoDelete WRITE setAutoDelete NOTIFY autoDeleteChanged)
public:
enum ResultType {
PositiveResult,
NegativeResult,
NeutralResult
};
Q_ENUM(ResultType)
explicit MessageResult();
~MessageResult();
bool hasResult() const;
QVariant result() const;
bool autoDelete() const;
//USE IN GUI ONLY
//TODO USE IN GUI ONLY in doc
Q_INVOKABLE void setCloseTarget(QObject *closeObject, const QMetaMethod &closeMethod);
Q_INVOKABLE void complete(MessageResult::ResultType result);
Q_INVOKABLE inline void complete(MessageResult::ResultType result, const QVariant &resultValue) {
setResult(resultValue);
complete(result);
}
public Q_SLOTS:
void discardMessage();
void setResult(QVariant result);
void setAutoDelete(bool autoDelete);
Q_SIGNALS:
void positiveAction();
void negativeAction();
void neutralAction();
void anyAction(ResultType result);
void autoDeleteChanged(bool autoDelete);
private:
QScopedPointer<MessageResultPrivate> d;
};
Q_MVVMCORE_EXPORT MessageResult *information(const QString &title,
const QString &text,
const QString &okText = {});
Q_MVVMCORE_EXPORT void information(const QString &title,
const QString &text,
QObject *scope,
std::function<void()> onResult,
const QString &okText = {});
Q_MVVMCORE_EXPORT void information(const QString &title,
const QString &text,
std::function<void()> onResult,
const QString &okText = {});
Q_MVVMCORE_EXPORT MessageResult *question(const QString &title,
const QString &text,
const QString &yesText = {},
const QString &noText = {});
Q_MVVMCORE_EXPORT void question(const QString &title,
const QString &text,
QObject *scope,
std::function<void(bool)> onResult,
const QString &yesText = {},
const QString &noText = {});
Q_MVVMCORE_EXPORT void question(const QString &title,
const QString &text,
std::function<void(bool)> onResult,
const QString &yesText = {},
const QString &noText = {});
Q_MVVMCORE_EXPORT MessageResult *warning(const QString &title,
const QString &text,
const QString &okText = {});
Q_MVVMCORE_EXPORT void warning(const QString &title,
const QString &text,
QObject *scope,
std::function<void()> onResult,
const QString &okText = {});
Q_MVVMCORE_EXPORT void warning(const QString &title,
const QString &text,
std::function<void()> onResult,
const QString &okText = {});
Q_MVVMCORE_EXPORT MessageResult *critical(const QString &title,
const QString &text,
const QString &okText = {});
Q_MVVMCORE_EXPORT void critical(const QString &title,
const QString &text,
QObject *scope,
std::function<void()> onResult,
const QString &okText = {});
Q_MVVMCORE_EXPORT void critical(const QString &title,
const QString &text,
std::function<void()> onResult,
const QString &okText = {});
Q_MVVMCORE_EXPORT MessageResult *about(const QString &description,
const QUrl &websiteUrl = QUrl(),
const QString &licenseName = QString(),
const QUrl &licenseUrl = QUrl(),
const QString &companyName = QString(),
bool addQtVersion = true,
const QStringList &extraTopInfos = QStringList(),
const QString &extraBottomInfos = QString());
Q_MVVMCORE_EXPORT MessageResult *getInput(const QString &title,
const QString &text,
const char *inputType,
const QVariant &defaultValue = {},
const QVariantMap &viewProperties = {},
const QString &okText = {},
const QString &cancelText = {});
Q_MVVMCORE_EXPORT void getInput(const QString &title,
const QString &text,
const char *inputType,
QObject *scope,
std::function<void(QVariant)> onResult,
const QVariant &defaultValue = {},
const QVariantMap &viewProperties = {},
const QString &okText = {},
const QString &cancelText = {});
Q_MVVMCORE_EXPORT void getInput(const QString &title,
const QString &text,
const char *inputType,
std::function<void(QVariant)> onResult,
const QVariant &defaultValue = {},
const QVariantMap &viewProperties = {},
const QString &okText = {},
const QString &cancelText = {});
template <typename TEdit>
inline MessageResult *getInput(const QString &title,
const QString &text,
const QVariant &defaultValue = {},
const QVariantMap &viewProperties = {},
const QString &okText = {},
const QString &cancelText = {}) {
return getInput(title, text, QMetaType::typeName(qMetaTypeId<TEdit>()), defaultValue, viewProperties, okText, cancelText);
}
template <typename TEdit>
inline void getInput(const QString &title,
const QString &text,
QObject *scope,
std::function<void(TEdit)> onResult,
const QVariant &defaultValue = {},
const QVariantMap &viewProperties = {},
const QString &okText = {},
const QString &cancelText = {}) {
getInput(title, text, QMetaType::typeName(qMetaTypeId<TEdit>()), scope, [onResult](QVariant v) {
onResult(v.template value<TEdit>());
}, defaultValue, viewProperties, okText, cancelText);
}
template <typename TEdit>
inline void getInput(const QString &title,
const QString &text,
std::function<void(TEdit)> onResult,
const QVariant &defaultValue = {},
const QVariantMap &viewProperties = {},
const QString &okText = {},
const QString &cancelText = {}) {
getInput(title, text, QMetaType::typeName(qMetaTypeId<TEdit>()), [onResult](QVariant v) {
onResult(v.template value<TEdit>());
}, defaultValue, viewProperties, okText, cancelText);
}
Q_MVVMCORE_EXPORT MessageResult *getExistingDirectory(const QString &title = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getExistingDirectory(QObject *scope,
std::function<void(QUrl)> onResult,
const QString &title = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getExistingDirectory(std::function<void(QUrl)> onResult,
const QString &title = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT MessageResult *getOpenFile(const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getOpenFile(QObject *scope,
std::function<void(QUrl)> onResult,
const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getOpenFile(std::function<void(QUrl)> onResult,
const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT MessageResult *getOpenFiles(const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getOpenFiles(QObject *scope,
std::function<void(QList<QUrl>)> onResult,
const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getOpenFiles(std::function<void(QList<QUrl>)> onResult,
const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT MessageResult *getSaveFile(const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getSaveFile(QObject *scope,
std::function<void(QUrl)> onResult,
const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
Q_MVVMCORE_EXPORT void getSaveFile(std::function<void(QUrl)> onResult,
const QString &title = {},
const QStringList &supportedMimeTypes = {},
const QUrl &dir = {});
}
Q_DECLARE_METATYPE(QtMvvm::MessageConfig)
Q_DECLARE_TYPEINFO(QtMvvm::MessageConfig, Q_MOVABLE_TYPE);
Q_DECLARE_METATYPE(QtMvvm::MessageResult*)
Q_DECLARE_OPERATORS_FOR_FLAGS(QtMvvm::MessageConfig::StandardButtons)
#endif // QTMVVM_MESSAGE_H

23
src/mvvmcore/message_p.h

@ -9,20 +9,31 @@ namespace QtMvvm {
class MessageConfigPrivate : public QSharedData
{
public:
MessageConfigPrivate(MessageConfig::MessageType type);
MessageConfigPrivate(const QByteArray &type, const QByteArray &subType);
MessageConfigPrivate(const MessageConfigPrivate &other);
MessageConfig::MessageType type;
QByteArray type;
QByteArray subType;
QString title;
QString text;
QString positiveAction;
QString negativeAction;
QString neutralAction;
QByteArray inputType;
MessageConfig::StandardButtons buttons;
QHash<MessageConfig::StandardButton, QString> buttonTexts;
QVariant defaultValue;
QVariantMap editProperties;
};
class MessageResultPrivate
{
public:
MessageResultPrivate();
QPointer<QObject> closeObject;
QMetaMethod closeMethod;
bool closeRequested;
QVariant result;
bool autoDelete;
};
}
#endif // QTMVVM_MESSAGE_P_H

4
src/mvvmcore/serviceregistry.cpp

@ -96,9 +96,9 @@ QObject *ServiceRegistryPrivate::constructInjectedLocked(const QMetaObject *meta
throw ServiceConstructionException("Failed to convert QObject to interface with iid \"" +
iid +
"\". Use QtMvvm::registerInterfaceConverter to make it convertable "
"or change the properties type to \"QObject*\"");
"or change the property's type to \"QObject*\"");
}
tProp.write(instance, variant); //TODO check if casting works
tProp.write(instance, variant);
}
}

16
src/mvvmcore/viewmodel.cpp

@ -61,18 +61,16 @@ void ViewModel::showForResult(quint32 requestCode, const QMetaObject *viewMetaOb
viewMetaObject->className() +
QByteArrayLiteral(") is not a class that extends QtMvvm::ViewModel"));
}
showResultImp(requestCode, viewMetaObject, params);
showImp(viewMetaObject, params, const_cast<ViewModel*>(this), requestCode);
}
void ViewModel::showImp(const QMetaObject *mo, const QVariantHash &params, QPointer<ViewModel> parent)
void ViewModel::showImp(const QMetaObject *metaObject, const QVariantHash &params, QPointer<ViewModel> parent, quint32 requestCode)
{
CoreAppPrivate::dInstance()->showViewModel(mo, params, parent, 0);
}
void ViewModel::showResultImp(quint32 requestCode, const QMetaObject *mo, const QVariantHash &params) const
{
Q_ASSERT_X(requestCode != 0, Q_FUNC_INFO, "requestCode must not be 0");
CoreAppPrivate::dInstance()->showViewModel(mo, params, const_cast<ViewModel*>(this), requestCode);
QMetaObject::invokeMethod(CoreAppPrivate::dInstance().data(), "showViewModel", Qt::QueuedConnection,
Q_ARG(const QMetaObject*, metaObject),
Q_ARG(const QVariantHash&, params),
Q_ARG(QPointer<ViewModel>, parent),
Q_ARG(quint32, requestCode));
}
// ------------- Private Implementation -------------

5
src/mvvmcore/viewmodel.h

@ -45,8 +45,7 @@ private:
QScopedPointer<ViewModelPrivate> d;
static void showImp(const QMetaObject *mo, const QVariantHash &params, QPointer<ViewModel> parent);
void showResultImp(quint32 requestCode, const QMetaObject *mo, const QVariantHash &params) const;
static void showImp(const QMetaObject *metaObject, const QVariantHash &params, QPointer<ViewModel> parent, quint32 requestCode = 0);
};
// ------------- Generic Implementation -------------
@ -62,7 +61,7 @@ template<typename TViewModel>
void ViewModel::showForResult(quint32 requestCode, const QVariantHash &params) const
{
static_assert(std::is_base_of<ViewModel, TViewModel>::value, "TViewModel must extend QtMvvm::ViewModel");
showResultImp(requestCode, &TViewModel::staticMetaObject, params);
showImp(&TViewModel::staticMetaObject, params, const_cast<ViewModel*>(this), requestCode);
}
}

24
src/mvvmwidgets/widgetspresenter.cpp

@ -77,6 +77,11 @@ void WidgetsPresenter::present(ViewModel *viewModel, const QVariantHash &params,
}
}
void WidgetsPresenter::showDialog(const MessageConfig &config, MessageResult *result)
{
Q_UNIMPLEMENTED();
}
const QMetaObject *WidgetsPresenter::findWidgetMetaObject(const QMetaObject *viewModelMetaObject)
{
auto currentMeta = viewModelMetaObject;
@ -149,22 +154,9 @@ bool WidgetsPresenter::tryPresent(QWidget *view, QWidget *parentView)
bool WidgetsPresenter::setupLifeCycle(ViewModel *viewModel, QWidget *view)
{
//TODO fix
return false;
auto viewMo = view->metaObject();
if(viewMo->indexOfSignal("qtmvvm_visibleChanged(bool)") != -1) {
connect(view, SIGNAL(qtmvvm_visibleChanged(bool)),
viewModel, SLOT(updateVisible(bool)));
return true;
}
if(viewMo->indexOfSignal("visibleChanged(bool)") != -1) {
connect(view, SIGNAL(visibleChanged(bool)),
viewModel, SLOT(updateVisible(bool)));
return true;
}
//TODO implement as soon as quick part is ready as well
Q_UNUSED(viewModel)
Q_UNUSED(view)
return false;
}

1
src/mvvmwidgets/widgetspresenter.h

@ -35,6 +35,7 @@ public:
static void registerViewExplicitly(const QMetaObject *viewModelType, const QMetaObject *viewType);
void present(ViewModel *viewModel, const QVariantHash &params, QPointer<ViewModel> parent) override;
void showDialog(const MessageConfig &config, MessageResult *result) override;
protected:
virtual const QMetaObject *findWidgetMetaObject(const QMetaObject *viewModelMetaObject);

Loading…
Cancel
Save