Browse Source

wip update imports

pull/2/head
Skycoder42 7 years ago
parent
commit
93a620b1fe
No known key found for this signature in database GPG Key ID: 8E01AD9EF0578D2B
  1. 2
      doc/qtmvvm.dox
  2. 17
      examples/mvvmquick/SampleQuick/ContainerView.qml
  3. 23
      src/imports/mvvmquick/plugins.qmltypes
  4. 131
      src/imports/mvvmquick/qqmlviewplaceholder.cpp
  5. 170
      src/imports/mvvmquick/qqmlviewplaceholder.h

2
doc/qtmvvm.dox

@ -103,6 +103,8 @@ The following list shows which classes belong to which Qt module, in alphabetica
- @ref QtMvvm::ExchangeDevicesModel "ExchangeDevicesModel" - @ref QtMvvm::ExchangeDevicesModel "ExchangeDevicesModel"
- @ref QtMvvm::DataSyncViewModel "DataSyncViewModel" (uncreatable) - @ref QtMvvm::DataSyncViewModel "DataSyncViewModel" (uncreatable)
- @ref QtMvvm::NetworkExchangeViewModel "NetworkExchangeViewModel" (uncreatable) - @ref QtMvvm::NetworkExchangeViewModel "NetworkExchangeViewModel" (uncreatable)
- @ref QtMvvm::DataSyncSettingsViewModel "DataSyncSettingsViewModel" (uncreatable)
- @ref QtMvvm::DataSyncSettingsEntry "DataSyncSettingsEntry" (uncreatable)
- PChangeRemoteViewModel (uncreatable, internal) - PChangeRemoteViewModel (uncreatable, internal)
- PExportSetupViewModel (uncreatable, internal) - PExportSetupViewModel (uncreatable, internal)
- PIdentityEditViewModel (uncreatable, internal) - PIdentityEditViewModel (uncreatable, internal)

17
examples/mvvmquick/SampleQuick/ContainerView.qml

@ -35,30 +35,13 @@ Page {
ViewPlaceholder { ViewPlaceholder {
id: viewPlaceholder id: viewPlaceholder
viewModelType: containerView.viewModel.vmType
parentViewModel: containerView.viewModel
autoPresent: false
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
BusyIndicator { BusyIndicator {
anchors.centerIn: parent anchors.centerIn: parent
anchors.verticalCenterOffset: -(hookButton.height/2)
running: !viewPlaceholder.loadedView running: !viewPlaceholder.loadedView
} }
Button {
id: hookButton
Layout.fillWidth: true
text: qsTr("Load from QML")
onClicked: viewPlaceholder.presentView();
enabled: !viewPlaceholder.loadedView
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
}
} }
Button { Button {

23
src/imports/mvvmquick/plugins.qmltypes

@ -130,30 +130,10 @@ Module {
prototype: "QQuickItem" prototype: "QQuickItem"
exports: ["de.skycoder42.QtMvvm.Quick/ViewPlaceholder 1.1"] exports: ["de.skycoder42.QtMvvm.Quick/ViewPlaceholder 1.1"]
exportMetaObjectRevisions: [0] exportMetaObjectRevisions: [0]
Property { name: "viewModelType"; type: "string" }
Property { name: "showParams"; type: "QVariantHash" }
Property { name: "parentViewModel"; type: "QtMvvm::ViewModel"; isPointer: true }
Property { name: "autoPresent"; type: "bool" }
Property { name: "autoResizeView"; type: "bool" } Property { name: "autoResizeView"; type: "bool" }
Property { name: "replaceViews"; type: "bool" } Property { name: "replaceViews"; type: "bool" }
Property { name: "closeViewOnAction"; type: "bool" } Property { name: "closeViewOnAction"; type: "bool" }
Property { name: "loadedView"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "loadedView"; type: "QQuickItem"; isReadonly: true; isPointer: true }
Signal {
name: "viewModelTypeChanged"
Parameter { name: "viewModelType"; type: "string" }
}
Signal {
name: "showParamsChanged"
Parameter { name: "showParams"; type: "QVariantHash" }
}
Signal {
name: "parentViewModelChanged"
Parameter { name: "parentViewModel"; type: "QtMvvm::ViewModel"; isPointer: true }
}
Signal {
name: "autoPresentChanged"
Parameter { name: "autoPresent"; type: "bool" }
}
Signal { Signal {
name: "autoResizeViewChanged" name: "autoResizeViewChanged"
Parameter { name: "autoResizeView"; type: "bool" } Parameter { name: "autoResizeView"; type: "bool" }
@ -170,12 +150,11 @@ Module {
name: "loadedViewChanged" name: "loadedViewChanged"
Parameter { name: "loadedView"; type: "QQuickItem"; isPointer: true } Parameter { name: "loadedView"; type: "QQuickItem"; isPointer: true }
} }
Method { name: "presentView" }
Method { name: "discardView" } Method { name: "discardView" }
Method { Method {
name: "presentItem" name: "presentItem"
type: "bool" type: "bool"
Parameter { name: "item"; type: "QVariant" } Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
} }
Method { name: "closeAction"; type: "bool" } Method { name: "closeAction"; type: "bool" }
} }

131
src/imports/mvvmquick/qqmlviewplaceholder.cpp

@ -8,11 +8,7 @@ using namespace QtMvvm;
QQmlViewPlaceholder::QQmlViewPlaceholder(QQuickItem *parent) : QQmlViewPlaceholder::QQmlViewPlaceholder(QQuickItem *parent) :
QQuickItem{parent} QQuickItem{parent}
{ {
// auto presenting setImplicitSize(0, 0); // init to 0
connect(this, &QQmlViewPlaceholder::viewModelTypeChanged,
this, &QQmlViewPlaceholder::presentIfReady);
connect(this, &QQmlViewPlaceholder::autoPresentChanged,
this, &QQmlViewPlaceholder::presentIfReady);
// size changes // size changes
connect(this, &QQmlViewPlaceholder::widthChanged, connect(this, &QQmlViewPlaceholder::widthChanged,
@ -23,18 +19,12 @@ QQmlViewPlaceholder::QQmlViewPlaceholder(QQuickItem *parent) :
this, &QQmlViewPlaceholder::resizeView); this, &QQmlViewPlaceholder::resizeView);
} }
bool QQmlViewPlaceholder::presentItem(const QVariant &item) bool QQmlViewPlaceholder::presentItem(QQuickItem *item)
{ {
// check if the parameter is valid
auto quickItem = item.value<QQuickItem*>();
if(!quickItem) {
qmlWarning(this) << "presentItem called with invalid item of type: " << item.typeName();
return false;
}
// handle already existing view case // handle already existing view case
if(_loadedView) { if(_loadedView) {
if(_replaceViews) { // quick discard without reenableing all children if(_replaceViews) { // quick discard without reenableing all children
disconnectSizeChanges(false);
_loadedView->setVisible(false); _loadedView->setVisible(false);
_loadedView->deleteLater(); _loadedView->deleteLater();
_loadedView = nullptr; _loadedView = nullptr;
@ -45,11 +35,12 @@ bool QQmlViewPlaceholder::presentItem(const QVariant &item)
} }
// add // add
_loadedView = quickItem; _loadedView = item;
quickItem->setParent(this); _loadedView->setParent(this);
quickItem->setParentItem(this); _loadedView->setParentItem(this);
connectSizeChanges();
resizeView(); resizeView();
quickItem->setVisible(true); _loadedView->setVisible(true);
// hide all children // hide all children
for(auto child : childItems()) { for(auto child : childItems()) {
@ -87,52 +78,11 @@ bool QQmlViewPlaceholder::closeAction()
return false; return false;
} }
void QQmlViewPlaceholder::setParentViewModel(ViewModel *parentViewModel)
{
// first: clear the auto-connected viewmodel, if required
if(_clearParentVmCon && _parentVmCon)
disconnect(_parentVmCon);
// then: set property as usual
if(_parentViewModel == parentViewModel)
return;
_parentViewModel = parentViewModel;
emit parentViewModelChanged(_parentViewModel);
// check the vm parent for a presenter method
auto view = qobject_cast<QQuickItem*>(_parentViewModel->parent());
if(view) {
if(view->metaObject()->indexOfMethod("presentItem(QVariant)") == -1)
qmlWarning(this) << R"(Parent item of "parentViewModel" does not have a "presentItem" method. Check the ViewPlaceholder documentation!)";
} else
qmlWarning(this) << R"(Parent item of "parentViewModel" is not an Item)";
presentIfReady();
}
QQuickItem *QQmlViewPlaceholder::loadedView() const QQuickItem *QQmlViewPlaceholder::loadedView() const
{ {
return _loadedView; return _loadedView;
} }
void QQmlViewPlaceholder::componentComplete()
{
// auto-set the vm if not already set
if(!_parentViewModel)
getParentViewModel();
// last step: call base implementation, then present
QQuickItem::componentComplete();
_isReady = true;
presentIfReady();
}
void QQmlViewPlaceholder::presentView()
{
CoreApp::show(qUtf8Printable(_viewModelType), _showParams, _parentViewModel);
}
void QQmlViewPlaceholder::discardView() void QQmlViewPlaceholder::discardView()
{ {
// hide view // hide view
@ -145,57 +95,46 @@ void QQmlViewPlaceholder::discardView()
} }
// now delete it // now delete it
disconnectSizeChanges(true);
_loadedView->deleteLater(); _loadedView->deleteLater();
_loadedView = nullptr; _loadedView = nullptr;
emit loadedViewChanged(nullptr); emit loadedViewChanged(nullptr);
} }
void QQmlViewPlaceholder::parentItemVmChanged(ViewModel *viewModel) void QQmlViewPlaceholder::resizeView()
{ {
// set vm without clearing the connection if(_loadedView && _autoResizeView) {
_clearParentVmCon = false; _loadedView->setWidth(width());
setParentViewModel(viewModel); _loadedView->setHeight(height());
_clearParentVmCon = true; }
} }
void QQmlViewPlaceholder::presentIfReady() void QQmlViewPlaceholder::updateImpHeight()
{ {
if(_isReady && setImplicitHeight(_loadedView->implicitHeight());
_autoPresent &&
!_loadedView &&
_parentViewModel &&
!_viewModelType.isEmpty())
presentView();
} }
void QQmlViewPlaceholder::resizeView() void QQmlViewPlaceholder::updateImpWidth()
{ {
if(_loadedView && _autoResizeView) { setImplicitWidth(_loadedView->implicitWidth());
_loadedView->setWidth(width()); }
_loadedView->setHeight(height());
} void QQmlViewPlaceholder::connectSizeChanges()
{
connect(_loadedView, &QQuickItem::implicitWidthChanged,
this, &QQmlViewPlaceholder::updateImpWidth);
connect(_loadedView, &QQuickItem::implicitHeightChanged,
this, &QQmlViewPlaceholder::updateImpHeight);
setImplicitSize(_loadedView->implicitWidth(),
_loadedView->implicitHeight());
} }
void QQmlViewPlaceholder::getParentViewModel() void QQmlViewPlaceholder::disconnectSizeChanges(bool resetSize)
{ {
auto pItem = parentItem(); disconnect(_loadedView, &QQuickItem::implicitWidthChanged,
if(!pItem) this, &QQmlViewPlaceholder::updateImpWidth);
return; disconnect(_loadedView, &QQuickItem::implicitHeightChanged,
this, &QQmlViewPlaceholder::updateImpHeight);
QQmlProperty vmProp{pItem, QStringLiteral("viewModel")}; if(resetSize)
if(!vmProp.isValid()) setImplicitSize(0, 0);
return;
// set the vm from the property
auto vm = vmProp.read().value<ViewModel*>();
if(vm)
setParentViewModel(vm); // no warning here - might be ok for lazy presented vms
// connect to further changes, via helper slot
auto cSlotIndex = metaObject()->indexOfSlot("parentItemVmChanged(QtMvvm::ViewModel*)");
Q_ASSERT(cSlotIndex != -1);
if(_parentVmCon)
disconnect(_parentVmCon);
_parentVmCon = connect(pItem, vmProp.property().notifySignal(),
this, metaObject()->method(cSlotIndex));
} }

170
src/imports/mvvmquick/qqmlviewplaceholder.h

@ -5,58 +5,184 @@
#include <QtMvvmCore/ViewModel> #include <QtMvvmCore/ViewModel>
#ifdef DOXYGEN_RUN
namespace de::skycoder42::QtMvvm::Quick {
/*!
* @brief A placeholder item to show a view within another view
*
* @extends QtQuick.Item
* @since 1.1
*
* The following snippet shows how use the placeholder
* @code{.qml}
Page {
id: view
property MyViewModel viewModel
function presentItem(item) {
return viewPlaceholder.presentItem(item);
}
function closeAction() {
return viewPlaceholder.closeAction();
}
PresenterProgress {}
ColumnLayout {
anchors.fill: parent
ViewPlaceholder {
id: viewPlaceholder
Layout.fillWidth: true
Layout.fillHeight: true
BusyIndicator {
anchors.centerIn: parent
running: !viewPlaceholder.loadedView
}
}
Button {
Layout.fillWidth: true
text: viewPlaceholder.loadedView ? qsTr("Discard child") : qsTr("Show Child")
onClicked: viewPlaceholder.loadedView ? viewPlaceholder.discardView() : viewModel.loadChild();
}
}
}
* @endcode
*/
class ViewPlaceholder
#else
namespace QtMvvm { namespace QtMvvm {
class QQmlViewPlaceholder : public QQuickItem class QQmlViewPlaceholder : public QQuickItem
#endif
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString viewModelType MEMBER _viewModelType NOTIFY viewModelTypeChanged) /*!
Q_PROPERTY(QVariantHash showParams MEMBER _showParams NOTIFY showParamsChanged) * @brief Specify whether to automatically resize the placeholders content view
Q_PROPERTY(QtMvvm::ViewModel* parentViewModel MEMBER _parentViewModel WRITE setParentViewModel NOTIFY parentViewModelChanged) *
Q_PROPERTY(bool autoPresent MEMBER _autoPresent NOTIFY autoPresentChanged) * @default{`true`}
*
* When enabled, the view that is loaded into the placeholder is always automatically
* resized to exactly fit into the placeholder. If not, the view must resize itself.
*
* @accessors{
* @memberAc{autoResizeView}
* @notifyAc{autoResizeViewChanged()}
* }
*
* @sa width, height, implicitWidth, implicitHeight
*/
Q_PROPERTY(bool autoResizeView MEMBER _autoResizeView NOTIFY autoResizeViewChanged) Q_PROPERTY(bool autoResizeView MEMBER _autoResizeView NOTIFY autoResizeViewChanged)
/*!
* @brief Specify what happens when showing a new viewmodel while one already exists
*
* @default{`false`}
*
* When set to false, trying to present a new viewmodel on this placeholder will fail. If
* true, the old one is destroyed and replaced by the new one instead.
*
* @accessors{
* @memberAc{replaceViews}
* @notifyAc{replaceViewsChanged()}
* }
*/
Q_PROPERTY(bool replaceViews MEMBER _replaceViews NOTIFY replaceViewsChanged) Q_PROPERTY(bool replaceViews MEMBER _replaceViews NOTIFY replaceViewsChanged)
/*!
* @brief Specify whether discarding the contained view is a close action
*
* @default{`false`}
*
* When the placeholder receives a close action and the contained view does not handle it,
* either the placeholder only closes the contained view and thus accepts the action (that
* happens if true), or does not accept it keep the view so that the next higher instance
* can handle the request (that happens if false).
*
* @accessors{
* @memberAc{closeViewOnAction}
* @notifyAc{closeViewOnActionChanged()}
* }
*
* @sa ViewPlaceholder::closeAction
*/
Q_PROPERTY(bool closeViewOnAction MEMBER _closeViewOnAction NOTIFY closeViewOnActionChanged) Q_PROPERTY(bool closeViewOnAction MEMBER _closeViewOnAction NOTIFY closeViewOnActionChanged)
/*!
* @brief Returns the currently loaded view
*
* @default{`nullptr`}
*
* If a view is contained in the placeholder, that one is returned. Otherwise nullptr is
* returned by the property
*
* @accessors{
* @memberAc{closeViewOnAction}
* @notifyAc{closeViewOnActionChanged()}
* @readonlyAc
* }
*/
Q_PROPERTY(QQuickItem* loadedView READ loadedView NOTIFY loadedViewChanged) Q_PROPERTY(QQuickItem* loadedView READ loadedView NOTIFY loadedViewChanged)
public: public:
//! @private
explicit QQmlViewPlaceholder(QQuickItem *parent = nullptr); explicit QQmlViewPlaceholder(QQuickItem *parent = nullptr);
Q_INVOKABLE bool presentItem(const QVariant &item); /*!
* @brief The presenter method to be called from the parent view
*
* @param item The item to be presented in this placeholder
* @returns true if the item was presented as the placeholders content, false if not
*
* Implement a method with the same signature in the view that holds the placeholder and
* call this method from your implementation. This way you can automatically pass views
* to be presented to the placeholder.
*
* @sa ViewPlaceholder
*/
Q_INVOKABLE bool presentItem(QQuickItem *item);
/*!
* @brief A close action that propagates to the contained item
*
* @returns true if the contained item accepted the action or was discarded, false
* otherwise
*
* Implement a method with the same signature in the view that holds the placeholder and
* call this method from your implementation. This way close actions are properly handeled
* automatically.
*
* @sa ViewPlaceholder, ViewPlaceholder::closeViewOnAction
*/
Q_INVOKABLE bool closeAction(); Q_INVOKABLE bool closeAction();
void setParentViewModel(ViewModel *parentViewModel); //! @private
QQuickItem* loadedView() const; QQuickItem* loadedView() const;
void componentComplete() override;
public Q_SLOTS: public Q_SLOTS:
void presentView(); //! Closes the currenty contained view by destoying it
void discardView(); void discardView();
Q_SIGNALS: Q_SIGNALS:
void viewModelTypeChanged(const QString &viewModelType); //! @notifyAcFn{ViewPlaceholder::autoResizeView}
void showParamsChanged(const QVariantHash &showParams);
void parentViewModelChanged(QtMvvm::ViewModel* parentViewModel);
void autoPresentChanged(bool autoPresent);
void autoResizeViewChanged(bool autoResizeView); void autoResizeViewChanged(bool autoResizeView);
//! @notifyAcFn{ViewPlaceholder::replaceViews}
void replaceViewsChanged(bool replaceViews); void replaceViewsChanged(bool replaceViews);
//! @notifyAcFn{ViewPlaceholder::closeViewOnAction}
void closeViewOnActionChanged(bool closeViewOnAction); void closeViewOnActionChanged(bool closeViewOnAction);
//! @notifyAcFn{ViewPlaceholder::loadedView}
void loadedViewChanged(QQuickItem* loadedView); void loadedViewChanged(QQuickItem* loadedView);
private Q_SLOTS: private Q_SLOTS:
void parentItemVmChanged(QtMvvm::ViewModel *viewModel);
void presentIfReady();
void resizeView(); void resizeView();
void updateImpHeight();
void updateImpWidth();
private: private:
QString _viewModelType;
QVariantHash _showParams;
ViewModel *_parentViewModel = nullptr;
bool _autoPresent = true;
bool _autoResizeView = true; bool _autoResizeView = true;
bool _replaceViews = false; bool _replaceViews = false;
bool _closeViewOnAction = false; bool _closeViewOnAction = false;
@ -64,12 +190,10 @@ private:
QPointer<QQuickItem> _loadedView = nullptr; QPointer<QQuickItem> _loadedView = nullptr;
bool _isReady = false; bool _isReady = false;
bool _clearParentVmCon = true;
QMetaObject::Connection _parentVmCon; QMetaObject::Connection _parentVmCon;
void getParentViewModel();
void connectSizeChanges(); void connectSizeChanges();
void disconnectSizeChanges(); void disconnectSizeChanges(bool resetSize);
}; };
} }

Loading…
Cancel
Save