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>();
break;
case 1:
show<TabViewModel>();
show<TabItemViewModel>({
{QStringLiteral("title"), QStringLiteral("Root Tab")}
});
break;
case 2:
show<QtMvvm::SettingsViewModel>();

2
examples/mvvmcore/SampleCore/samplecoreapp.cpp

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

4
examples/mvvmcore/SampleCore/sampleviewmodel.cpp

@ -68,7 +68,9 @@ void SampleViewModel::setActive(bool active)
void SampleViewModel::showTabs()
{
show<TabViewModel>();
show<TabItemViewModel>({
{QStringLiteral("title"), QStringLiteral("Root Tab")}
});
}
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)
QTMVVM_CONTAINER_VM(TabViewModel)
public:
Q_INVOKABLE explicit TabItemViewModel(QObject *parent = nullptr);
~TabItemViewModel();
@ -39,4 +41,6 @@ private:
QString _title;
};
Q_DECLARE_METATYPE(TabViewModel*)
#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)
{
showViewModelWithReturn(metaObject, params, std::move(parent), requestCode);
}
void CoreAppPrivate::showDialog(const MessageConfig &config, MessageResult *result)
{
if(presenter) {
//first: check for single instance
auto isSingleton = false;
try {
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");
if(sInfoIndex != -1) {
auto sInfo = metaObject->classInfo(sInfoIndex);
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;
}
// next handle the singleton
if(isSingleton) {
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 a singleton
auto isSingle = isSingleton(metaObject);
if(isSingle) {
auto viewModel = singleInstances.value(metaObject);
if(viewModel) {
logDebug() << "Found existing single instance for" << metaObject->className();
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();
// if singleton -> store it
if(isSingleton)
if(isSingle)
singleInstances.insert(metaObject, vm);
return vm;
} catch(QException &e) {
logCritical() << "Failed to present viewmodel of type"
<< metaObject->className()
@ -225,25 +310,6 @@ void CoreAppPrivate::showViewModel(const QMetaObject *metaObject, const QVariant
<< metaObject->className()
<< "- no presenter was set";
}
}
void CoreAppPrivate::showDialog(const MessageConfig &config, MessageResult *result)
{
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);
}
return nullptr;
}

8
src/mvvmcore/coreapp_p.h

@ -29,6 +29,14 @@ private:
IPresenter *presenter = nullptr;
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
#define QTMVVM_SINGLETON Q_CLASSINFO("qtmvvm_singleton", "true")
#define QTMVVM_CONTAINER_VM(x) Q_CLASSINFO("qtmvvm_container_viewmodel", #x)
// ------------- Generic Implementation -------------
template<typename TViewModel>

20
src/mvvmquick/quickpresenter.cpp

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

Loading…
Cancel
Save