Page and PageStack

This commit is contained in:
Marco Martin 2011-10-30 19:47:08 +01:00
parent 3c8ff37491
commit 56dc7f6314
4 changed files with 812 additions and 4 deletions

View File

@ -0,0 +1,123 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Components project.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 1.1
import "." 0.1
Item {
id: root
// The status of the page. One of the following:
// PageStatus.Inactive - the page is not visible
// PageStatus.Activating - the page is transitioning into becoming the active page
// PageStatus.Active - the page is the current active page
// PageStatus.Deactivating - the page is transitioning into becoming inactive
property int status: PageStatus.Inactive
property PageStack pageStack
// Defines orientation lock for a page
property int orientationLock: PageOrientation.Automatic
property Item tools: null
visible: false
width: visible && parent ? parent.width : internal.previousWidth
height: visible && parent ? parent.height : internal.previousHeight
onWidthChanged: internal.previousWidth = visible ? width : internal.previousWidth
onHeightChanged: internal.previousHeight = visible ? height : internal.previousHeight
onStatusChanged: {
if (status == PageStatus.Activating)
internal.orientationLockCheck();
}
onOrientationLockChanged: {
if (status == PageStatus.Activating || status == PageStatus.Active)
internal.orientationLockCheck();
}
// This is needed to make a parentless Page component visible in the Designer of QtCreator.
// It's done here instead of binding the visible property because binding it to a script
// block returning false would cause an element on the Page not to end up focused despite
// specifying focus=true inside the active focus scope. The focus would be gained and lost
// in createObject.
Component.onCompleted: if (!parent) visible = true
QtObject {
id: internal
property int previousWidth: 0
property int previousHeight: 0
function isScreenInPortrait() {
return screen.currentOrientation == Screen.Portrait || screen.currentOrientation == Screen.PortraitInverted;
}
function isScreenInLandscape() {
return screen.currentOrientation == Screen.Landscape || screen.currentOrientation == Screen.LandscapeInverted;
}
function orientationLockCheck() {
switch (orientationLock) {
case PageOrientation.Automatic:
screen.allowedOrientations = Screen.Default
break
case PageOrientation.LockPortrait:
screen.allowedOrientations = Screen.Portrait
break
case PageOrientation.LockLandscape:
screen.allowedOrientations = Screen.Landscape
break
case PageOrientation.LockPrevious:
screen.allowedOrientations = screen.currentOrientation
break
case PageOrientation.Manual:
default:
// Do nothing
// In manual mode it is expected that orientation is set
// explicitly to "screen.allowedOrientations" by the user.
break
}
}
}
}

View File

@ -0,0 +1,229 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Components project.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
// Page stack. Items are page containers.
var pageStack = [];
// Page component cache map. Key is page url, value is page component.
var componentCache = {};
// Returns the page stack depth.
function getDepth() {
return pageStack.length;
}
// Pushes a page on the stack.
function push(page, properties, replace, immediate) {
// page order sanity check
if ((!replace && page == currentPage)
|| (replace && pageStack.length > 1
&& page == pageStack[pageStack.length - 2].page)) {
throw new Error("Cannot navigate so that the resulting page stack has two consecutive entries of the same page instance.");
}
// figure out if more than one page is being pushed
var pages;
if (page instanceof Array) {
pages = page;
page = pages.pop();
if (page.createObject === undefined && page.parent === undefined && typeof page != "string") {
properties = properties || page.properties;
page = page.page;
}
}
// get the current container
var oldContainer = pageStack[pageStack.length - 1];
// pop the old container off the stack if this is a replace
if (oldContainer && replace) {
pageStack.pop();
}
// push any extra defined pages onto the stack
if (pages) {
var i;
for (i = 0; i < pages.length; i++) {
var tPage = pages[i];
var tProps;
if (tPage.createObject === undefined && tPage.parent === undefined && typeof tPage != "string") {
tProps = tPage.properties;
tPage = tPage.page;
}
pageStack.push(initPage(tPage, tProps));
}
}
// initialize the page
var container = initPage(page, properties);
// push the page container onto the stack
pageStack.push(container);
depth = pageStack.length;
currentPage = container.page;
// perform page transition
immediate = immediate || !oldContainer;
var orientationChange = false;
if (oldContainer) {
orientationChange = orientationChanges(oldContainer.page, container.page);
oldContainer.pushExit(replace, immediate, orientationChange);
}
// sync tool bar
var tools = container.page.tools || null;
if (toolBar) {
toolBar.setTools(tools, immediate ? "set" : replace ? "replace" : "push");
}
container.pushEnter(immediate, orientationChange);
return container.page;
}
// Initializes a page and its container.
function initPage(page, properties) {
var container = containerComponent.createObject(root);
var pageComp;
if (page.createObject) {
// page defined as component
pageComp = page;
} else if (typeof page == "string") {
// page defined as string (a url)
pageComp = componentCache[page];
if (!pageComp) {
pageComp = componentCache[page] = Qt.createComponent(page);
}
}
if (pageComp) {
if (pageComp.status == Component.Error) {
throw new Error("Error while loading page: " + pageComp.errorString());
} else {
// instantiate page from component
page = pageComp.createObject(container, properties || {});
}
} else {
// copy properties to the page
for (var prop in properties) {
if (properties.hasOwnProperty(prop)) {
page[prop] = properties[prop];
}
}
}
container.page = page;
container.owner = page.parent;
// the page has to be reparented if
if (page.parent != container) {
page.parent = container;
}
if (page.pageStack !== undefined) {
page.pageStack = root;
}
return container;
}
// Pops a page off the stack.
function pop(page, immediate) {
// make sure there are enough pages in the stack to pop
if (pageStack.length > 1) {
// pop the current container off the stack and get the next container
var oldContainer = pageStack.pop();
var container = pageStack[pageStack.length - 1];
if (page !== undefined) {
// an unwind target has been specified - pop until we find it
while (page != container.page && pageStack.length > 1) {
container.cleanup();
pageStack.pop();
container = pageStack[pageStack.length - 1];
}
}
depth = pageStack.length;
currentPage = container.page;
// perform page transition
var orientationChange = orientationChanges(oldContainer.page, container.page);
oldContainer.popExit(immediate, orientationChange);
container.popEnter(immediate, orientationChange);
// sync tool bar
var tools = container.page.tools || null;
if (toolBar) {
toolBar.setTools(tools, immediate ? "set" : "pop");
}
return oldContainer.page;
} else {
return null;
}
}
// Checks if the orientation changes between oldPage and newPage
function orientationChanges(oldPage, newPage) {
return newPage.orientationLock != PageOrientation.Automatic
&& newPage.orientationLock != PageOrientation.LockPrevious
&& newPage.orientationLock != oldPage.orientationLock
}
// Clears the page stack.
function clear() {
var container;
while (container = pageStack.pop()) {
container.cleanup();
}
depth = 0;
currentPage = null;
}
// Iterates through all pages in the stack (top to bottom) to find a page.
function find(func) {
for (var i = pageStack.length - 1; i >= 0; i--) {
var page = pageStack[i].page;
if (func(page)) {
return page;
}
}
return null;
}

View File

@ -0,0 +1,459 @@
/****************************************************************************
**
** Copyright (C) 2011 Marco Martin <mart@kde.org>
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Components project.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
// The PageStack item defines a container for pages and a stack-based
// navigation model. Pages can be defined as QML items or components.
import QtQuick 1.1
import "." 0.1
import "PageStack.js" as Engine
Item {
id: root
width: parent ? parent.width : 0
height: parent ? parent.height : 0
property int depth: Engine.getDepth()
property Item currentPage: null
property ToolBar toolBar
property variant initialPage
// Indicates whether there is an ongoing page transition.
property bool busy: internal.ongoingTransitionCount > 0
// Pushes a page on the stack.
// The page can be defined as a component, item or string.
// If an item is used then the page will get re-parented.
// If a string is used then it is interpreted as a url that is used to load a page component.
//
// The page can also be given as an array of pages. In this case all those pages will be pushed
// onto the stack. The items in the stack can be components, items or strings just like for single
// pages. Additionally an object can be used, which specifies a page and an optional properties
// property. This can be used to push multiple pages while still giving each of them properties.
// When an array is used the transition animation will only be to the last page.
//
// The properties argument is optional and allows defining a map of properties to set on the page.
// If the immediate argument is true then no transition animation is performed.
// Returns the page instance.
function push(page, properties, immediate)
{
return Engine.push(page, properties, false, immediate);
}
// Pops a page off the stack.
// If page is specified then the stack is unwound to that page, to unwind to the first page specify
// page as null. If the immediate argument is true then no transition animation is performed.
// Returns the page instance that was popped off the stack.
function pop(page, immediate)
{
return Engine.pop(page, immediate);
}
// Replaces a page on the stack.
// See push() for details.
function replace(page, properties, immediate)
{
return Engine.push(page, properties, true, immediate);
}
// Clears the page stack.
function clear()
{
return Engine.clear();
}
// Iterates through all pages (top to bottom) and invokes the specified function.
// If the specified function returns true the search stops and the find function
// returns the page that the iteration stopped at. If the search doesn't result
// in any page being found then null is returned.
function find(func)
{
return Engine.find(func);
}
// Called when the page stack visibility changes.
onVisibleChanged: {
if (currentPage) {
internal.setPageStatus(currentPage, visible ? PageStatus.Active : PageStatus.Inactive);
if (visible)
currentPage.visible = currentPage.parent.visible = true;
}
}
onInitialPageChanged: {
if (initialPage) {
if (depth == 0)
push(initialPage, null, true)
else if (depth == 1)
replace(initialPage, null, true)
else
console.log("Cannot update PageStack.initialPage")
}
}
Component.onCompleted: {
if (initialPage && depth == 0)
push(initialPage, null, true)
}
QtObject {
id: internal
// The number of ongoing transitions.
property int ongoingTransitionCount: 0
// Sets the page status.
function setPageStatus(page, status)
{
if (page != null) {
if (page.status !== undefined) {
if (status == PageStatus.Active && page.status == PageStatus.Inactive)
page.status = PageStatus.Activating;
else if (status == PageStatus.Inactive && page.status == PageStatus.Active)
page.status = PageStatus.Deactivating;
page.status = status;
}
}
}
}
// Component for page containers.
Component {
id: containerComponent
Item {
id: container
width: parent ? parent.width : 0
height: parent ? parent.height : 0
// The states correspond to the different possible positions of the container.
state: "Hidden"
// The page held by this container.
property Item page: null
// The owner of the page.
property Item owner: null
// The width of the longer screen dimension
property int screenWidth: Math.max(screen.width, screen.height)
// Duration of transition animation (in ms)
property int transitionDuration: 250
// Flag that indicates the container should be cleaned up after the transition has ended.
property bool cleanupAfterTransition: false
// Flag that indicates if page transition animation is running
property bool transitionAnimationRunning: false
// State to be set after previous state change animation has finished
property string pendingState: "none"
// Ensures that transition finish actions are executed
// in case the object is destroyed before reaching the
// end state of an ongoing transition
Component.onDestruction: {
if (transitionAnimationRunning)
transitionEnded();
}
// Sets pending state as current if state change is delayed
onTransitionAnimationRunningChanged: {
if (!transitionAnimationRunning && pendingState != "none") {
state = pendingState;
pendingState = "none";
}
}
// Handles state change depening on transition animation status
function setState(newState)
{
if (transitionAnimationRunning)
pendingState = newState;
else
state = newState;
}
// Performs a push enter transition.
function pushEnter(immediate, orientationChanges)
{
if (!immediate) {
if (orientationChanges)
setState("LandscapeRight");
else
setState("Right");
}
setState("");
page.visible = true;
if (root.visible && immediate)
internal.setPageStatus(page, PageStatus.Active);
}
// Performs a push exit transition.
function pushExit(replace, immediate, orientationChanges)
{
if (orientationChanges)
setState(immediate ? "Hidden" : "LandscapeLeft");
else
setState(immediate ? "Hidden" : "Left");
if (root.visible && immediate)
internal.setPageStatus(page, PageStatus.Inactive);
if (replace) {
if (immediate)
cleanup();
else
cleanupAfterTransition = true;
}
}
// Performs a pop enter transition.
function popEnter(immediate, orientationChanges)
{
if (!immediate)
state = orientationChanges ? "LandscapeLeft" : "Left";
setState("");
page.visible = true;
if (root.visible && immediate)
internal.setPageStatus(page, PageStatus.Active);
}
// Performs a pop exit transition.
function popExit(immediate, orientationChanges)
{
if (orientationChanges)
setState(immediate ? "Hidden" : "LandscapeRight");
else
setState(immediate ? "Hidden" : "Right");
if (root.visible && immediate)
internal.setPageStatus(page, PageStatus.Inactive);
if (immediate)
cleanup();
else
cleanupAfterTransition = true;
}
// Called when a transition has started.
function transitionStarted()
{
transitionAnimationRunning = true;
internal.ongoingTransitionCount++;
if (root.visible)
internal.setPageStatus(page, (state == "") ? PageStatus.Activating : PageStatus.Deactivating);
}
// Called when a transition has ended.
function transitionEnded()
{
if (state != "")
state = "Hidden";
if (root.visible)
internal.setPageStatus(page, (state == "") ? PageStatus.Active : PageStatus.Inactive);
internal.ongoingTransitionCount--;
transitionAnimationRunning = false;
if (cleanupAfterTransition)
cleanup();
}
states: [
// Explicit properties for default state.
State {
name: ""
PropertyChanges { target: container; visible: true; opacity: 1 }
},
// Start state for pop entry, end state for push exit.
State {
name: "Left"
PropertyChanges { target: container; x: -width / 2; opacity: 0 }
},
// Start state for pop entry, end state for push exit
// when exiting portrait and entering landscape.
State {
name: "LandscapeLeft"
PropertyChanges { target: container; x: -screenWidth / 2; opacity: 0 }
},
// Start state for push entry, end state for pop exit.
State {
name: "Right"
PropertyChanges { target: container; x: width / 2; opacity: 0 }
},
// Start state for push entry, end state for pop exit
// when exiting portrait and entering landscape.
State {
name: "LandscapeRight"
PropertyChanges { target: container; x: screenWidth / 2; opacity: 0 }
},
// Inactive state.
State {
name: "Hidden"
PropertyChanges { target: container; visible: false }
}
]
transitions: [
// Push exit transition
Transition {
from: ""; to: "Left"
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.InQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
ScriptAction { script: transitionEnded() }
}
},
// Pop entry transition
Transition {
from: "Left"; to: ""
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.OutQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
ScriptAction { script: transitionEnded() }
}
},
// Push exit transition landscape
Transition {
from: ""; to: "LandscapeLeft"
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.InQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
ScriptAction { script: transitionEnded() }
}
},
// Pop entry transition landscape
Transition {
from: "LandscapeLeft"; to: ""
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.OutQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
ScriptAction { script: transitionEnded() }
}
},
// Pop exit transition
Transition {
from: ""; to: "Right"
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.InQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
// Workaround for transition animation bug causing ghost view with page pop transition animation
// TODO: Root cause still unknown
PropertyAnimation {}
ScriptAction { script: transitionEnded() }
}
},
// Push entry transition
Transition {
from: "Right"; to: ""
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.OutQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
ScriptAction { script: transitionEnded() }
}
},
// Pop exit transition landscape
Transition {
from: ""; to: "LandscapeRight"
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.InQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
// Workaround for transition animation bug causing ghost view with page pop transition animation
// TODO: Root cause still unknown
PropertyAnimation {}
ScriptAction { script: transitionEnded() }
}
},
// Push entry transition landscape
Transition {
from: "LandscapeRight"; to: ""
SequentialAnimation {
ScriptAction { script: transitionStarted() }
ParallelAnimation {
PropertyAnimation { properties: "x"; easing.type: Easing.OutQuad; duration: transitionDuration }
PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: transitionDuration }
}
ScriptAction { script: transitionEnded() }
}
}
]
// Cleans up the container and then destroys it.
function cleanup()
{
if (page != null) {
if (page.status == PageStatus.Active)
internal.setPageStatus(page, PageStatus.Inactive);
if (owner != container) {
// container is not the owner of the page - re-parent back to original owner
page.visible = false;
page.parent = owner;
}
}
container.destroy();
}
}
}
}

View File

@ -24,14 +24,11 @@ ToolBar 0.1 ToolBar.qml
ToolButton 0.1 ToolButton.qml
ListItem 0.1 ToolButton.qml
CommonDialog 0.1 CommonDialog.qml
Dialog 0.1 Dialog.qml
QueryDialog 0.1 QueryDialog.qml
SelectionDialog 0.1 SelectionDialog.qml
Page 0.1 Page.qml
PageStack 0.1 PageStack.qml
Window 0.1 Window.qml
TabBar 0.1 TabBar.qml
TabButton 0.1 TabButton.qml
TabGroup 0.1 TabGroup.qml