Browse Source

wip update imports

pull/2/head
Skycoder42 6 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::DataSyncViewModel "DataSyncViewModel" (uncreatable)
- @ref QtMvvm::NetworkExchangeViewModel "NetworkExchangeViewModel" (uncreatable)
- @ref QtMvvm::DataSyncSettingsViewModel "DataSyncSettingsViewModel" (uncreatable)
- @ref QtMvvm::DataSyncSettingsEntry "DataSyncSettingsEntry" (uncreatable)
- PChangeRemoteViewModel (uncreatable, internal)
- PExportSetupViewModel (uncreatable, internal)
- PIdentityEditViewModel (uncreatable, internal)

17
examples/mvvmquick/SampleQuick/ContainerView.qml

@ -35,30 +35,13 @@ Page {
ViewPlaceholder {
id: viewPlaceholder
viewModelType: containerView.viewModel.vmType
parentViewModel: containerView.viewModel
autoPresent: false
Layout.fillWidth: true
Layout.fillHeight: true
BusyIndicator {
anchors.centerIn: parent
anchors.verticalCenterOffset: -(hookButton.height/2)
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 {

23
src/imports/mvvmquick/plugins.qmltypes

@ -130,30 +130,10 @@ Module {
prototype: "QQuickItem"
exports: ["de.skycoder42.QtMvvm.Quick/ViewPlaceholder 1.1"]
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: "replaceViews"; type: "bool" }
Property { name: "closeViewOnAction"; type: "bool" }
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 {
name: "autoResizeViewChanged"
Parameter { name: "autoResizeView"; type: "bool" }
@ -170,12 +150,11 @@ Module {
name: "loadedViewChanged"
Parameter { name: "loadedView"; type: "QQuickItem"; isPointer: true }
}
Method { name: "presentView" }
Method { name: "discardView" }
Method {
name: "presentItem"
type: "bool"
Parameter { name: "item"; type: "QVariant" }
Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
}
Method { name: "closeAction"; type: "bool" }
}

131
src/imports/mvvmquick/qqmlviewplaceholder.cpp

@ -8,11 +8,7 @@ using namespace QtMvvm;
QQmlViewPlaceholder::QQmlViewPlaceholder(QQuickItem *parent) :
QQuickItem{parent}
{
// auto presenting
connect(this, &QQmlViewPlaceholder::viewModelTypeChanged,
this, &QQmlViewPlaceholder::presentIfReady);
connect(this, &QQmlViewPlaceholder::autoPresentChanged,
this, &QQmlViewPlaceholder::presentIfReady);
setImplicitSize(0, 0); // init to 0
// size changes
connect(this, &QQmlViewPlaceholder::widthChanged,
@ -23,18 +19,12 @@ QQmlViewPlaceholder::QQmlViewPlaceholder(QQuickItem *parent) :
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
if(_loadedView) {
if(_replaceViews) { // quick discard without reenableing all children
disconnectSizeChanges(false);
_loadedView->setVisible(false);
_loadedView->deleteLater();
_loadedView = nullptr;
@ -45,11 +35,12 @@ bool QQmlViewPlaceholder::presentItem(const QVariant &item)
}
// add
_loadedView = quickItem;
quickItem->setParent(this);
quickItem->setParentItem(this);
_loadedView = item;
_loadedView->setParent(this);
_loadedView->setParentItem(this);
connectSizeChanges();
resizeView();
quickItem->setVisible(true);
_loadedView->setVisible(true);
// hide all children
for(auto child : childItems()) {
@ -87,52 +78,11 @@ bool QQmlViewPlaceholder::closeAction()
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
{
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()
{
// hide view
@ -145,57 +95,46 @@ void QQmlViewPlaceholder::discardView()
}
// now delete it
disconnectSizeChanges(true);
_loadedView->deleteLater();
_loadedView = nullptr;
emit loadedViewChanged(nullptr);
}
void QQmlViewPlaceholder::parentItemVmChanged(ViewModel *viewModel)
void QQmlViewPlaceholder::resizeView()
{
// set vm without clearing the connection
_clearParentVmCon = false;
setParentViewModel(viewModel);
_clearParentVmCon = true;
if(_loadedView && _autoResizeView) {
_loadedView->setWidth(width());
_loadedView->setHeight(height());
}
}
void QQmlViewPlaceholder::presentIfReady()
void QQmlViewPlaceholder::updateImpHeight()
{
if(_isReady &&
_autoPresent &&
!_loadedView &&
_parentViewModel &&
!_viewModelType.isEmpty())
presentView();
setImplicitHeight(_loadedView->implicitHeight());
}
void QQmlViewPlaceholder::resizeView()
void QQmlViewPlaceholder::updateImpWidth()
{
if(_loadedView && _autoResizeView) {
_loadedView->setWidth(width());
_loadedView->setHeight(height());
}
setImplicitWidth(_loadedView->implicitWidth());
}
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();
if(!pItem)
return;
QQmlProperty vmProp{pItem, QStringLiteral("viewModel")};
if(!vmProp.isValid())
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));
disconnect(_loadedView, &QQuickItem::implicitWidthChanged,
this, &QQmlViewPlaceholder::updateImpWidth);
disconnect(_loadedView, &QQuickItem::implicitHeightChanged,
this, &QQmlViewPlaceholder::updateImpHeight);
if(resetSize)
setImplicitSize(0, 0);
}

170
src/imports/mvvmquick/qqmlviewplaceholder.h

@ -5,58 +5,184 @@
#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 {
class QQmlViewPlaceholder : public QQuickItem
#endif
{
Q_OBJECT
Q_PROPERTY(QString viewModelType MEMBER _viewModelType NOTIFY viewModelTypeChanged)
Q_PROPERTY(QVariantHash showParams MEMBER _showParams NOTIFY showParamsChanged)
Q_PROPERTY(QtMvvm::ViewModel* parentViewModel MEMBER _parentViewModel WRITE setParentViewModel NOTIFY parentViewModelChanged)
Q_PROPERTY(bool autoPresent MEMBER _autoPresent NOTIFY autoPresentChanged)
/*!
* @brief Specify whether to automatically resize the placeholders content view
*
* @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)
/*!
* @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)
/*!
* @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)
/*!
* @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)
public:
//! @private
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();
void setParentViewModel(ViewModel *parentViewModel);
//! @private
QQuickItem* loadedView() const;
void componentComplete() override;
public Q_SLOTS:
void presentView();
//! Closes the currenty contained view by destoying it
void discardView();
Q_SIGNALS:
void viewModelTypeChanged(const QString &viewModelType);
void showParamsChanged(const QVariantHash &showParams);
void parentViewModelChanged(QtMvvm::ViewModel* parentViewModel);
void autoPresentChanged(bool autoPresent);
//! @notifyAcFn{ViewPlaceholder::autoResizeView}
void autoResizeViewChanged(bool autoResizeView);
//! @notifyAcFn{ViewPlaceholder::replaceViews}
void replaceViewsChanged(bool replaceViews);
//! @notifyAcFn{ViewPlaceholder::closeViewOnAction}
void closeViewOnActionChanged(bool closeViewOnAction);
//! @notifyAcFn{ViewPlaceholder::loadedView}
void loadedViewChanged(QQuickItem* loadedView);
private Q_SLOTS:
void parentItemVmChanged(QtMvvm::ViewModel *viewModel);
void presentIfReady();
void resizeView();
void updateImpHeight();
void updateImpWidth();
private:
QString _viewModelType;
QVariantHash _showParams;
ViewModel *_parentViewModel = nullptr;
bool _autoPresent = true;
bool _autoResizeView = true;
bool _replaceViews = false;
bool _closeViewOnAction = false;
@ -64,12 +190,10 @@ private:
QPointer<QQuickItem> _loadedView = nullptr;
bool _isReady = false;
bool _clearParentVmCon = true;
QMetaObject::Connection _parentVmCon;
void getParentViewModel();
void connectSizeChanges();
void disconnectSizeChanges();
void disconnectSizeChanges(bool resetSize);
};
}

Loading…
Cancel
Save