20 changed files with 804 additions and 38 deletions
@ -0,0 +1,237 @@ |
|||||
|
import QtQuick 2.10 |
||||
|
import QtQuick.Controls 2.3 |
||||
|
import de.skycoder42.QtMvvm.Core 1.1 |
||||
|
import de.skycoder42.QtMvvm.Quick 1.1 |
||||
|
|
||||
|
/*! @brief A presentation helper that can present generic mvvm dialogs |
||||
|
* |
||||
|
* @extends QtQml.QtObject |
||||
|
* |
||||
|
* @details You can use this class as presenter for dialogs in case you create your own root |
||||
|
* presenter instead of using the QtMvvmApp. This partial presenter can handle simple dialogs |
||||
|
* (the ones shown via QtMvvm::CoreApp::showDialog). Use it as follows: |
||||
|
* |
||||
|
* @code{.qml} |
||||
|
* MyPresenter { |
||||
|
* id: _root |
||||
|
* |
||||
|
* DialogPresenter { |
||||
|
* id: _rootDialogs |
||||
|
* rootItem: _root.contentItem |
||||
|
* } |
||||
|
* |
||||
|
* function showDialog(config, result) { |
||||
|
* return _rootDialogs.showDialog(config, result); |
||||
|
* } |
||||
|
* |
||||
|
* function closeAction() { |
||||
|
* var closed = false; |
||||
|
* // ... |
||||
|
* if(!closed) |
||||
|
* closed = _rootDialogs.closeAction(); |
||||
|
* // ... |
||||
|
* return closed; |
||||
|
* } |
||||
|
* } |
||||
|
* @endcode |
||||
|
* |
||||
|
* @sa QtMvvmApp |
||||
|
*/ |
||||
|
QtObject { |
||||
|
id: _dialogPresenter |
||||
|
|
||||
|
/*! @brief The root item to present dialogs to |
||||
|
* |
||||
|
* @default{`null`} |
||||
|
* |
||||
|
* This propety **must** be set in order for the presenter to work. It will create new |
||||
|
* dialogs with that item as parent, which decides in which relative are they are |
||||
|
* displayed. Unless you want to explicitly reposition dialogs, this should always be the |
||||
|
* root item of the root component of your application. |
||||
|
* |
||||
|
* @accessors{ |
||||
|
* @memberAc{rootItem} |
||||
|
* @notifyAc{rootItemChanged()} |
||||
|
* } |
||||
|
*/ |
||||
|
property Item rootItem: null |
||||
|
|
||||
|
//TODO document |
||||
|
readonly property bool empty: _popups.length == 0 |
||||
|
|
||||
|
/*! @brief The primary presenting method to present a dialog |
||||
|
* |
||||
|
* @param type:MessageConfig config The message configuration to create a dialog of |
||||
|
* @param type:MessageResult result The result to report the dialog result to |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Use this method in your main presenter to present dialogs via this sub presenter. |
||||
|
* |
||||
|
* @sa QtMvvm::MessageConfig, QtMvvm::MessageResult, QtMvvmApp::showDialog |
||||
|
*/ |
||||
|
function showDialog(config, result) { |
||||
|
if(config.type == "msgbox") |
||||
|
return createMsgBox(config, result) |
||||
|
else if(config.type == "input") |
||||
|
return createInput(config, result) |
||||
|
else if(config.type == "file") |
||||
|
return createFile(config, result) |
||||
|
else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*! @brief Can be called to try to close open dialogs |
||||
|
* |
||||
|
* @return type:bool `true` if a dialog was closed, `false` if not |
||||
|
* |
||||
|
* Use this method in your main presenter react on a close event. It will close the |
||||
|
* latest top level dialog, if one is present. |
||||
|
* |
||||
|
* @sa QtMvvmApp::closeAction |
||||
|
*/ |
||||
|
function closeAction() { |
||||
|
if(_popups.length > 0) { |
||||
|
_popups[_popups.length - 1].reject(); |
||||
|
return true; |
||||
|
} else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
//! Internal property |
||||
|
property var _popups: [] |
||||
|
//! Internal property |
||||
|
property Component _msgBoxComponent: MsgBox { |
||||
|
id: __msgBox |
||||
|
|
||||
|
onClosed: { |
||||
|
var index = _popups.indexOf(__msgBox); |
||||
|
if(index > -1) { |
||||
|
__msgBox.destroy(); |
||||
|
_dialogPresenter._popups.splice(index, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Component.onCompleted: { |
||||
|
_popups.push(__msgBox) |
||||
|
__msgBox.open() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//! Internal property |
||||
|
property Component _inputComponent: InputDialog { |
||||
|
id: __input |
||||
|
|
||||
|
onClosed: { |
||||
|
var index = _popups.indexOf(__input); |
||||
|
if(index > -1) { |
||||
|
__input.destroy(); |
||||
|
_dialogPresenter._popups.splice(index, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Component.onCompleted: { |
||||
|
_popups.push(__input) |
||||
|
__input.open() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//! Internal property |
||||
|
property Component _fileComponent: FileDialog { |
||||
|
id: __file |
||||
|
|
||||
|
onClosed: { |
||||
|
var index = _popups.indexOf(__file); |
||||
|
if(index > -1) { |
||||
|
__file.destroy(); |
||||
|
_dialogPresenter._popups.splice(index, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Component.onCompleted: { |
||||
|
_popups.push(__file) |
||||
|
__file.open() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//! Internal property |
||||
|
property Component _folderComponent: FolderDialog { |
||||
|
id: __folder |
||||
|
|
||||
|
onClosed: { |
||||
|
var index = _popups.indexOf(__folder); |
||||
|
if(index > -1) { |
||||
|
__folder.destroy(); |
||||
|
_dialogPresenter._popups.splice(index, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Component.onCompleted: { |
||||
|
_popups.push(__folder) |
||||
|
__folder.open() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*! @brief Method present a dialog of the QtMvvm::MessageConfig::TypeMessageBox |
||||
|
* |
||||
|
* @param type:MessageConfig config The message configuration to create a dialog of |
||||
|
* @param type:MessageResult result The result to report the dialog result to |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Used by the showDialog() method to show a dialog of the message box type. You can use |
||||
|
* it yourself if you want to extend the presenter and still keep the default dialogs it |
||||
|
* supports. |
||||
|
* |
||||
|
* @sa DialogPresenter::showDialog |
||||
|
*/ |
||||
|
function createMsgBox(config, result) { |
||||
|
var props = config.viewProperties; |
||||
|
props["msgConfig"] = config; |
||||
|
props["msgResult"] = result; |
||||
|
var incubator = _msgBoxComponent.incubateObject(rootItem, props, Qt.Synchronous); |
||||
|
return incubator.status !== Component.Error; |
||||
|
} |
||||
|
|
||||
|
/*! @brief Method present a dialog of the QtMvvm::MessageConfig::TypeInputDialog |
||||
|
* |
||||
|
* @param type:MessageConfig config The message configuration to create a dialog of |
||||
|
* @param type:MessageResult result The result to report the dialog result to |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Used by the showDialog() method to show a dialog of the input dialog type. You can use |
||||
|
* it yourself if you want to extend the presenter and still keep the default dialogs it |
||||
|
* supports. |
||||
|
* |
||||
|
* @sa DialogPresenter::showDialog |
||||
|
*/ |
||||
|
function createInput(config, result) { |
||||
|
var props = config.viewProperties; |
||||
|
props["msgConfig"] = config; |
||||
|
props["msgResult"] = result; |
||||
|
var incubator = _inputComponent.incubateObject(rootItem, props, Qt.Synchronous); |
||||
|
return incubator.status !== Component.Error; |
||||
|
} |
||||
|
|
||||
|
/*! @brief Method present a dialog of the QtMvvm::MessageConfig::TypeFileDialog |
||||
|
* |
||||
|
* @param type:MessageConfig config The message configuration to create a dialog of |
||||
|
* @param type:MessageResult result The result to report the dialog result to |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Used by the showDialog() method to show a dialog of the file dialog type. You can use |
||||
|
* it yourself if you want to extend the presenter and still keep the default dialogs it |
||||
|
* supports. |
||||
|
* |
||||
|
* @sa DialogPresenter::showDialog |
||||
|
*/ |
||||
|
function createFile(config, result) { |
||||
|
var props = config.viewProperties; |
||||
|
props["msgConfig"] = config; |
||||
|
props["msgResult"] = result; |
||||
|
var incubator = null; |
||||
|
if(config.subType == "folder") |
||||
|
incubator = _folderComponent.incubateObject(rootItem, props, Qt.Synchronous); |
||||
|
else |
||||
|
incubator = _fileComponent.incubateObject(rootItem, props, Qt.Synchronous); |
||||
|
return incubator.status !== Component.Error; |
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
import QtQuick 2.10 |
||||
|
import QtQuick.Controls 2.3 |
||||
|
|
||||
|
/*! @brief A presentation helper that can present mvvm views that extend the |
||||
|
* @ref QtQuick.Controls.Popup "Popup" type |
||||
|
* |
||||
|
* @extends QtQml.QtObject |
||||
|
* |
||||
|
* @details You can use this class as presenter for popup views in case you create your own |
||||
|
* root presenter instead of using the QtMvvmApp. This partial presenter can handle any view |
||||
|
* that extends the popup type. Use it as follows: |
||||
|
* |
||||
|
* @code{.qml} |
||||
|
* MyPresenter { |
||||
|
* id: _root |
||||
|
* |
||||
|
* PopupPresenter { |
||||
|
* id: _rootPopup |
||||
|
* rootItem: _root.contentItem |
||||
|
* } |
||||
|
* |
||||
|
* function presentPopup(popup) { |
||||
|
* return _rootPopup.presentPopup(popup); |
||||
|
* } |
||||
|
* |
||||
|
* function closeAction() { |
||||
|
* var closed = false; |
||||
|
* // ... |
||||
|
* if(!closed) |
||||
|
* closed = _rootPopup.closeAction(); |
||||
|
* // ... |
||||
|
* return closed; |
||||
|
* } |
||||
|
* } |
||||
|
* @endcode |
||||
|
* |
||||
|
* @sa QtMvvmApp |
||||
|
*/ |
||||
|
QtObject { |
||||
|
id: _popPresenter |
||||
|
|
||||
|
/*! @brief The root item to present popup views to |
||||
|
* |
||||
|
* @default{`null`} |
||||
|
* |
||||
|
* This propety **must** be set in order for the presenter to work. It will create new |
||||
|
* popups with that item as parent, which decides in which relative are they are |
||||
|
* displayed. Unless you want to explicitly reposition popups, this should always be the |
||||
|
* root item of the root component of your application. |
||||
|
* |
||||
|
* @accessors{ |
||||
|
* @memberAc{rootItem} |
||||
|
* @notifyAc{rootItemChanged()} |
||||
|
* } |
||||
|
*/ |
||||
|
property Item rootItem: null |
||||
|
|
||||
|
//TODO document |
||||
|
readonly property bool empty: _popups.length == 0 |
||||
|
|
||||
|
//! Internal property |
||||
|
property var _popups: [] |
||||
|
|
||||
|
/*! @brief The primary presenting method to present a popup view |
||||
|
* |
||||
|
* @param type:Popup popup The popup to be presented |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Use this method in your main presenter to present popups via this sub presenter. |
||||
|
* |
||||
|
* @sa QtMvvmApp::presentPopup, @ref QtQuick.Controls.Popup "Popup" |
||||
|
*/ |
||||
|
function presentPopup(popup) { |
||||
|
popup.parent = rootItem; |
||||
|
popup.closed.connect(function() { |
||||
|
var index = _popups.indexOf(popup); |
||||
|
if(index > -1) { |
||||
|
popup.destroy(); |
||||
|
_popups.splice(index, 1); |
||||
|
} |
||||
|
}); |
||||
|
_popups.push(popup); |
||||
|
popup.open(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*! @brief Can be called to try to close open popups |
||||
|
* |
||||
|
* @return type:bool `true` if a popup was closed, `false` if not |
||||
|
* |
||||
|
* Use this method in your main presenter react on a close event. It will close the |
||||
|
* latest top level popup, if one is present. |
||||
|
* |
||||
|
* @sa QtMvvmApp::closeAction |
||||
|
*/ |
||||
|
function closeAction() { |
||||
|
if(_popups.length > 0) { |
||||
|
_popups[_popups.length - 1].close(); |
||||
|
return true; |
||||
|
} else |
||||
|
return false; |
||||
|
} |
||||
|
} |
@ -0,0 +1,240 @@ |
|||||
|
import QtQuick 2.10 |
||||
|
import QtQuick.Controls 2.3 |
||||
|
|
||||
|
/*! @brief A presentation helper that can present standard mvvm views |
||||
|
* |
||||
|
* @extends QtQuick.Controls.StackView |
||||
|
* |
||||
|
* @details You can use this class as presenter for normale views in case you create your own |
||||
|
* root presenter instead of using the QtMvvmApp. This partial presenter can handle any view |
||||
|
* that extends the @ref QtQuick.Item "Item" type. Use it as follows: |
||||
|
* |
||||
|
* @code{.qml} |
||||
|
* MyPresenter { |
||||
|
* id: _root |
||||
|
* |
||||
|
* PresentingStackView { |
||||
|
* id: _rootStack |
||||
|
* anchors.fill: parent |
||||
|
* } |
||||
|
* |
||||
|
* function presentItem(item) { |
||||
|
* return _rootStack.presentItem(item); |
||||
|
* } |
||||
|
* |
||||
|
* function closeAction() { |
||||
|
* var closed = false; |
||||
|
* // ... |
||||
|
* if(!closed) |
||||
|
* closed = _rootStack.closeAction(); |
||||
|
* // ... |
||||
|
* return closed; |
||||
|
* } |
||||
|
* } |
||||
|
* @endcode |
||||
|
* |
||||
|
* @sa QtMvvmApp |
||||
|
*/ |
||||
|
StackView { |
||||
|
id: _presenterStack |
||||
|
|
||||
|
/*! @brief The duration of the default push and pop animations |
||||
|
* |
||||
|
* @default{`150` milliseconds} |
||||
|
* |
||||
|
* You can use this property to speed up or slow down the default animations |
||||
|
* |
||||
|
* @accessors{ |
||||
|
* @memberAc{animDuration} |
||||
|
* @notifyAc{animDurationChanged()} |
||||
|
* } |
||||
|
* |
||||
|
* @sa opDuration |
||||
|
*/ |
||||
|
property int animDuration: 150 |
||||
|
/*! @brief The duration of the fade out |
||||
|
* |
||||
|
* @default{`75` milliseconds} |
||||
|
* |
||||
|
* You can use this property to speed up or slow down the fading part of the push and |
||||
|
* pop animations. |
||||
|
* |
||||
|
* @accessors{ |
||||
|
* @memberAc{opDuration} |
||||
|
* @notifyAc{opDurationChanged()} |
||||
|
* } |
||||
|
* |
||||
|
* @sa animDuration |
||||
|
*/ |
||||
|
property int opDuration: 75 |
||||
|
|
||||
|
//! Internal property |
||||
|
property var _clearItems: [] |
||||
|
|
||||
|
/*! @brief The primary presenting method to present a view |
||||
|
* |
||||
|
* @param type:Item item The item to be presented |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Use this method in your main presenter to present items via this sub presenter. |
||||
|
* |
||||
|
* If the presented item has a boolean property named `presentAsRoot`, the item will |
||||
|
* replace all contents on the stack instead of beeing pushed on it. |
||||
|
* |
||||
|
* @sa QtMvvmApp::presentItem, @ref QtQuick.Item "Item" |
||||
|
*/ |
||||
|
function presentItem(item) { |
||||
|
if(typeof item.presentAsRoot == "boolean" && item.presentAsRoot) { |
||||
|
if(safeReplace(null, item)) |
||||
|
return true; |
||||
|
else |
||||
|
return false; |
||||
|
} else { |
||||
|
if(push(item)) |
||||
|
return true; |
||||
|
else |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*! @brief Can be called to try to close the presenters current top level view |
||||
|
* |
||||
|
* @return type:bool `true` if a view was closed, `false` if not |
||||
|
* |
||||
|
* Use this method in your main presenter react on a close event. It will pop the top |
||||
|
* level view from the stack, if one is present |
||||
|
* |
||||
|
* @sa QtMvvmApp::closeAction |
||||
|
*/ |
||||
|
function closeAction() { |
||||
|
if(_presenterStack.currentItem && |
||||
|
typeof _presenterStack.currentItem.closeAction == "function") { |
||||
|
if(_presenterStack.currentItem.closeAction()) |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if(_presenterStack.safePop()) |
||||
|
return true; |
||||
|
else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*! @brief Pop and delete a view |
||||
|
* |
||||
|
* @param type:Item item an optional item to be popped to |
||||
|
* @param type:int operation How to perform the operation |
||||
|
* @return type:bool `true` if a view was closed, `false` if not |
||||
|
* |
||||
|
* Use this method instead of the @ref QtQuick.Controls.StackView "pop()" method. It will |
||||
|
* not only pop the top level view, but also delete it. This is recommened to do for views |
||||
|
* presented. |
||||
|
* |
||||
|
* @sa PresentingStackView::closeAction, PresentingStackView::safeReplace |
||||
|
*/ |
||||
|
function safePop(item, operation) { |
||||
|
var resItem = pop(item, operation) |
||||
|
if(resItem) { |
||||
|
_clearItems.push(resItem); |
||||
|
return true; |
||||
|
} else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*! @brief replace and delete views |
||||
|
* |
||||
|
* @param type:Item target The new view to be placed on the stack |
||||
|
* @param type:Item item an optional item to be popped to |
||||
|
* @param type:object properties The presentation properties to be passed to the target |
||||
|
* @param type:int operation How to perform the operation |
||||
|
* @return type:bool `true` if the replacement was successful, `false` if not |
||||
|
* |
||||
|
* Use this method instead of the @ref QtQuick.Controls.StackView "replace()" method. It |
||||
|
* will not only replace the replaced views, but also delete them. This is recommened to |
||||
|
* do for views presented. |
||||
|
* |
||||
|
* @sa PresentingStackView::closeAction, PresentingStackView::safePop |
||||
|
*/ |
||||
|
function safeReplace(target, item, properties, operation) { |
||||
|
var items = []; |
||||
|
console.log("current depth: ", depth) |
||||
|
for(var i = depth -1; i >= 0; i--) { |
||||
|
var cItem = get(i, StackView.ForceLoad); |
||||
|
_clearItems.push(cItem); |
||||
|
if(cItem === target) |
||||
|
break; |
||||
|
} |
||||
|
if(replace(target, item, properties, operation)) |
||||
|
return true; |
||||
|
else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
//! Internal method |
||||
|
function clearWaitingItems() { |
||||
|
_clearItems.forEach(function(item) { |
||||
|
if(typeof item.afterPop == "function") |
||||
|
item.afterPop(); |
||||
|
item.destroy(); |
||||
|
}); |
||||
|
_clearItems = []; |
||||
|
} |
||||
|
|
||||
|
pushEnter: Transition { |
||||
|
PropertyAnimation { |
||||
|
property: "y" |
||||
|
easing.type: Easing.InOutQuad |
||||
|
from: height * 0.3 |
||||
|
to: 0 |
||||
|
duration: _presenterStack.animDuration |
||||
|
} |
||||
|
PropertyAnimation { |
||||
|
property: "opacity" |
||||
|
from: 0.0 |
||||
|
to: 1.0 |
||||
|
duration: _presenterStack.opDuration |
||||
|
} |
||||
|
} |
||||
|
pushExit: Transition { |
||||
|
PauseAnimation { |
||||
|
duration: _presenterStack.animDuration |
||||
|
} |
||||
|
|
||||
|
onRunningChanged: { |
||||
|
if(!running) |
||||
|
Qt.callLater(clearWaitingItems) |
||||
|
} |
||||
|
} |
||||
|
popEnter: Transition { |
||||
|
PauseAnimation { |
||||
|
duration: _presenterStack.animDuration |
||||
|
} |
||||
|
} |
||||
|
popExit: Transition { |
||||
|
PropertyAnimation { |
||||
|
property: "y" |
||||
|
easing.type: Easing.InOutQuad |
||||
|
from: 0 |
||||
|
to: height * 0.3 |
||||
|
duration: _presenterStack.animDuration |
||||
|
} |
||||
|
SequentialAnimation { |
||||
|
PauseAnimation { |
||||
|
duration: _presenterStack.animDuration - _presenterStack.opDuration |
||||
|
} |
||||
|
PropertyAnimation { |
||||
|
id: pp1 |
||||
|
property: "opacity" |
||||
|
from: 1.0 |
||||
|
to: 0.0 |
||||
|
duration: _presenterStack.opDuration |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onRunningChanged: { |
||||
|
if(!running) |
||||
|
Qt.callLater(clearWaitingItems) |
||||
|
} |
||||
|
} |
||||
|
replaceEnter: pushEnter |
||||
|
replaceExit: pushExit |
||||
|
} |
@ -0,0 +1,184 @@ |
|||||
|
import QtQuick 2.10 |
||||
|
import QtQuick.Controls 2.3 |
||||
|
import de.skycoder42.QtMvvm.Quick 1.1 |
||||
|
|
||||
|
/*! @brief An application root window that is a full fledged QML presenter |
||||
|
* |
||||
|
* @extends QtQuick.Controls.ApplicationWindow |
||||
|
* |
||||
|
* @details This is the standard presenter you should use in your mvvm application as the root |
||||
|
* QML component of the primary qml file loaded by the engine. It will automatically register |
||||
|
* as the main QML presenter and can handle all the standard view types. |
||||
|
* |
||||
|
* @sa PresenterProgress, PresentingStackView, PresentingDrawer, PopupPresenter, |
||||
|
* DialogPresenter, QuickPresenter |
||||
|
*/ |
||||
|
ApplicationWindow { |
||||
|
id: _root |
||||
|
visible: true |
||||
|
width: 360 |
||||
|
height: 520 |
||||
|
|
||||
|
/*! @brief type:PresentingDrawer A reference to the PresentingDrawer |
||||
|
* |
||||
|
* @default{`null`} |
||||
|
* |
||||
|
* Returns the PresentingDrawer that is beeing used by the app. It is null by default as |
||||
|
* the presenter only gets created the first time a drawer view is beeing shown. From that |
||||
|
* point on, you can access the drawer via this property. |
||||
|
* |
||||
|
* @accessors{ |
||||
|
* @memberAc{drawer} |
||||
|
* @notifyAc{drawerChanged()} |
||||
|
* @readonlyAc |
||||
|
* } |
||||
|
* |
||||
|
* @sa PresentingDrawer, QtMvvmApp::presentDrawerContent, QtMvvmApp::rootOnlyDrawer |
||||
|
*/ |
||||
|
readonly property alias drawer: _drawerLoader.item |
||||
|
/*! @brief Specifies if the drawer can be accessed from the root element only |
||||
|
* |
||||
|
* @default{`true`} |
||||
|
* |
||||
|
* If set to `true`, the presenter can only be accessed by the user if only one view is |
||||
|
* currently presented on the internal PresentingStackView. As soon as second view gets |
||||
|
* pushed, the user cannot open the drawer anymore. By settings it to `false`, the drawer |
||||
|
* will always be accessible on any view on the stack. |
||||
|
* |
||||
|
* @accessors{ |
||||
|
* @memberAc{rootOnlyDrawer} |
||||
|
* @notifyAc{rootOnlyDrawerChanged()} |
||||
|
* } |
||||
|
* |
||||
|
* @sa QtMvvmApp::presentDrawerContent, QtMvvmApp::drawer, QtMvvmApp::presentItem |
||||
|
*/ |
||||
|
property bool rootOnlyDrawer: true |
||||
|
|
||||
|
PresenterProgress { |
||||
|
id: _rootProgress |
||||
|
z: _rootStack.empty ? 10 : -10 |
||||
|
} |
||||
|
|
||||
|
PresentingStackView { |
||||
|
id: _rootStack |
||||
|
anchors.fill: parent |
||||
|
} |
||||
|
|
||||
|
Loader { |
||||
|
id: _drawerLoader |
||||
|
active: false |
||||
|
asynchronous: false |
||||
|
sourceComponent: PresentingDrawer { |
||||
|
id: _rootDrawer |
||||
|
|
||||
|
interactive: !_root.rootOnlyDrawer || _rootStack.depth == 1 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
PopupPresenter { |
||||
|
id: _rootPopup |
||||
|
rootItem: _root.contentItem |
||||
|
} |
||||
|
|
||||
|
DialogPresenter { |
||||
|
id: _rootDialogs |
||||
|
rootItem: _root.contentItem |
||||
|
} |
||||
|
|
||||
|
/*! @brief The presenting method to present a drawer item |
||||
|
* |
||||
|
* @param type:Item item The item to be shown |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Calls PresentingDrawer::presentDrawerContent on the internally used presenting drawer. |
||||
|
* If no drawer has been presented yet, it is automatically created. |
||||
|
* |
||||
|
* @sa PresentingDrawer::presentDrawerContent, QtMvvmApp::drawer, @ref QtQuick.Item "Item" |
||||
|
*/ |
||||
|
function presentDrawerContent(item) { |
||||
|
if(!_drawerLoader.item) |
||||
|
_drawerLoader.active = true; |
||||
|
return _drawerLoader.item.presentDrawerContent(item); |
||||
|
} |
||||
|
|
||||
|
/*! @brief The presenting method to present a view |
||||
|
* |
||||
|
* @param type:Item item The item to be presented |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Calls PresentingStackView::presentItem on the internally used presenting stack view. |
||||
|
* |
||||
|
* @sa PresentingStackView::presentItem, @ref QtQuick.Item "Item" |
||||
|
*/ |
||||
|
function presentItem(item) { |
||||
|
return _rootStack.presentItem(item); |
||||
|
} |
||||
|
|
||||
|
/*! @brief The presenting method to present a popup view |
||||
|
* |
||||
|
* @param type:Popup popup The popup to be presented |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Calls PopupPresenter::presentPopup on the internally used popup presenter. |
||||
|
* |
||||
|
* @sa PopupPresenter::presentPopup, @ref QtQuick.Controls.Popup "Popup" |
||||
|
*/ |
||||
|
function presentPopup(popup) { |
||||
|
return _rootPopup.presentPopup(popup); |
||||
|
} |
||||
|
|
||||
|
/*! @brief The presenting method to present a dialog |
||||
|
* |
||||
|
* @param type:MessageConfig config The message configuration to create a dialog of |
||||
|
* @param type:MessageResult result The result to report the dialog result to |
||||
|
* @return type:bool `true` if successfully presented, `false` if not |
||||
|
* |
||||
|
* Calls DialogPresenter::showDialog on the internally used dialog presenter. |
||||
|
* |
||||
|
* @sa QtMvvm::MessageConfig, QtMvvm::MessageResult, DialogPresenter::showDialog |
||||
|
*/ |
||||
|
function showDialog(config, result) { |
||||
|
return _rootDialogs.showDialog(config, result); |
||||
|
} |
||||
|
|
||||
|
//! @copybrief PresentingDrawer::toggle |
||||
|
function toggleDrawer() { |
||||
|
if(_drawerLoader.item) |
||||
|
_drawerLoader.item.toggle(); |
||||
|
else |
||||
|
console.warn("No drawer like view active. Cannot toggle drawer"); |
||||
|
} |
||||
|
|
||||
|
/*! @brief Can be called to perform a close operation |
||||
|
* |
||||
|
* @return type:bool `true` if anything was closed, `false` if not |
||||
|
* |
||||
|
* Use this method to perform a close operation. The app will automatically check all |
||||
|
* internally used presenter in a logical order and call this method on all of them until |
||||
|
* one returns with a positive result. This way you have a global method to close any kind |
||||
|
* of active view. This is also used to handle window close events and the mobile back |
||||
|
* button. |
||||
|
* |
||||
|
* @sa PopupPresenter::closeAction, DialogPresenter::closeAction, |
||||
|
* PresentingDrawer::closeAction, PresentingStackView::closeAction |
||||
|
*/ |
||||
|
function closeAction() { |
||||
|
var closed = false; |
||||
|
if(!closed) |
||||
|
closed = _rootDialogs.closeAction(); |
||||
|
if(!closed) |
||||
|
closed = _rootPopup.closeAction(); |
||||
|
if(!closed && _drawerLoader.item) |
||||
|
closed = _drawerLoader.item.closeAction(); |
||||
|
if(!closed) |
||||
|
closed = _rootStack.closeAction(); |
||||
|
//if everything was closed -> still accept it |
||||
|
if(closed && _rootDialogs.emtpy && _rootPopup.empty && _rootStack.empty) |
||||
|
closed = false; |
||||
|
return closed; |
||||
|
} |
||||
|
|
||||
|
Component.onCompleted: QuickPresenter.qmlPresenter = _root |
||||
|
|
||||
|
onClosing: close.accepted = !closeAction(); |
||||
|
} |
Loading…
Reference in new issue