Browse Source

Added support for container based presentation

pull/2/head
Skycoder42 7 years ago
parent
commit
9787a8092f
No known key found for this signature in database GPG Key ID: 8E01AD9EF0578D2B
  1. 4
      examples/mvvmcore/SampleCore/drawerviewmodel.cpp
  2. 2
      examples/mvvmcore/SampleCore/samplecoreapp.cpp
  3. 4
      examples/mvvmcore/SampleCore/sampleviewmodel.cpp
  4. 4
      examples/mvvmcore/SampleCore/tabviewmodel.h
  5. 120
      src/mvvmcore/coreapp.cpp
  6. 8
      src/mvvmcore/coreapp_p.h
  7. 2
      src/mvvmcore/viewmodel.h
  8. 20
      src/mvvmquick/quickpresenter.cpp

4
examples/mvvmcore/SampleCore/drawerviewmodel.cpp

@ -30,7 +30,9 @@ void DrawerViewModel::open(int index)
show<SampleViewModel>(); show<SampleViewModel>();
break; break;
case 1: case 1:
show<TabViewModel>(); show<TabItemViewModel>({
{QStringLiteral("title"), QStringLiteral("Root Tab")}
});
break; break;
case 2: case 2:
show<QtMvvm::SettingsViewModel>(); show<QtMvvm::SettingsViewModel>();

2
examples/mvvmcore/SampleCore/samplecoreapp.cpp

@ -1,6 +1,7 @@
#include "samplecoreapp.h" #include "samplecoreapp.h"
#include "sampleviewmodel.h" #include "sampleviewmodel.h"
#include "drawerviewmodel.h" #include "drawerviewmodel.h"
#include "tabviewmodel.h"
#include <QtCore/QLoggingCategory> #include <QtCore/QLoggingCategory>
#include <QtCore/QCommandLineParser> #include <QtCore/QCommandLineParser>
@ -33,6 +34,7 @@ void SampleCoreApp::performRegistrations()
{ {
Q_INIT_RESOURCE(sample_core); Q_INIT_RESOURCE(sample_core);
qRegisterMetaType<TabViewModel*>();
QtMvvm::registerInterfaceConverter<IEventService>(); QtMvvm::registerInterfaceConverter<IEventService>();
QLoggingCategory::setFilterRules(QStringLiteral("qtmvvm.debug=true")); QLoggingCategory::setFilterRules(QStringLiteral("qtmvvm.debug=true"));

4
examples/mvvmcore/SampleCore/sampleviewmodel.cpp

@ -68,7 +68,9 @@ void SampleViewModel::setActive(bool active)
void SampleViewModel::showTabs() void SampleViewModel::showTabs()
{ {
show<TabViewModel>(); show<TabItemViewModel>({
{QStringLiteral("title"), QStringLiteral("Root Tab")}
});
} }
void SampleViewModel::showSettings() void SampleViewModel::showSettings()

4
examples/mvvmcore/SampleCore/tabviewmodel.h

@ -23,6 +23,8 @@ class TabItemViewModel : public QtMvvm::ViewModel
Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(QString title READ title NOTIFY titleChanged)
QTMVVM_CONTAINER_VM(TabViewModel)
public: public:
Q_INVOKABLE explicit TabItemViewModel(QObject *parent = nullptr); Q_INVOKABLE explicit TabItemViewModel(QObject *parent = nullptr);
~TabItemViewModel(); ~TabItemViewModel();
@ -39,4 +41,6 @@ private:
QString _title; QString _title;
}; };
Q_DECLARE_METATYPE(TabViewModel*)
#endif // TABVIEWMODEL_H #endif // TABVIEWMODEL_H

120
src/mvvmcore/coreapp.cpp

@ -171,23 +171,107 @@ QScopedPointer<CoreAppPrivate> &CoreAppPrivate::dInstance()
} }
void CoreAppPrivate::showViewModel(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)
{
showViewModelWithReturn(metaObject, params, std::move(parent), requestCode);
}
void CoreAppPrivate::showDialog(const MessageConfig &config, MessageResult *result)
{ {
if(presenter) { if(presenter) {
//first: check for single instance try {
auto isSingleton = false; presenter->showDialog(config, result);
logDebug() << "Successfully presented dialog of type" << config.type();
} catch(QException &e) {
logCritical() << "Failed to show dialog for type"
<< config.type() << ":" << config.subType()
<< "with error:"
<< e.what();
result->complete(MessageConfig::NoButton);
}
} else {
logCritical() << "Failed to show dialog ff type"
<< config.type() << ":" << config.subType()
<< "- no presenter was set";
result->complete(MessageConfig::NoButton);
}
}
bool CoreAppPrivate::isSingleton(const QMetaObject *metaObject) const
{
auto sInfoIndex = metaObject->indexOfClassInfo("qtmvvm_singleton"); auto sInfoIndex = metaObject->indexOfClassInfo("qtmvvm_singleton");
if(sInfoIndex != -1) { if(sInfoIndex != -1) {
auto sInfo = metaObject->classInfo(sInfoIndex); auto sInfo = metaObject->classInfo(sInfoIndex);
Q_ASSERT(qstrcmp(sInfo.name(), "qtmvvm_singleton") == 0); Q_ASSERT(qstrcmp(sInfo.name(), "qtmvvm_singleton") == 0);
isSingleton = qstrcmp(sInfo.value(), "true") == 0; return qstrcmp(sInfo.value(), "true") == 0;
} else
return false;
}
const QMetaObject *CoreAppPrivate::getContainer(const QMetaObject *metaObject) const
{
auto cInfoIndex = metaObject->indexOfClassInfo("qtmvvm_container_viewmodel");
if(cInfoIndex != -1) {
auto cInfo = metaObject->classInfo(cInfoIndex);
Q_ASSERT(qstrcmp(cInfo.name(), "qtmvvm_container_viewmodel") == 0);
auto typeId = QMetaType::type(QByteArray{cInfo.value() + QByteArray{"*"}}.constData());
if(typeId == QMetaType::UnknownType) {
throw PresenterException {
QByteArrayLiteral("Unabled to find the qtmvvm_container_viewmodel of type \"") + cInfo.value() +
QByteArrayLiteral("\" for viewmodel of type \"") + metaObject->className() + QByteArrayLiteral("\"")
};
}
auto containerMo = QMetaType::metaObjectForType(typeId);
if(!containerMo) {
throw PresenterException {
QByteArrayLiteral("The qtmvvm_container_viewmodel of type \"") + cInfo.value() +
QByteArrayLiteral("\" for viewmodel of type \"") + metaObject->className() +
QByteArrayLiteral("\" does exists, but does not have a QMetaObject")
};
}
if(!containerMo->inherits(&ViewModel::staticMetaObject)) {
throw PresenterException {
QByteArrayLiteral("The qtmvvm_container_viewmodel of type \"") + cInfo.value() +
QByteArrayLiteral("\" for viewmodel of type \"") + metaObject->className() +
QByteArrayLiteral("\" does exists, but does not extend QtMvvm::ViewModel")
};
}
return containerMo;
} else
return nullptr;
}
QPointer<ViewModel> CoreAppPrivate::showViewModelWithReturn(const QMetaObject *metaObject, const QVariantHash &params, QPointer<ViewModel> parent, quint32 requestCode)
{
if(presenter) {
// first: check if it has a container, and if yes: show the container
try {
auto container = getContainer(metaObject);
if(container) {
logDebug() << "Found container type for" << metaObject->className()
<< "as" << container->className();
parent = showViewModelWithReturn(container, { //TODO document special parameters
{QStringLiteral("qtmvvm_container_for"), QByteArray{metaObject->className()}},
{QStringLiteral("qtmvvm_child_params"), params}
}, std::move(parent), 0);
if(!parent)
throw PresenterException{"Failed to present parent container"};
}
} catch(PresenterException &e) {
logCritical() << "Failed to present viewmodel of type"
<< metaObject->className()
<< "with error:"
<< e.what();
return nullptr;
} }
// next handle the singleton // next: handle a singleton
if(isSingleton) { auto isSingle = isSingleton(metaObject);
if(isSingle) {
auto viewModel = singleInstances.value(metaObject); auto viewModel = singleInstances.value(metaObject);
if(viewModel) { if(viewModel) {
logDebug() << "Found existing single instance for" << metaObject->className();
emit viewModel->instanceInvoked(ViewModel::QPrivateSignal{}); emit viewModel->instanceInvoked(ViewModel::QPrivateSignal{});
return; return viewModel;
} }
} }
@ -210,8 +294,9 @@ void CoreAppPrivate::showViewModel(const QMetaObject *metaObject, const QVariant
logDebug() << "Successfully presented" << metaObject->className(); logDebug() << "Successfully presented" << metaObject->className();
// if singleton -> store it // if singleton -> store it
if(isSingleton) if(isSingle)
singleInstances.insert(metaObject, vm); singleInstances.insert(metaObject, vm);
return vm;
} catch(QException &e) { } catch(QException &e) {
logCritical() << "Failed to present viewmodel of type" logCritical() << "Failed to present viewmodel of type"
<< metaObject->className() << metaObject->className()
@ -225,25 +310,6 @@ void CoreAppPrivate::showViewModel(const QMetaObject *metaObject, const QVariant
<< metaObject->className() << metaObject->className()
<< "- no presenter was set"; << "- no presenter was set";
} }
}
void CoreAppPrivate::showDialog(const MessageConfig &config, MessageResult *result) return nullptr;
{
if(presenter) {
try {
presenter->showDialog(config, result);
logDebug() << "Successfully presented dialog of type" << config.type();
} catch(QException &e) {
logCritical() << "Failed to show dialog ff type"
<< config.type() << ":" << config.subType()
<< "with error:"
<< e.what();
result->complete(MessageConfig::NoButton);
}
} else {
logCritical() << "Failed to show dialog ff type"
<< config.type() << ":" << config.subType()
<< "- no presenter was set";
result->complete(MessageConfig::NoButton);
}
} }

8
src/mvvmcore/coreapp_p.h

@ -29,6 +29,14 @@ private:
IPresenter *presenter = nullptr; IPresenter *presenter = nullptr;
QHash<const QMetaObject*, QPointer<ViewModel>> singleInstances; QHash<const QMetaObject*, QPointer<ViewModel>> singleInstances;
bool isSingleton(const QMetaObject *metaObject) const;
const QMetaObject * getContainer(const QMetaObject *metaObject) const;
QPointer<ViewModel> showViewModelWithReturn(const QMetaObject *metaObject,
const QVariantHash &params,
QPointer<ViewModel> parent,
quint32 requestCode);
}; };
} }

2
src/mvvmcore/viewmodel.h

@ -67,6 +67,8 @@ private:
//TODO doc //TODO doc
#define QTMVVM_SINGLETON Q_CLASSINFO("qtmvvm_singleton", "true") #define QTMVVM_SINGLETON Q_CLASSINFO("qtmvvm_singleton", "true")
#define QTMVVM_CONTAINER_VM(x) Q_CLASSINFO("qtmvvm_container_viewmodel", #x)
// ------------- Generic Implementation ------------- // ------------- Generic Implementation -------------
template<typename TViewModel> template<typename TViewModel>

20
src/mvvmquick/quickpresenter.cpp

@ -166,21 +166,33 @@ int QuickPresenter::presentMethodIndex(const QMetaObject *presenterMetaObject, Q
{ {
auto index = -1; auto index = -1;
if(viewObject->inherits("QQuickPopup")) { if(viewObject->inherits("QQuickPopup")) {
logDebug() << "Presenting" << viewObject->metaObject()->className() << "as popup";
index = presenterMetaObject->indexOfMethod("presentPopup(QVariant)"); index = presenterMetaObject->indexOfMethod("presentPopup(QVariant)");
if(index != -1) {
logDebug() << "Presenting" << viewObject->metaObject()->className()
<< "as popup with presenter" << presenterMetaObject->className();
}
} if(viewObject->inherits("QQuickItem")) { } if(viewObject->inherits("QQuickItem")) {
if(nameOrClassContains(viewObject, QStringLiteral("Drawer"))) { if(nameOrClassContains(viewObject, QStringLiteral("Drawer"))) {
logDebug() << "Presenting" << viewObject->metaObject()->className() << "as drawer";
index = presenterMetaObject->indexOfMethod("presentDrawerContent(QVariant)"); index = presenterMetaObject->indexOfMethod("presentDrawerContent(QVariant)");
if(index != -1) {
logDebug() << "Presenting" << viewObject->metaObject()->className()
<< "as drawer with presenter" << presenterMetaObject->className();
}
} }
if(index == -1 && nameOrClassContains(viewObject, QStringLiteral("Tab"))) { if(index == -1 && nameOrClassContains(viewObject, QStringLiteral("Tab"))) {
logDebug() << "Presenting" << viewObject->metaObject()->className() << "as tab";
index = presenterMetaObject->indexOfMethod("presentTab(QVariant)"); index = presenterMetaObject->indexOfMethod("presentTab(QVariant)");
if(index != -1) {
logDebug() << "Presenting" << viewObject->metaObject()->className()
<< "as tab with presenter" << presenterMetaObject->className();
}
} }
if(index == -1) { if(index == -1) {
logDebug() << "Presenting" << viewObject->metaObject()->className() << "as item";
index = presenterMetaObject->indexOfMethod("presentItem(QVariant)"); index = presenterMetaObject->indexOfMethod("presentItem(QVariant)");
if(index != -1) {
logDebug() << "Presenting" << viewObject->metaObject()->className()
<< "as item with presenter" << presenterMetaObject->className();
}
} }
} }
return index; return index;

Loading…
Cancel
Save